私はJavaが初めてで、昨夜いくつかのコードを実行していましたが、これは本当に私を悩ませました。forループですべてのX出力を表示する単純なプログラムを作成していて、variable % variable
vs as variable % 5000
またはwhatnot としてモジュラスを使用すると、パフォーマンスが大幅に低下することに気付きました。誰かがなぜこれが原因で何が原因であるかを誰かに説明できますか?だから私はもっと良くなることができます...
ここに「効率的な」コードがあります(ちょっとした構文が間違っていると、コードがインストールされていないコンピューター上にいます)
long startNum = 0;
long stopNum = 1000000000L;
for (long i = startNum; i <= stopNum; i++){
if (i % 50000 == 0) {
System.out.println(i);
}
}
これが「非効率なコード」です
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 50000;
for (long i = startNum; i <= stopNum; i++){
if (i % progressCheck == 0) {
System.out.println(i);
}
}
ちなみに、違いを測定するための日付変数があり、それが十分に長くなると、最初の変数は50ミリ秒かかりましたが、他の変数は12秒かそれに似た時間を要しました。あなたのPCが私のものよりも効率的であるかどうかはstopNum
、増加または減少する必要があるかもしれprogressCheck
ません。
私はこの質問をウェブ上で探しましたが、答えを見つけることができません。たぶん私はそれを正しく尋ねていません。
編集:私の質問がそれほど人気があるとは思っていませんでした。すべての回答に感謝します。所要時間の半分ごとにベンチマークを実行しましたが、非効率的なコードにはかなり長い時間がかかりました。彼らがprintlnを使用していることは確かですが、どちらも同じ量を実行しているので、特に矛盾が繰り返し可能であるため、それが大幅に歪むとは思いません。答えについては、私はJavaを初めて使用するので、今のところどちらの答えが最適かを投票者に決定させます。水曜日までに選んでみます。
EDIT2:今夜、別のテストを行います。ここでは、係数の代わりに変数をインクリメントし、それがprogressCheckに達すると、変数を1つ実行し、その変数を0にリセットします。3番目のオプションです。
EDIT3.5:
私はこのコードを使用しました。以下に結果を示します。すばらしい支援をありがとうございます。また、longのshort値を0と比較してみたので、新しいチェックはすべて「65536」回発生し、繰り返しで等しくなります。
public class Main {
public static void main(String[] args) {
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 65536;
final long finalProgressCheck = 50000;
long date;
// using a fixed value
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if (i % 65536 == 0) {
System.out.println(i);
}
}
long final1 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
//using a variable
for (long i = startNum; i <= stopNum; i++) {
if (i % progressCheck == 0) {
System.out.println(i);
}
}
long final2 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using a final declared variable
for (long i = startNum; i <= stopNum; i++) {
if (i % finalProgressCheck == 0) {
System.out.println(i);
}
}
long final3 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using increments to determine progressCheck
int increment = 0;
for (long i = startNum; i <= stopNum; i++) {
if (increment == 65536) {
System.out.println(i);
increment = 0;
}
increment++;
}
//using a short conversion
long final4 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if ((short)i == 0) {
System.out.println(i);
}
}
long final5 = System.currentTimeMillis() - date;
System.out.println(
"\nfixed = " + final1 + " ms " + "\nvariable = " + final2 + " ms " + "\nfinal variable = " + final3 + " ms " + "\nincrement = " + final4 + " ms" + "\nShort Conversion = " + final5 + " ms");
}
}
結果:
- 固定= 874ミリ秒(通常は約1000ミリ秒ですが、2の累乗であるため高速です)
- 変数= 8590ミリ秒
- 最終変数= 1944ミリ秒(50000を使用した場合は最大1000ミリ秒)
- 増分= 1904ミリ秒
- 短い変換= 679 ms
除算が不足しているため、Short Conversionは「速い」方法より23%高速でした。これは注目に値します。あなたが何かを256回ごとに(またはそこについて)表示または比較する必要がある場合は、これを実行して使用できます
if ((byte)integer == 0) {'Perform progress check code here'}
1つの最後の興味深い注、65536(かなりの数ではない)で「最終宣言された変数」に係数を使用すると、固定値の半分の速度(遅い)でした。以前はほぼ同じ速度でベンチマークを行っていました。
final
前に追加するとprogressCheck
、両方が再び同じ速度で実行されます。これにより、コンパイラまたはJITがループprogressCheck
が一定であることがわかっている場合に、ループを最適化することができます。