سؤال

قرأت أن JVM يخزن داخليا ، عدد صحيح وطول 4 بايت. قرأته من مقال من عام 2000 ، لذلك لا أعرف مدى صحة الأمر الآن.

لأحدث JVMs ، هل هناك أي زيادة في الأداء في استخدام عدد صحيح/طويل؟ وهل تغير هذا الجزء من التنفيذ منذ عام 2000؟

شكرًا

هل كانت مفيدة؟

المحلول

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. قد يكون النوع الطويل كبيرًا جدًا بالنسبة لك ؛ ولكن مرة أخرى كل هذا يتوقف على طلبك.

يجب فقط استخدم قصيرًا إذا كان لديك قلق بشأن المساحة (الذاكرة) باستخدام int (في معظم الحالات). إذا كنت تقوم بإنشاء صفائف وجربها من خلال الإعلان عن صفائف من النوع int واختصار. سوف تستخدم قصيرة 1/2 من الفضاء بدلاً من int. ولكن إذا قمت بإجراء الاختبارات بناءً على السرعة / الأداء ، فسترى فرقًا كبيرًا أو معدومًا (إذا كنت تتعامل مع المصفوفات), ، بالإضافة إلى ذلك ، الشيء الوحيد الذي تحفظه هو الفضاء.

كما ذكر المعلق لفترة طويلة لأن فترة طويلة هي 64 بت. لن تكون قادرًا على تخزين حجم فترة طويلة في 4 بايت (لاحظ نطاق طويل).

نصائح أخرى

يتم تخزين أنواع عدد صحيح في العديد من البايتات ، اعتمادًا على النوع الدقيق:

  • بايت على 8 بت
  • قصير على 16 بت ، وقعت
  • int على 32 بت ، وقعت
  • طويل على 64 بت ، وقعت

انظر المواصفات هنا.

أما بالنسبة للأداء ، فهذا يعتمد على ما تفعله معهم. على سبيل المثال ، إذا كنت تقوم بتعيين قيمة حرفية إلى بايت أو قصير ، فسيتم رفعها إلى INT لأن القيم الحرفية تعتبر INTS افتراضيًا.

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

لذا ، جوابي هو: ذلك يعتمد :)

إنها تفاصيل التنفيذ ، ولكن لا يزال صحيحًا أنه لأسباب الأداء ، ستستخدم معظم JVMs كلمة كاملة (أو أكثر) لكل متغير ، نظرًا لأن ذاكرة الوصول إلى وحدات Word في وحدات الكلمات. إذا قام JVM بتخزين المتغيرات في وحدات ومواقع الكلمات الفرعية ، فسيكون ذلك أبطأ بالفعل.

هذا يعني أن JVM 32bit ستستخدم 4 بايتات لقصير قصير (وحتى منطقية) بينما ستستخدم 64 بت JVM 8 بايت. ومع ذلك ، فإن الشيء نفسه غير صحيح لعناصر الصفيف.

وأنا أتفق مع user2391480 ، يبدو أن الحسابات ذات السراويل القصيرة أكثر تكلفة. فيما يلي مثال ، حيث أن عمليات الجهاز (Java7 64bit و Intel I7-3770 و Windows 7) مع السراويل القصيرة أبطأ حوالي 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;
    }

تعديل: تم تعديله وفقًا لطلب لعق المستخدم الساخن في التعليق ، من أجل استدعاء طريقة حساب () أكثر من مرة خارج الطريقة الرئيسية.

لا يوجد فرق في الأساس. يتعين على المرء أن "يخلط" JITC قليلاً حتى لا يدرك أن عمليات الزيادة/الانخفاض هي إلغاء ذاتي وأن النتائج لا تستخدم. افعل ذلك وتخرج الحالات الثلاث على قدم المساواة. (فعلا، 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)

الحسابات مع نوع قصير مكلفة للغاية.

خذ حلقة عديمة الفائدة التالية على سبيل المثال:

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

إذا كان هذا قصيرًا ، فسيستغرق الأمر حرفيًا 1000 مرة أطول مما لو كان INT أو طويلًا.

فحص على إصدارات JVMS 64 بت 6/7 على Linux

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top