سؤال

لماذا هو الجزء الثاني من الكود أسرع؟

Map<Integer, Double> map = new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {
        map.put(i, j);
    }
}

Map<Integer, Double> map=new HashMap<Integer, Double>();
for (int i = 0; i < 50000; i++) {
    for (double j = 0.0; j < 10000; j++) {            
        map.put(new Integer(i), new Double(j));
    }
}
هل كانت مفيدة؟

المحلول

استخدامات Autoboxing Integer.valueOf, ، والتي تتخبط داخليًا كائنات عدد صحيح للأعداد الصحيحة الصغيرة (افتراضيًا من -128 إلى 127 ، ولكن يمكن تكوين القيمة القصوى باستخدام "java.lang.integer.integercache.high" - انظر رمز المصدر لـ integer.valueof) ، لذلك يختلف عن الاتصال new Integer مباشرة. لان Integer.valueOf هل تحقق سريعًا لحجم قيمة عدد صحيح قبل الاتصال new Integer, ، إنه أسرع قليلاً للاتصال new Integer مباشرة (على الرغم من أنه يستخدم المزيد من الذاكرة إذا كان لديك الكثير من الأعداد الصحيحة الصغيرة). التخصيص في Java سريع للغاية ، والوقت الذي يقوم به GC يتناسب مع عدد الكائنات الحية قصيرة الأجل (أي لا تتناسب مع كمية القمامة) ، لذلك GC أيضًا سريع جدًا.

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

في إصدارات JVM الحديثة هناك استبدال العددية التحسين (باستثناء 1.6.0_18 حيث يكون تحليل الهروب موقوف مؤقتا) ، مما يعني أنه يمكن تحسين تخصيصات الكائنات قصيرة العمر. عندما كان استبدال العددية في JVM جديدًا ، صنع شخص ما معيار حيث كان هناك رمز مشابه لك. وكانت النتيجة أن الرمز الذي استخدم البدائية كان أسرع ، الرمز مع صريح new Integer() كانت المكالمات بأسرع ما يقرب من تلك التي تستخدم البدائية ، وكان الكود الذي استخدم autoboxing أبطأ بكثير. كان هذا لأن استخدامات Autoboxing Integer.valueOf وعلى الأقل في ذلك الوقت ، لم يأخذ تحسين استبدال العددية هذه الحالة الخاصة في الاعتبار. لا أعرف ما إذا كان قد تم تحسين التحسين منذ ذلك الحين.

نصائح أخرى

سوف Autoboxing استخدام Integer.valueOf و Double.valueOf. هناك بعض النفقات العامة في استدعاء هذه الأساليب (على الرغم من أنها ستتحمل في النهاية). ايضا Integer.valueOf هل يقوم البعض بفحص القيم المنخفضة لاستخدام مثيلات مجمعة ، وهو ما لا يمثل فوزًا في الكود الخاص بك بشكل متكرر (على الرغم من أنه قد يقلل من حجم الكومة قليلاً). قد تكون الحالات المجمعة فوزًا حيث تقلل من حجم الكومة ، وأوقات GC ويمكنها حتى تحسين أداء اختبار المساواة ..

ولكن ، بشكل عام ، إنه عبارة عن ميكروبتيم يجب أن تتجاهله بشكل عام.

لأن نتائج علامات Microbenchmbles غير موثوقة؟

أيضًا ، يتم التزام التلقائي باستخدام integer.valueof () و double.valueof () ، وليس المُنشئين.

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