C++の#ifdef #ifndefのようなJavaのようなコンパイル時の条件を作成する方法があるかどうか疑問です。
私の問題は、Javaで記述されたアルゴリズムを使用していることと、そのアルゴリズムの実行時間が異なることです。そのため、各改善を使用するときにどれだけの時間を節約できるかを測定したいと思います。
現在、実行時に改善すべきものとそうでないものを決定するために使用されるブール変数のセットがあります。しかし、これらの変数をテストすることでさえ、総実行時間に影響を与えます。
そこで、コンパイル時にプログラムのどの部分をコンパイルして使用するかを決定する方法を見つけたいと思います。
誰かがJavaでそれを行う方法を知っていますか?あるいは、そのような方法がないことを誰かが知っているかもしれません(それも有用です)。
private static final boolean enableFast = false;
// ...
if (enableFast) {
// This is removed at compile time
}
上記のような条件は、コンパイル時に評価されます。代わりにこれを使用する場合
private static final boolean enableFast = "true".equals(System.getProperty("fast"));
次に、enableFastに依存する条件がJITコンパイラーによって評価されます。このためのオーバーヘッドは無視できます。
javacは、到達不能のコンパイル済みコードを出力しません。 #define
の定数値に設定された最終変数と、#ifdef
の通常のif
ステートメントを使用します。
Javapを使用して、到達不能コードが出力クラスファイルに含まれていないことを証明できます。たとえば、次のコードを考えます。
public class Test
{
private static final boolean debug = false;
public static void main(String[] args)
{
if (debug)
{
System.out.println("debug was enabled");
}
else
{
System.out.println("debug was not enabled");
}
}
}
javap -c Test
は次の出力を提供し、2つのパスのうち1つだけがコンパイルされたことを示します(ifステートメントはコンパイルされませんでした)。
public static void main(Java.lang.String[]);
Code:
0: getstatic #2; //Field Java/lang/System.out:Ljava/io/PrintStream;
3: ldc #3; //String debug was not enabled
5: invokevirtual #4; //Method Java/io/PrintStream.println:(Ljava/lang/String;)V
8: return
私は解決策を見つけたと思う、それははるかに簡単です。
「最終」修飾子でブール変数を定義すると、Javaコンパイラー自体が問題を解決します。この条件をテストした結果が事前にわかっているためです。コード:
boolean flag1 = true;
boolean flag2 = false;
int j=0;
for(int i=0;i<1000000000;i++){
if(flag1)
if(flag2)
j++;
else
j++;
else
if(flag2)
j++;
else
j++;
}
コンピューターで約3秒実行します。
そしてこれ
final boolean flag1 = true;
final boolean flag2 = false;
int j=0;
for(int i=0;i<1000000000;i++){
if(flag1)
if(flag2)
j++;
else
j++;
else
if(flag2)
j++;
else
j++;
}
約1秒実行されます。このコードにかかる時間
int j=0;
for(int i=0;i<1000000000;i++){
j++;
}
使用したことはありませんが、これは存在します
JCPPは完全な、準拠した、スタンドアロンの、純粋なJava Cプリプロセッサの実装です。これは、CスタイルのコンパイラをJava = sablecc、antlr、JLex、CUPなどのツールを使用します。このプロジェクトは、GNU Cライブラリのバージョン1.2.5以降のソースコードの多くを正常に前処理するために使用されています。 、Apple Objective Cライブラリ。
本当に条件付きコンパイルが必要で、Antを使用する場合は、コードをフィルター処理して、検索と置換を実行できる場合があります。
例: http://weblogs.Java.net/blog/schaefa/archive/2005/01/how_to_do_condi.html
同じ方法で、たとえば、LOG.debug(...);
を/*LOG.debug(...);*/
に置き換えるフィルターを作成できます。これは、同時により簡潔であることは言うまでもなく、if (LOG.isDebugEnabled()) { ... }
のものよりも高速に実行されます。
Mavenを使用する場合、here。
Manifold は、完全に統合されたJavaプリプロセッサ(ビルドステップまたは生成されたソースなし)を提供します。条件付きコンパイルのみを対象とし、Cスタイルのディレクティブを使用します。
Factoryパターンを使用して、クラスの実装を切り替えますか?
オブジェクトの作成時間は今では気になりませんか?長い実行期間にわたって平均すると、費やされる時間の最大の要素はメインアルゴリズムにあるはずです。
厳密に言えば、あなたが達成しようとしていることをするのにプリプロセッサは本当に必要ありません。もちろん、私が提案したもの以外にも、おそらく他の方法で要件を満たすことができます。
final static int appFlags = context.getApplicationInfo().flags;
final static boolean isDebug = (appFlags & ApplicationInfo.FLAG_DEBUGGABLE) != 0