
بالنسبة إلى التحسينات الدقيقة لـ PHP ، من خلال استبدال علامات الاقتباس المزدوجة بعلامات اقتباس مفردة ، يتم كسر العديد من النسخ بحيث يكون من الصعب للغاية إنشاء جدول جديد. ولكن سأحاول.
في هذه المقالة ، سيكون هناك معيار واحد فقط ، حيث سيكون بدونه ، ويتم التركيز بشكل رئيسي على تحليل كيفية ترتيبه بالداخل.
تنصل
- كل ما هو موضح أدناه هو ، بالنسبة للجزء الأكبر ، توفير على نانوثانية ، ومن الناحية العملية ، لن يفعل شيئًا سوى خسارة الوقت الضائع في مثل هذا التحليل المصغر. هذا ينطبق بشكل خاص على "تحسينات" من وقت الترجمة.
- سأقطع الكود والإخراج إلى أقصى حد ، ولم يتبق منه سوى الجوهر.
- عند كتابة مقال ، استخدمت PHP 7.2
التمهيدية اللازمة
تتم معالجة سلسلة في علامات اقتباس مزدوجة
في مرحلة الترجمة بشكل مختلف قليلاً عن سلسلة في علامات اقتباس مفردة.
سيتم تحليل اقتباسات مفردة مثل هذا:
statement -> expr -> scalar -> dereferencable_scalar -> T_CONSTANT_ENCAPSED_STRING
مضاعفة جدا:
statement -> expr -> scalar -> '"' encaps_list '"' -> , ,
في المقالات المتعلقة بـ microoptimizations لـ PHP ، هناك نصيحة غالبًا بعدم استخدام
الطباعة ، لأنها أبطأ من
الصدى . دعونا نرى كيف يتم فرزها.
تحليل
الصدى :
statement -> T_ECHO echo_expr_list -> echo_expr_list -> echo_expr -> expr
تحليل
الطباعة :
statement -> expr -> T_PRINT expr -> expr ( )
أي بشكل عام ، نعم ،
تم اكتشاف
الصدى خطوة مبكرة وهذه الخطوة ، تجدر الإشارة ، صعبة للغاية.
من أجل عدم زيادة الانتباه مرة أخرى أثناء المقال ، سنضع في اعتبارنا أن علامات الاقتباس المزدوجة في مرحلة الترجمة تفقد واحدة ، ويفقد
صدى الطباعة . أيضًا ، دعونا لا ننسى أنه في أسوأ الحالات ، يتعلق الأمر بالنانو ثانية.
حسنا ، حتى لا يستيقظ مرتين. فيما يلي وظائف الاختلاف التي تجمع
الطباعة والصدى :
1 - void zend_compile_print(znode *result, zend_ast *ast) 1 + void zend_compile_echo(zend_ast *ast) 2 2 { 3 3 zend_op *opline; 4 4 zend_ast *expr_ast = ast->child[0]; 5 5 6 6 znode expr_node; 7 7 zend_compile_expr(&expr_node, expr_ast); 8 8 9 9 opline = zend_emit_op(NULL, ZEND_ECHO, &expr_node, NULL); 10 - opline->extended_value = 1; 11 - 12 - result->op_type = IS_CONST; 13 - ZVAL_LONG(&result->u.constant, 1); 10 + opline->extended_value = 0; 14 11 }
حسنًا ، أنت تفهم - أنها متطابقة في الوظائف ، ولكن
الطباعة تُرجع أيضًا ثابتًا يساوي 1. أعتقد أن هذا الموضوع مع
الطباعة يمكنك إغلاقه ونسيانه إلى الأبد.
خط بسيط ، دون زخرفة
سلاسل
echo 'Some string';
echo "Some string";
سيتم تقسيم متطابقة تقريبا إلى 2 (إخلاء مسؤولية P2) الرموز.
T_ECHO: echo T_ENCAPSED_AND_WHITESPACE/T_CONSTANT_ENCAPSED_STRING: "Some string"
علاوة على ذلك ، بالنسبة إلى علامات الاقتباس المفردة ، سيكون هناك دائمًا T_CONSTANT_ENCAPSED_STRING ، وللحصول على علامات اقتباس مزدوجة ، عندما يكون الأمر كذلك. إذا كان هناك مسافة في السطر ، فقم T_ENCAPSED_AND_WHITESPACE.
ستكون رموز شفرة التشغيل بسيطة ومشوهة تمامًا:
line
النتائج
إذا كنت ترغب في حفظ بضع دورات للمعالج في مرحلة الترجمة ، فاستعمل علامات الاقتباس المفردة للسلاسل الثابتة.
خط ديناميكي
هناك 4 خيارات.
echo "Hello $name! Have a nice day!"; echo 'Hello '.$name.'! Have a nice day!'; echo 'Hello ', $name, '! Have a nice day!'; printf ('Hello %s! Have a nice day!', $name);
للخيار الأول:
T_ECHO: echo T_ENCAPSED_AND_WHITESPACE: Hello T_VARIABLE: $name T_ENCAPSED_AND_WHITESPACE: ! Have a nice day!
للثانية (للثالثة أيضًا ، فقط بدلاً من الفترات ستكون هناك فواصل):
T_ECHO: echo T_CONSTANT_ENCAPSED_STRING: 'Hello ' string: . T_VARIABLE: $name string: . T_CONSTANT_ENCAPSED_STRING: '! Have a nice day!'
للرابع:
T_STRING: printf T_CONSTANT_ENCAPSED_STRING: 'Hello %s! Have a nice day!' string: , T_VARIABLE: $name
ولكن مع opcodes سيكون كل شيء أكثر تسلية.
أول واحد:
echo "Hello $name! Have a nice day!"; line
الثانية:
echo 'Hello '.$name.'! Have a nice day!'; line
الثالث:
echo 'Hello ', $name, '! Have a nice day!'; line
الرابع:
printf ('Hello %s! Have a nice day!', $name); line
يخبرنا الفطرة السليمة أن الخيار "printf" سوف يفقد سرعته من خلال الثلاثة الأولى (خاصة أنه في النهاية لا يزال هناك نفس ECHO) ، لذلك سنتركه للمهام التي تتطلب التنسيق ولن نتذكر المزيد في هذه المقالة.
يبدو أن الخيار الثالث هو الأسرع - لطباعة ثلاثة أسطر متتالية دون تسلسل ، و ROPE غريبة وإنشاء متغيرات إضافية. لكن ليس بهذه البساطة. من المؤكد أن وظيفة الطباعة في PHP ليست هي Rocket Science ، ولكنها ليست بأي حال من الأحوال نواتج C-shny عادية. من
يهتم -
تنكشف الكرة بدءًا من
php_output_write في
الملف الرئيسي / output.c .
CONCAT. كل شيء بسيط هنا - نقوم بتحويل الحجج إلى سلاسل ، إذا لزم الأمر ،
وننشئ سلسلة جديدة باستخدام
memcpy سريع. السلبية الوحيدة هي أنه مع وجود سلسلة طويلة من السلاسل لكل عملية ، سيتم إنشاء خطوط جديدة عن طريق نقل نفس البايتات من مكان إلى آخر.
ولكن مع ROPE_INIT و ROPE_ADD و ROPE_END ، كل شيء أكثر إثارة للاهتمام. اتبع اليدين:
- ROPE_INIT (تحويلة = 3 ، عائد = ~ 3 ، معاملات = "Hello +")
نحن نخصص "الحبل" من ثلاث فتحات (تحويلة) ، ونضع السلسلة "Hello +" (المعاملات) في الفتحة 0 ونعيد المتغير المؤقت ~ 3 (الرجوع) الذي يحتوي على "الحبل". - ROPE_ADD (تحويلة = 1 ، عائد = ~ 3 ، معاملات = ~ 3 ،! 0)
نضع في الفتحة 1 (تحويلة) من "الحبل" ~ 3 (المعاملات) السلسلة "Vasya" ، التي تم الحصول عليها من المتغير! 0 (المعاملات) وإرجاع "الحبل" ~ 3 (العودة). - ROPE_END (تحويلة = 2 ، عائد = ~ 2 ، معاملات = ~ 3 ، '٪ 21 + لديك + + + لطيفة + يوم٪ 21')
نضع السطر '٪ 21 + Have + a + nice + day٪ 21' (المعاملات) في الفتحة 2 (ext) ، ثم نقوم بإنشاء سلسلة متدرجة بالحجم المطلوب وانسخ كل فتحات "الحبل" فيه بالتناوب مع memcpy نفسه.
بشكل منفصل ، تجدر الإشارة إلى أنه في حالة الثوابت والمتغيرات المؤقتة ، سيتم وضع روابط البيانات في الفتحات ، ولن يكون هناك نسخ غير ضرورية.
في رأيي ، أنيقة جدا. :)
دعونا المعيار. كبيانات مصدر ، نأخذ الملف
zend_vm_execute.h (IMHO سيكون هذا صحيحًا) لـ 71 ألف سطر وطباعته في 100 طريقة لـ 100 مرور ، مع إسقاط الحد الأدنى والحد الأقصى (بدأ كل قياس 10 مرات ، واختر الخيار الأكثر شيوعًا):
<?php $file = explode("\n", file_get_contents("C:\projects\C\php-src\Zend\zend_vm_execute.h")); $out = []; for ($c = 0; $c < 100; $c++) { $start = microtime(true); ob_start(); $i = 0; foreach ($file as $line) { $i++;
ماذا نقيس | متوسط الوقت بالثواني |
---|
"حبل" | 0.0129 |
عدة ECHO | 0.0135 |
سلسلة | 0.0158 |
printf ، للتأكد من اكتمالها | 0.0245 |
النتائج
- بالنسبة للسلاسل ذات الاستبدال البسيط ، تكون كل علامات الاقتباس المفاجئة والمثالية أكثر مثالية من علامات الاقتباس المفردة ذات السلاسل. وكلما طالت مدة استخدام الخطوط ، زاد الربح.
- الحجج مفصولة بفواصل ... هناك العديد من الفروق الدقيقة. عن طريق القياس ، يكون أسرع من التسلسل وأبطأ من "الحبل" ، ولكن هناك الكثير من "المتغيرات" المرتبطة بالإدخال / الإخراج.
استنتاج
من الصعب علي أن أتوصل إلى موقف قد تنشأ فيه الحاجة إلى مثل هذه التحسينات الصغيرة. عند اختيار هذا النهج أو ذاك ، من المنطقي أن يتم الاسترشاد بمبادئ أخرى - على سبيل المثال ، إمكانية قراءة الكود أو أسلوب الترميز الذي تتبعه شركتك.
بالنسبة لي شخصيا ، أنا لا أحب نهج التسلسل بسبب مظهر vyrviglazny ، على الرغم من أنه في بعض الحالات يمكن تبريره.
ملاحظة: إذا كان هذا النوع من التحليل مثيرًا للاهتمام - واسمحوا لي أن أعرف - فهناك الكثير الذي لا يزال بعيدًا عن الغموض والواضح دائمًا: مجموعة من الكائنات VS ، أو foreach VS بينما VS ، ، لديك الخيار ... :)
شرح قليلا من قراءة التعليقات
بناء جملة HEREDOC و "السلاسل المعقدة" (حيث تكون المتغيرات في أقواس داخلية) هي نفس السلاسل مزدوجة الاقتباس وتجميعها بنفس الطريقة تمامًا.
مزيج من PHP مع HTML مثل هذا:
<?php $name = 'Vasya';?>Hello <?=$name?>! Have a nice day!
هذا هو مجرد 3
صدى على التوالي.