13

私は、JVMが内部的にshort、integer、およびlongを4バイト格納することを読みました。2000年の記事から読んだので、今がどれだけ真実かわかりません。

新しいJVMの場合、整数/整数よりも短いものを使用することでパフォーマンスが向上しますか?そして、実装のその部分は2000年以降変更されましたか?

ありがとう

4

6 に答える 6

15

整数型は、正確な型に応じて、多くのバイトに格納されます。

  • 8ビットのバイト
  • 16ビットが不足している、署名されている
  • 32ビットのint、符号付き
  • 64ビットで長い、署名済み

こちらの仕様をご覧ください。

パフォーマンスに関しては、それはあなたが彼らと何をしているかに依存します。たとえば、リテラル値をバイトまたはショートに割り当てる場合、リテラル値はデフォルトでintと見なされるため、intにアップスケールされます。

byte b = 10;  // upscaled to int, because "10" is an int

それがあなたができない理由です:

byte b = 10;
b = b + 1;  // Error, right member converted to int, cannot be reassigned to byte without a cast.

したがって、バイトまたはショートを使用してループを実行することを計画している場合、何も得られません。

for (byte b=0; b<10; b++) 
{ ... } 

一方、一部のデータを格納するためにバイトまたはショートの配列を使用している場合は、サイズを小さくすることで明らかにメリットが得られます。

byte[] bytes = new byte[1000];
int[] ints = new int[1000];  // 4X the size

だから、私の答えは:それは依存します:)

于 2010-03-04T16:11:49.467 に答える
13
long  64 –9,223,372,036,854,775,808 to 9 ,223,372,036,854,775,807 
int   32 –2,147,483,648 to 2,147,483,647 
short 16 –32,768 to 32,767 
byte   8 –128 to 127 

必要なものを使用してください。範囲が狭いため、ショートパンツはめったに使用されず、ビッグエンディアン形式であると思います。

パフォーマンスの向上は最小限ですが、先ほど述べたように、アプリケーションでintを使用した場合の範囲よりも広い範囲が必要な場合は、長いタイプは、あなたには極端に大きすぎるかもしれません。しかし、繰り返しますが、それはすべてアプリケーションによって異なります。

スペース(メモリ)に懸念がある場合にのみshortを使用する必要があります。それ以外の場合は、intを使用します(ほとんどの場合)。配列などを作成している場合は、int型とshort型の配列を宣言して試してみてください。Shortは、intではなく1/2のスペースを使用します。ただし、速度/パフォーマンスに基づいてテストを実行すると、違いはほとんどまたはまったくわかりません(アレイを扱っている場合)。さらに、節約できるのはスペースだけです。

また、longは64ビットであるため、コメント投稿者がlongについて言及していることもあります。longのサイズを4バイトに格納することはできません(longの範囲に注意してください)。

于 2010-03-04T16:07:56.227 に答える
8

これは実装の詳細ですが、CPUはワード単位でメモリにアクセスするため、パフォーマンス上の理由から、ほとんどのJVMは各変数にフルワード(またはそれ以上)を使用することは事実です。JVMが変数をサブワード単位と場所に格納した場合、実際には遅くなります。

これは、32ビットJVMが短い(さらにはブール値)ために4バイトを使用するのに対し、64ビットJVMは8バイトを使用することを意味します。ただし、配列要素については同じではありません。

于 2010-03-04T16:15:52.203 に答える
1

基本的に違いはありません。JITCを少し「混乱」させて、インクリメント/デクリメント操作が自己キャンセルであり、結果が使用されないことを認識しないようにする必要があります。そうすれば、3つのケースはほぼ同じになります。(実際には、short少し速いようです。)

public class ShortTest {

    public static void main(String[] args){
        // Do the inner method 5 times to see how it changes as the JITC attempts to
        // do further optimizations.
        for (int i = 0; i < 5; i++) {
            calculate(i);
        }
    }

    public static void calculate(int passNum){

        System.out.println("Pass " + passNum);
        // Broke into two (nested) loop counters so the total number of iterations could
        // be large enough to be seen on the clock.  (Though this isn't as important when
        // the JITC over-optimizations are prevented.)
        int M = 100000;
        int N = 100000;
        java.util.Random r = new java.util.Random();
        short x = (short) r.nextInt(1);
        short y1 = (short) (x + 1);
        int y2 = x + 1;
        long y3 = x + 1;

        long time1=System.currentTimeMillis();
        short s=x;
        for (int j = 0; j<M;j++) {
            for(int i = 0; i<N;i++) {
                s+=y1;
                s-=1;
                if (s > 100) {
                    System.out.println("Shouldn't be here");
                }
            }
        }
        long time2=System.currentTimeMillis();
        System.out.println("Time elapsed for shorts: "+(time2-time1) + " (" + time1 + "," + time2 + ")");


        long time3=System.currentTimeMillis();
        int in=x;
        for (int j = 0; j<M;j++) {
            for(int i = 0; i<N;i++) {
                in+=y2;
                in-=1;
                if (in > 100) {
                    System.out.println("Shouldn't be here");
                }
            }
        }
        long time4=System.currentTimeMillis();
        System.out.println("Time elapsed for ints: "+(time4-time3) + " (" + time3 + "," + time4 + ")");


        long time5=System.currentTimeMillis();
        long l=x;
        for (int j = 0; j<M;j++) {
            for(int i = 0; i<N;i++) {
                l+=y3;
                l-=1;
                if (l > 100) {
                    System.out.println("Shouldn't be here");
                }
            }
        }
        long time6=System.currentTimeMillis();
        System.out.println("Time elapsed for longs: "+(time6-time5) + " (" + time5 + "," + time6 + ")");


        System.out.println(s+in+l);
    }
}

結果:

C:\JavaTools>java ShortTest
Pass 0
Time elapsed for shorts: 59119 (1422405830404,1422405889523)
Time elapsed for ints: 45810 (1422405889524,1422405935334)
Time elapsed for longs: 47840 (1422405935335,1422405983175)
0
Pass 1
Time elapsed for shorts: 58258 (1422405983176,1422406041434)
Time elapsed for ints: 45607 (1422406041435,1422406087042)
Time elapsed for longs: 46635 (1422406087043,1422406133678)
0
Pass 2
Time elapsed for shorts: 31822 (1422406133679,1422406165501)
Time elapsed for ints: 39663 (1422406165502,1422406205165)
Time elapsed for longs: 37232 (1422406205165,1422406242397)
0
Pass 3
Time elapsed for shorts: 30392 (1422406242398,1422406272790)
Time elapsed for ints: 37949 (1422406272791,1422406310740)
Time elapsed for longs: 37634 (1422406310741,1422406348375)
0
Pass 4
Time elapsed for shorts: 31303 (1422406348376,1422406379679)
Time elapsed for ints: 36583 (1422406379680,1422406416263)
Time elapsed for longs: 38730 (1422406416264,1422406454994)
0

C:\JavaTools>java -version
java version "1.7.0_65"
Java(TM) SE Runtime Environment (build 1.7.0_65-b19)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
于 2015-01-28T00:57:02.163 に答える
0

user2391480に同意します。ショートパンツを使用した計算は、はるかに高価なようです。これが例です。私のマシン(Java7 64ビット、Intel i7-3770、Windows 7)では、shortを使用した操作は整数やlongよりも約50倍遅くなります。

public class ShortTest {

public static void main(String[] args){
    calculate();
    calculate();
}

public static void calculate(){
    int N = 100000000;

    long time1=System.currentTimeMillis();
    short s=0;
    for(int i = 0; i<N;i++) {
        s+=1;
        s-=1;
    }
    long time2=System.currentTimeMillis();
    System.out.println("Time elapsed for shorts: "+(time2-time1));


    long time3=System.currentTimeMillis();
    int in=0;
    for(int i = 0; i<N;i++) {
        in+=1;
        in-=1;
    }
    long time4=System.currentTimeMillis();
    System.out.println("Time elapsed for ints: "+(time4-time3));


    long time5=System.currentTimeMillis();
    long l=0;
    for(int i = 0; i<N;i++) {
        l+=1;
        l-=1;
    }
    long time6=System.currentTimeMillis();
    System.out.println("Time elapsed for longs: "+(time6-time5));


    System.out.println(s+in+l);
}

}

出力:

Time elapsed for shorts: 113
Time elapsed for ints: 2
Time elapsed for longs: 2
0
Time elapsed for shorts: 119
Time elapsed for ints: 2
Time elapsed for longs: 2
0

注:「1」を短く指定することは(ユーザーRobotnikが遅延の原因として提案しているように、毎回キャストを回避するために)役に立たないようです。

    short s=0;
    short one = (short)1;
    for(int i = 0; i<N;i++) {
      s+=one;
      s-=one;
    }

編集:メインメソッドの外部でcalculate()メソッドを複数回呼び出すために、コメント内のユーザーHotLicksの要求に従って変更されました。

于 2015-01-27T22:07:52.807 に答える
-2

短いタイプでの計算は非常に高価です。

たとえば、次の役に立たないループを考えてみましょう。

short t=0;
//int t=0;
//long t=0;
for(many many times...)
{
  t+=1;
  t-=1;
}

短い場合は、intまたはlongの場合よりも文字通り数千倍長くかかります。

Linux上の64ビットJVMバージョン6/7でチェック

于 2013-11-05T18:30:13.987 に答える