Saya jadi penasaran dan melihat tautan Adam Backstrom ke Tech Your Universe . Artikel ini menjelaskan salah satu alasan yang mengharuskan harus digunakan alih-alih require_once. Namun, klaim mereka tidak sesuai dengan analisis saya. Saya akan tertarik melihat di mana saya mungkin telah misanalysed solusinya. Saya menggunakan PHP 5.2.0 untuk perbandingan.
Saya mulai dengan membuat 100 file header yang menggunakan require_once untuk memasukkan file header lainnya. Masing-masing file ini terlihat seperti:
<?php
// /home/fbarnes/phpperf/hdr0.php
require_once "../phpperf/common_hdr.php";
?>
Saya membuat ini menggunakan Bash hack cepat:
for i in /home/fbarnes/phpperf/hdr{00..99}.php; do
echo "<?php
// $i" > $i
cat helper.php >> $i;
done
Dengan cara ini saya bisa dengan mudah bertukar antara menggunakan require_once dan membutuhkan ketika menyertakan file header. Saya kemudian membuat app.php untuk memuat seratus file. Ini terlihat seperti:
<?php
// Load all of the php hdrs that were created previously
for($i=0; $i < 100; $i++)
{
require_once "/home/fbarnes/phpperf/hdr$i.php";
}
// Read the /proc file system to get some simple stats
$pid = getmypid();
$fp = fopen("/proc/$pid/stat", "r");
$line = fread($fp, 2048);
$array = split(" ", $line);
// Write out the statistics; on RedHat 4.5 with kernel 2.6.9
// 14 is user jiffies; 15 is system jiffies
$cntr = 0;
foreach($array as $elem)
{
$cntr++;
echo "stat[$cntr]: $elem\n";
}
fclose($fp);
?>
Saya membandingkan header require_once dengan header yang menggunakan file header seperti:
<?php
// /home/fbarnes/phpperf/h/hdr0.php
if(!defined('CommonHdr'))
{
require "../phpperf/common_hdr.php";
define('CommonHdr', 1);
}
?>
Saya tidak menemukan banyak perbedaan ketika menjalankan ini dengan require vs require_once. Sebenarnya, tes awal saya sepertinya menyiratkan bahwa require_once sedikit lebih cepat, tapi saya tidak perlu percaya itu. Saya mengulangi percobaan dengan 10.000 file input. Di sini saya memang melihat perbedaan yang konsisten. Saya menjalankan tes beberapa kali, hasilnya dekat tetapi menggunakan require_once menggunakan rata-rata 30,8 pengguna jiffies dan 72,6 sistem jiffies; menggunakan memerlukan menggunakan rata-rata 39,4 pengguna jiffies dan 72,0 sistem jiffies. Oleh karena itu, tampak bahwa bebannya sedikit lebih rendah menggunakan require_once. Namun, waktu jam dinding sedikit meningkat. 10.000 panggilan need_once menggunakan rata-rata 10,15 detik untuk menyelesaikan dan rata-rata 10.000 panggilan menggunakan 9,84 detik.
Langkah selanjutnya adalah melihat perbedaan-perbedaan ini. Saya menggunakan strace untuk menganalisis panggilan sistem yang sedang dibuat.
Sebelum membuka file dari require_once, panggilan sistem berikut dilakukan:
time(NULL) = 1223772434
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=88, ...}) = 0
time(NULL) = 1223772434
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3
Ini kontras dengan membutuhkan:
time(NULL) = 1223772905
lstat64("/home", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf", {st_mode=S_IFDIR|0755, st_size=4096, ...}) = 0
lstat64("/home/fbarnes/phpperf/h", {st_mode=S_IFDIR|0755, st_size=270336, ...}) = 0
lstat64("/home/fbarnes/phpperf/h/hdr0.php", {st_mode=S_IFREG|0644, st_size=146, ...}) = 0
time(NULL) = 1223772905
open("/home/fbarnes/phpperf/h/hdr0.php", O_RDONLY) = 3
Tech Your Universe menyiratkan bahwa require_once harus membuat lebih banyak panggilan lstat64. Namun, keduanya melakukan panggilan lstat64 dengan jumlah yang sama. Mungkin, perbedaannya adalah saya tidak menjalankan APC untuk mengoptimalkan kode di atas. Namun, selanjutnya saya membandingkan output strace untuk seluruh proses:
[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
190709 strace_1000r.out
210707 strace_1000ro.out
401416 total
Secara efektif ada sekitar dua panggilan sistem per file header saat menggunakan require_once. Salah satu perbedaannya adalah require_once memiliki panggilan tambahan ke fungsi time ():
[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20009
strace_1000ro.out:30008
Panggilan sistem lainnya adalah getcwd ():
[fbarnes@myhost phpperf]$ grep -c getcwd strace_1000r.out strace_1000ro.out
strace_1000r.out:5
strace_1000ro.out:10004
Ini disebut karena saya memutuskan jalur relatif yang direferensikan dalam file hdrXXX. Jika saya menjadikan ini sebagai referensi absolut, maka satu-satunya perbedaan adalah panggilan waktu tambahan (NULL) yang dibuat dalam kode:
[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
190705 strace_1000r.out
200705 strace_1000ro.out
391410 total
[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20008
strace_1000ro.out:30008
Ini tampaknya menyiratkan bahwa Anda dapat mengurangi jumlah panggilan sistem dengan menggunakan jalur absolut daripada jalur relatif. Satu-satunya perbedaan di luar itu adalah panggilan waktu (NULL) yang tampaknya digunakan untuk menginstruksikan kode untuk membandingkan apa yang lebih cepat.
Satu catatan lain adalah bahwa paket optimasi APC memiliki opsi yang disebut "apc.include_once_override" yang mengklaim bahwa itu mengurangi jumlah panggilan sistem yang dilakukan oleh require_once dan panggilan include_once (lihat dokumentasi PHP ).