
Adapun optimasi mikro PHP, dengan mengganti tanda kutip ganda dengan tanda kutip tunggal, begitu banyak salinan yang rusak sehingga cukup bermasalah untuk membuat aliran baru. Tapi saya akan coba.
Dalam artikel ini hanya akan ada satu tolok ukur, di mana itu akan menjadi tanpa itu, dan penekanan utama adalah pada menganalisis bagaimana itu diatur di dalam.
Penafian
- Segala sesuatu yang diuraikan di bawah ini, untuk sebagian besar, menghemat nanodetik, dan dalam praktiknya tidak akan melakukan apa-apa selain kehilangan waktu yang hilang pada optimasi mikro tersebut. Ini terutama berlaku untuk "optimisasi" waktu kompilasi.
- Saya akan memotong kode dan output secara maksimal, hanya menyisakan esensi.
- Saat menulis artikel, saya menggunakan PHP 7.2
Diperlukan Pendahuluan
Sebuah string dalam tanda kutip ganda 
pada tahap kompilasi diproses sedikit berbeda dari string dalam tanda kutip tunggal.
Kutipan tunggal akan diuraikan seperti ini:
statement -> expr -> scalar -> dereferencable_scalar -> T_CONSTANT_ENCAPSED_STRING 
Gandakan jadi:
 statement -> expr -> scalar -> '"' encaps_list '"' ->        ,  ,     
Dalam artikel tentang optimasi mikro PHP, sering kali ada saran untuk tidak menggunakan 
cetak , karena lebih lambat daripada 
gema . Mari kita lihat bagaimana mereka diurutkan.
Parsing 
echo :
 statement -> T_ECHO echo_expr_list -> echo_expr_list ->  echo_expr -> expr 
Parsing 
cetak :
 statement -> expr -> T_PRINT expr -> expr ( ) 
Yaitu secara umum, ya, 
gema terdeteksi langkah sebelumnya dan langkah ini, harus dicatat, cukup sulit.
Agar tidak menonjolkan perhatian sekali lagi selama artikel, kami akan ingat bahwa pada tahap kompilasi, tanda kutip ganda kehilangan satu, dan 
cetak kehilangan 
gema . Juga, jangan lupa bahwa dalam kasus terburuk, ini tentang nanodetik.
Nah, agar tidak bangun dua kali. Berikut adalah fungsi-fungsi berbeda yang menyusun 
cetak dan 
gema :
 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 } 
Yah, Anda mengerti - mereka identik dalam fungsi, tetapi 
cetak juga menghasilkan konstanta sama dengan 1. Saya pikir pada topik ini dengan 
cetak Anda dapat menutup dan melupakannya selamanya.
Garis sederhana, tanpa embel-embel
Strings 
echo 'Some string'; dan 
echo "Some string"; akan dibagi hampir identik menjadi 2 (tolak P2) token.
 T_ECHO: echo T_ENCAPSED_AND_WHITESPACE/T_CONSTANT_ENCAPSED_STRING: "Some string" 
Selain itu, untuk tanda kutip tunggal akan selalu ada T_CONSTANT_ENCAPSED_STRING, dan untuk tanda kutip ganda, jika diinginkan. Jika ada spasi di baris, maka T_ENCAPSED_AND_WHITESPACE.
Opcodes akan mudah dipermalukan dan benar-benar identik:
 line  
Kesimpulan
Jika Anda ingin menyimpan beberapa siklus prosesor pada tahap kompilasi, maka, untuk string konstan, gunakan tanda kutip tunggal.
Garis dinamis
Ada 4 opsi.
 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); 
Untuk opsi pertama:
 T_ECHO: echo T_ENCAPSED_AND_WHITESPACE: Hello T_VARIABLE: $name T_ENCAPSED_AND_WHITESPACE: ! Have a nice day! 
Untuk yang kedua (untuk yang ketiga juga, hanya sebagai ganti periode akan ada koma):
 T_ECHO: echo T_CONSTANT_ENCAPSED_STRING: 'Hello ' string: . T_VARIABLE: $name string: . T_CONSTANT_ENCAPSED_STRING: '! Have a nice day!' 
Untuk yang keempat:
 T_STRING: printf T_CONSTANT_ENCAPSED_STRING: 'Hello %s! Have a nice day!' string: , T_VARIABLE: $name 
Tetapi dengan opcodes semuanya akan jauh lebih menghibur.
Yang pertama:
 echo "Hello $name! Have a nice day!"; line  
Kedua:
 echo 'Hello '.$name.'! Have a nice day!'; line  
Ketiga:
 echo 'Hello ', $name, '! Have a nice day!'; line  
Keempat:
 printf ('Hello %s! Have a nice day!', $name); line  
Akal sehat memberi tahu kita bahwa opsi dengan `printf` akan hilang dalam kecepatan pada tiga yang pertama (terutama karena pada akhirnya masih ada ECHO yang sama), jadi kita akan meninggalkannya untuk tugas-tugas di mana pemformatan diperlukan dan kita tidak akan mengingat lebih banyak dalam artikel ini.
Tampaknya pilihan ketiga adalah yang tercepat - untuk mencetak tiga baris berturut-turut tanpa penggabungan, ROPE aneh dan penciptaan variabel tambahan. Tapi tidak sesederhana itu. Fungsi cetak dalam PHP tentu saja bukan Rocket Science, tetapi tidak berarti f-C-shny 
dangkal . Siapa yang 
peduli - bola terurai dimulai dengan 
php_output_write dalam file 
utama / output.c .
CONCAT. Semuanya sederhana di sini - kami mengonversi, jika perlu, argumen menjadi string dan membuat 
zend_string baru menggunakan 
memcpy cepat. Satu-satunya negatif adalah bahwa dengan rangkaian panjang rangkaian untuk setiap operasi, baris baru akan dibuat dengan menggeser byte yang sama dari satu tempat ke tempat lain.
Tetapi dengan ROPE_INIT, ROPE_ADD dan ROPE_END semuanya jauh lebih menarik. Ikuti tangan:
- ROPE_INIT (ext = 3, return = ~ 3, operand = 'Hello +')
 Kami mengalokasikan "tali" dari tiga slot (ext), meletakkan string 'Hello +' (operan) di slot 0 dan mengembalikan variabel sementara ~ 3 (kembali) berisi "tali".
- ROPE_ADD (ext = 1, return = ~ 3, operan = ~ 3 ,! 0)
 Kami menempatkan di slot 1 (ext) dari "tali" ~ 3 (operan) string 'Vasya', yang diperoleh dari variabel! 0 (operan) dan mengembalikan "tali" ~ 3 (kembali).
- ROPE_END (ext = 2, return = ~ 2, operan = ~ 3, '% 21 + Semoga + bagus + hari% 21')
 Kami menempatkan baris '% 21 + Memiliki + bagus + hari% 21' (operan) di slot 2 (ext), setelah itu kami membuat zend_string dari ukuran yang diperlukan dan menyalin semua "tali" slot ke dalamnya pada gilirannya dengan memcpy yang sama.
Perlu dicatat secara terpisah bahwa dalam kasus konstanta dan variabel sementara, tautan ke data akan ditempatkan di slot, dan tidak akan ada penyalinan yang tidak perlu.
Menurut saya, cukup elegan. :)
Mari patokan. Sebagai sumber data, kami mengambil file 
zend_vm_execute.h (IMHO ini benar) untuk 71 ribu baris dan mencetaknya dalam 100 cara untuk 100 lintasan, menjatuhkan nilai minimum dan maksimum (setiap pengukuran dimulai 10 kali, memilih opsi yang paling umum):
 <?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++;  
| Apa yang kita ukur | Waktu rata-rata dalam detik | 
|---|
| "Tali" | 0,0129 | 
| Beberapa ECHO | 0,0135 | 
| Rangkaian | 0,0158 | 
| printf , untuk kelengkapan | 0,0245 | 
Kesimpulan
- Untuk string dengan substitusi sederhana, tiba-tiba, tanda kutip ganda lebih optimal daripada tanda kutip tunggal dengan penggabungan. Dan semakin panjang garis yang digunakan, semakin besar keuntungannya.
- Argumen dipisahkan oleh koma ... Ada banyak nuansa. Dengan pengukuran, ini lebih cepat daripada penggabungan dan lebih lambat dari "tali", tetapi ada terlalu banyak "variabel" yang terkait dengan input / output.
Kesimpulan
Sulit bagi saya untuk memikirkan situasi di mana kebutuhan untuk optimasi mikro seperti itu mungkin muncul. Ketika memilih pendekatan ini atau itu, lebih masuk akal untuk dipandu oleh prinsip-prinsip lain - misalnya, keterbacaan kode atau gaya pengkodean yang diadopsi oleh perusahaan Anda.
Bagi saya pribadi, saya tidak suka pendekatan gabungan karena tampilan vyrviglazny, meskipun dalam beberapa kasus itu dapat dibenarkan.
PS Jika analisis semacam ini menarik - beri tahu saya - ada banyak lagi yang jauh dari selalu tidak ambigu dan jelas: array objek VS, foreach VS sementara VS untuk, pilihan Anda ... :)
Sedikit penjelasan dari membaca komentar
Sintaks HEREDOC dan "string kompleks" (di mana variabel berada di dalam kurung di dalam) adalah string yang dikutip ganda dan dikompilasi dengan cara yang persis sama.
Campuran PHP dengan HTML seperti ini:
 <?php $name = 'Vasya';?>Hello <?=$name?>! Have a nice day! 
Ini hanya 3 
gema berturut-turut.