سؤال

خطرت لي فكرة تحويل بعض كتل if الخاصة بي إلى أسطر مفردة، باستخدام العامل الشرطي.ومع ذلك، كنت أتساءل عما إذا كان سيكون هناك تناقض في السرعة.قمت بإجراء الاختبار التالي:

static long startTime;
static long elapsedTime;
static String s;

public static void main(String[] args) {
    startTime = System.nanoTime();
    s = "";
    for (int i= 0; i < 1000000000; i++) {
        if (s.equals("")) {
            s = "";
        }
    }

    elapsedTime = System.nanoTime() - startTime;

    System.out.println("Type 1 took this long: " + elapsedTime + " ns");

    startTime = System.nanoTime();
    s = "";
    for (int i= 0; i < 1000000000; i++) {
        s = (s.equals("") ? "" : s);
    }

    elapsedTime = System.nanoTime() - startTime;

    System.out.println("Type 2 took this long: " + elapsedTime + " ns");
}

هذه هي نتيجتي:

استغرق النوع 1 وقتًا طويلاً:3293937157 ن.س

استغرق النوع 2 هذا الوقت الطويل:2856769127 ن.س

أفعل شيئا خطأ هنا؟

على افتراض s.equals("") هذا صحيح بالضرورة، هل هذه طريقة فعالة لجعل التعليمات البرمجية الخاصة بك أسرع؟

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

المحلول

تحتوي الإجابات الأخرى على معلومات مفيدة ذات صلة ولكن لا يتناول أي منها المشكلة حقيقي سؤال ما إذا كان النموذج الأول أكثر كفاءة من النموذج الثاني.

لا يوفر هذا القياس نتائج موثوقة لأنه لم يتم إجراؤه بشكل صحيح:إحدى "القواعد الأساسية" المهمة في قياس كود Java هي توفير عملية إحماء.في هذه الحالة، توفر الحلقة الأولى عملية إحماء للحلقة الثانية.

هذه الإجابة يوفر تعليمات إضافية لقياس الأداء الدقيق بالإضافة إلى بعض الروابط المفيدة.

نصائح أخرى

, is this a viable way to make your code faster?

يمكنك حتى أن تجعل الأمر أسرع إذا كان لديك String s; هو حقل غير ثابت.الحقل الثابت أبطأ من الحقل غير الثابت عندما تكون كذلك referencing ذلك مليار مرة

public static void main(String[] args) {

    startTime = System.nanoTime();
    String s = "";
    .
    .
}

يحرر:

لماذا هو أسرع؟؟

ويرجع ذلك إلى إشارة السلسلة إلى الحقل الثابت.

يمكنك رؤيته في رمز البايت الخاص به

    0: ldc           #23                 // String
       2: putstatic     #25                 // Field s:Ljava/lang/String;
       5: iconst_0
       6: istore_1
       7: goto          22
      10: getstatic     #25                 // Field s:Ljava/lang/String;
      13: ldc           #23                 // String
      15: invokevirtual #27                 // Method java/lang/String.equals:(L
java/lang/Object;)Z
      18: pop
      19: iinc          1, 1
      22: iload_1
      23: ldc           #33                 // int 1000000000
      25: if_icmplt     10
      28: return

كما ترون getStatic و putStatic سيتم استدعاؤه مليار مرة، ما يفعله هو أنه سيتم استدعاء مرجع الحقل الثابت ووضع مرجع السلسلة باستخدام putStatic

com.getStatic - الحصول على قيمة حقل ثابتة للفئة، حيث يتم تحديد الحقل من خلال مرجع الحقل في فهرس التجمع الثابت (الفهرس1 << 8 + الفهرس2)

putStatic - تعيين حقل ثابت إلى قيمة في فئة، حيث يتم تحديد الحقل من خلال فهرس مرجعي للحقل في تجمع ثابت (indexbyte1 << 8 + Indexbyte2)

انظر تلك تحول قليلا وهذا هو سبب بطء البرنامج

أيضًا إذا كنت تستخدم أ global/member field سوف يخلق نفس الشيء bytecode ولكن بدلا من ذلك سوف تستخدمgetfield و putfield وهو نفس ثابت getStatic و putStatic

الآن دعونا نرى non static field bytecode

      0: ldc           #21                 // String
       2: astore_1
       3: iconst_0
       4: istore_2
       5: goto          23
       8: aload_1
       9: ldc           #21                 // String
      11: invokevirtual #23                 // Method java/lang/String.equals:(L
java/lang/Object;)Z
      14: ifeq          20
      17: ldc           #21                 // String
      19: astore_1
      20: iinc          2, 1
      23: iload_2
      24: ldc           #29                 // int 1000000000
      26: if_icmplt     8
      29: return

كما ترون فإنه يستخدم فقط astore_1 و aload_1 لحفظ وتحميل مرجع الحقل غير الثابت دون عملية إضافية.

هذه الرائحة تشبه التحسين المبكر بالنسبة لي.إذا كنت لا تزال تنوي إجراء اختبار دقيق لكلا التطبيقين بهذه الطريقة، أقترح استخدام isEmpty() بدلاً من ذلك نظرًا لأن الكود الأساسي لذلك أكثر وضوحًا مقارنة بـ equals().أعني بذلك أن أي تحسين سيفعله المترجم/JVM لك سيكون أقل احتمالًا بسبب ما يحدث في equals(), ، وأكثر انعكاسًا لأي فوائد دقيقة يتمتع بها أحد التطبيقات على الآخر، على افتراض أن ذلك مهم حقًا.

يجب أن تكون سهولة القراءة هي القاعدة الأفضل بالنسبة لك لتقرر ما إذا كنت تريد استخدامها if-else أو ? :.

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