मैं उत्सुक हो गया और एडम बैकस्ट्रॉम के टेक योर यूनिवर्स के लिंक की जाँच की । यह आलेख उन कारणों में से एक का वर्णन करता है जिनके लिए आवश्यकता के बजाय उपयोग किया जाना चाहिए। हालांकि, उनके दावे मेरे विश्लेषण तक नहीं थे। मुझे यह देखने में दिलचस्पी होगी कि मैंने समाधान का दुरुपयोग कहां किया होगा। मैंने तुलना के लिए PHP 5.2.0 का उपयोग किया।
मैंने 100 हेडर फाइलें बनाकर शुरुआत की, जिनमें अन्य हेडर फाइल को शामिल करने के लिए जरूरी_ का उपयोग किया गया था। इनमें से प्रत्येक फाइल कुछ इस तरह दिखती है:
<?php
// /home/fbarnes/phpperf/hdr0.php
require_once "../phpperf/common_hdr.php";
?>
मैंने इन्हें त्वरित बैश हैक का उपयोग करके बनाया है:
for i in /home/fbarnes/phpperf/hdr{00..99}.php; do
echo "<?php
// $i" > $i
cat helper.php >> $i;
done
इस तरह मैं आसानी से हेडर फ़ाइलों को शामिल करते हुए आवश्यकता और आवश्यकता के उपयोग के बीच स्वैप कर सकता था। मैंने तब एक ऐप बनाया था। एक सौ फाइलों को लोड करने के लिए। यह देखा:
<?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);
?>
मैंने आवश्यकता हेडर की आवश्यकता के साथ हेडर के विपरीत काम किया है जो एक हेडर फ़ाइल का उपयोग करता है जैसे कि:
<?php
// /home/fbarnes/phpperf/h/hdr0.php
if(!defined('CommonHdr'))
{
require "../phpperf/common_hdr.php";
define('CommonHdr', 1);
}
?>
जब मुझे यह आवश्यकता के साथ चल रहा था तो मुझे ज्यादा अंतर नहीं मिला। वास्तव में, मेरे शुरुआती परीक्षणों का मतलब यह लग रहा था कि requ_once थोड़ा तेज था, लेकिन मैं जरूरी नहीं मानता कि। मैंने 10000 इनपुट फ़ाइलों के साथ प्रयोग दोहराया। यहाँ मैंने एक सुसंगत अंतर देखा। मैंने कई बार परीक्षण चलाया, परिणाम करीब हैं लेकिन 30_ उपयोगकर्ता की औसत जिफ़ी और 72.6 सिस्टम रिफ़िसेस पर आवश्यकता के अनुरूप उपयोग कर रहे हैं; उपयोग करने के लिए औसत 39.4 उपयोगकर्ता जीफिज और 72.0 सिस्टम जीफिज का उपयोग करने की आवश्यकता होती है। इसलिए, ऐसा प्रतीत होता है कि आवश्यकता _ का उपयोग करके लोड थोड़ा कम है। हालांकि, दीवार घड़ी का समय थोड़ा बढ़ जाता है। औसत पर पूरा करने के लिए 10,000 आवश्यकता_ऑन कॉल का उपयोग 10.15 सेकंड और औसत पर 10,000 कॉल का उपयोग 9.84 सेकंड की आवश्यकता होती है।
इन मतभेदों पर गौर करने के लिए अगला कदम है। मैंने सिस्टम कॉल का विश्लेषण करने के लिए स्ट्रेस का उपयोग किया है जो किए जा रहे हैं।
आवश्यकता से एक फ़ाइल खोलने से पहले निम्नलिखित सिस्टम कॉल किए जाते हैं:
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
यह आवश्यकता के विपरीत है:
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
टेक योर यूनिवर्स का तात्पर्य है कि आवश्यकता होती है_ और अधिक lstat64 कॉल करना चाहिए। हालाँकि, वे दोनों समान संख्या में lstat64 कॉल करते हैं। संभवतः, अंतर यह है कि मैं ऊपर दिए गए कोड को अनुकूलित करने के लिए APC नहीं चला रहा हूं। हालांकि, अगले मैंने पूरे रन के लिए स्ट्रेस के आउटपुट की तुलना की:
[fbarnes@myhost phpperf]$ wc -l strace_1000r.out strace_1000ro.out
190709 strace_1000r.out
210707 strace_1000ro.out
401416 total
प्रभावी रूप से लगभग दो और सिस्टम कॉल प्रति हेडर फ़ाइल की आवश्यकता होती है जब आवश्यकता होती है। एक अंतर यह है कि requ_once के पास समय () फ़ंक्शन के लिए एक अतिरिक्त कॉल है:
[fbarnes@myhost phpperf]$ grep -c time strace_1000r.out strace_1000ro.out
strace_1000r.out:20009
strace_1000ro.out:30008
अन्य सिस्टम कॉल getcwd () है:
[fbarnes@myhost phpperf]$ grep -c getcwd strace_1000r.out strace_1000ro.out
strace_1000r.out:5
strace_1000ro.out:10004
इसे इसलिए कहा जाता है क्योंकि मैंने hdrXXX फ़ाइलों में संदर्भित सापेक्ष पथ का निर्णय लिया था। यदि मैं इसे पूर्ण संदर्भ बनाता हूं, तो कोड में किए गए अतिरिक्त समय (NULL) कॉल का एकमात्र अंतर है:
[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
इसका अर्थ यह प्रतीत होता है कि आप सापेक्ष पथों के बजाय निरपेक्ष पथों का उपयोग करके सिस्टम कॉल की संख्या को कम कर सकते हैं। इसके बाहर का एकमात्र अंतर समय (NULL) कॉल है जो कि कोड को इंस्ट्रूमेंट करने के लिए उपयोग होने के लिए दिखाई देता है जो कि तेज है।
एक अन्य नोट यह है कि APC ऑप्टिमाइज़ेशन पैकेज में "apc.include_once_override" नाम का एक विकल्प होता है, जो दावा करता है कि यह आवश्यक कॉलों की संख्या को घटाता है जिनमें आवश्यक_ऑनस और शामिल_ऑनस कॉल ( PHP प्रलेखन देखें )।