私は、画像の非常に高度な操作を必要とする Java プロジェクトに取り組んでいます。実際、私は OpenCV を使用してほとんどの操作を行っており、JNI を使用して、必要な OpenCV 関数をラップしています。私は OpenCV がもたらすパフォーマンスに非常に満足しています。OpenCV コードを書いた人々は、コードに対して大きな功績を残しました。Java開発者が書いたコードで私が経験したこととは対照的です。
私は自分のプログラミング言語の選択について楽観的に始めました。プロジェクトの最初の作業反復は問題なく動作しましたが、そのパフォーマンスはリアルタイムにはほど遠いものです (2 秒あたり約 1 フレームを取得)。MY コードのいくつかの最適化を行い、それは大いに役立ちました。フレーム レートを 1 秒あたり約 10 ~ 20 フレームまで上げることができました。これは素晴らしいことですが、さらに最適化を行うには、Java コードを書き直して同じことを行う必要があることがわかりました。 -20 倍の効率。
Java の開発者がパフォーマンスにほとんど注意を払っていないことに愕然とします。特にメディア関連のクラスを作成する場合はそうです。OpenJDK をダウンロードし、使用している機能を調べています。たとえば、Raster クラスの下に getPixels(...) という関数があり、画像のピクセルを取得します。私は、この関数がソース コード内で高度に最適化された関数であり、パフォーマンスをさらに最適化するために System.arrayCopy を複数回呼び出すことを期待していました。代わりに、私が見つけたのは非常に「上品な」コードで、1行でできることを達成するために、5〜6の異なるクラスと10〜20の異なるメソッドを呼び出しています。
for (int i =0; i < n; i++) {
long p = rawFrame[i];
p = (p << 32) >>> 32;
byte red = (byte) ((p >> 16) & 0xff);
byte green = (byte) ((p >> 8) & 0xff);
byte blue = (byte) ((p) & 0xff);
byte val = (byte)(0.212671f * red + 0.715160f * green + 0.072169f * blue);
data[i] = val;
grayFrameData[i] = (val & 0x80) + (val & (0x7f));
}
上記のコードは、画像をグレースケールに変換し、約 1 ~ 10 ミリ秒で浮動ピクセル データを取得します。Java 組み込み関数で同じことをしたい場合、グレースケールへの変換自体に 200 ~ 300 ミリ秒かかり、次に float ピクセルを取得するのに約 50 ~ 100 ミリ秒かかります。これは、リアルタイムのパフォーマンスには受け入れられません。速度を上げるために注意してください。私は、Java 開発者が敬遠するビット単位の演算子を多用しています。
一般的なケースを処理する必要があることは理解していますが、それでも、少なくとも最適化のオプションを提供したり、少なくともこのコードの実行速度がどれほど遅いかを警告したりすることはできません。
私の質問は、開発のこの後半の時点で (私はすでに最初のイテレーションを持っていますが、リアルタイムでより多くのパフォーマンスを発揮する 2 番目のイテレーションに取り組んでいるわけではありません)、弾丸を噛んで C/C++ に切り替える必要があります。もっと調整するか、Java に固執して、スピードアップのために既に実装されている Java コードを書き直す必要がないように、物事がよりリアルタイムに適したものになることを願っています。
Java がいかに「上品」で遅いかということに、私は本当にうんざりし始めています。そこにあるクラスの量は、やり過ぎのようです。