जब PHP bytecode फ़ाइलों को संकलित करता है, तो PHP opcode कैश का उपयोग क्यों करता है?




apc (4)

मेरे दृष्टिकोण से, PHP और Java दोनों में समान संरचना है। सबसे पहले आप कुछ उच्च-स्तरीय कोड लिखते हैं, जिसे फिर एक वीएम द्वारा निष्पादित किए जाने वाले सरल कोड प्रारूप में अनुवादित किया जाना चाहिए। एक अंतर यह है, कि PHP सीधे सोर्स कोड फाइलों से काम करती है, जबकि जावा बाईटकोड को .class फाइलों में संग्रहीत करता है, जहां से VM उन्हें लोड कर सकता है।

आजकल तेजी से PHP निष्पादन की आवश्यकताएं बढ़ती हैं, जो लोगों को विश्वास दिलाता है कि यह सीधे opcodes के साथ काम करना बेहतर होगा और जब कोई उपयोगकर्ता किसी फ़ाइल को हिट करता है, तो हर बार संकलन चरण के माध्यम से नहीं।

समाधान तथाकथित त्वरक का भार प्रतीत होता है, जो मूल रूप से संचित परिणामों को कैश में संग्रहीत करते हैं और फिर संकलित opcodes का उपयोग फिर से संकलित करने के बजाय करते हैं।

एक अन्य दृष्टिकोण, फेसबुक द्वारा किया गया है, पूरी तरह से PHP कोड को एक अलग भाषा में संकलित करना है

तो मेरा सवाल है, PHP दुनिया में कोई भी ऐसा क्यों नहीं कर रहा है जो जावा करता है? क्या कुछ गतिशील तत्व हैं जिन्हें वास्तव में हर बार या कुछ उसी तरह recompiled किया जाना चाहिए? अन्यथा यह वास्तव में सब कुछ संकलित करने के लिए चालाक होगा जब कोड उत्पादन में जाता है और फिर बस उसी के साथ काम करता है।


PHP opcodes के लिए एक मानक तंत्र का उपयोग नहीं करता है। काश यह या तो एक स्टैक वीएम (अजगर, जावा) या एक रजिस्टर वीएम (x86, perl6 आदि) से चिपक जाता। लेकिन यह कुछ बिल्कुल होमग्रोन का उपयोग करता है और रगड़ में निहित है।

यह स्मृति में एक कनेक्टेड सूची का उपयोग करता है जिसके परिणामस्वरूप प्रत्येक opcode में -> op1 -> op2 और -> परिणाम होता है। अब उनमें से प्रत्येक या तो एक अस्थायी तालिका आदि में स्थिरांक या प्रविष्टियां हैं। इन बिंदुओं को किसी भी सेंस फैशन में क्रमबद्ध नहीं किया जा सकता है।

अब, लोगों ने इसे pecl / bcompiler जैसी वस्तुओं का उपयोग करके पूरा किया है जो डिस्क में स्ट्रीम को डंप करता है।

लेकिन कक्षाएं इसे और भी जटिल बनाती हैं, जिसका अर्थ है कि संभावित कोड टुकड़े जैसे हैं

if(<conditon>)
{
   class XYZ() { }
}
else 
{
   class XYZ() { }
}

class ABC extends XYZ {}

जिसका अर्थ है कि वर्गों और कार्यों के बारे में निर्णय की एक बड़ी संख्या केवल रनटाइम पर ही की जा सकती है - जावा की तरह कुछ दो वर्गों पर एक ही नाम से गूँजेंगे, जिन्हें सशर्त रूप से परिभाषित किया गया है। असल में, APC की विरासत और वर्ग कैशिंग कोड शायद कोडबेस का सबसे जटिल और बग-प्रवण हिस्सा है। जब भी कोई क्लास कैश की जाती है, तो ऑर्थोड कैश में सेव किए जाने से पहले सभी पैरेंट विरासत वाले सदस्यों को स्क्रब करना पड़ता है।

पॉइंटर समस्या अचूक नहीं है। एक apc_bindump है जिसे मैंने कभी भी पुनरारंभ करने के बाद सीधे डिस्क से संपूर्ण कैश प्रविष्टियों को लोड करने के लिए ठीक करने की जहमत नहीं उठाई है। लेकिन सभी को डिबग करने के लिए यह दर्दनाक है कि अभी भी सभी सिस्टम पॉइंटर्स का पता लगाने की आवश्यकता है - अपाचे मामला बहुत आसान है, क्योंकि फोर्क व्यवहार के कारण सभी php प्रक्रियाओं में समान सिस्टम पॉइंटर्स होते हैं। पुराने Fastcgi संस्करण धीमे थे क्योंकि वे पहले और init php को बाद में फोर्क करते थे - php-fpm ने तय किया कि इसे दूसरे तरीके से कर सकते हैं।

लेकिन अंततः, PHP में जो वास्तव में गायब है, वह एक बाईटेकोड प्रारूप का आविष्कार करने की इच्छा है, वर्तमान इंजन और सभी मॉड्यूल को दूर फेंक दें - एक स्टैक वीएम का उपयोग करके इसे फिर से लिखना और JIT का निर्माण करना। काश मेरे पास समय होता - fb लोग लगभग अपने हिपहॉप HHVM के साथ होते। जो तेजी से प्रदर्शन के लिए eval () का त्याग करता है - जो कि एक उचित बलिदान है :)

पुनश्च: मैं वह व्यक्ति हूं जिसे एपीसी को 5.4 के लिए ठीक से अपडेट करने का समय नहीं मिल रहा है


PHP ऑपकोड जावा क्लासफाइल्स के समान नहीं हैं। जावा क्लासफाइल्स अच्छी तरह से निर्दिष्ट हैं, और मशीनों के बीच पोर्टेबल हैं। PHP opcodes किसी भी तरह से पोर्टेबल नहीं हैं। उदाहरण के लिए, उनके पास बेक किए गए मेमोरी एड्रेस हैं। वे कड़ाई से PHP दुभाषिया के कार्यान्वयन विस्तार हैं, और जावा बाइटकोड की तरह कुछ भी नहीं माना जाना चाहिए।

क्या इस तरह से होना है? नहीं, शायद नहीं। लेकिन PHP स्रोत कोड एक गड़बड़ है, और ऐसा करने की न तो इच्छा है, और न ही PHP के आंतरिक समुदाय में राजनीतिक इच्छाशक्ति। मुझे लगता है कि PHP 6 में एक opcode कैश बेक करने की बात थी, लेकिन PHP 6 की मृत्यु हो गई, और मुझे उस विचार की स्थिति नहीं पता है।

संदर्भ : मैंने पीएचसी लिखी थी इसलिए मैं कुछ वर्षों के लिए पीएचपी कार्यान्वयन / संकलन में बहुत गहरा था।


यह बिल्कुल सच नहीं है कि PHP दुनिया में कोई भी ऐसा नहीं कर रहा है जो जावा करता है। एलेक्सी ज़ख़्लेस्टिन के प्रशिक्षक के रूप में परियोजनाएं जावा सर्वलेट कंटेनर के लिए अधिक दृढ़ता की डिग्री प्रदान करती हैं (हालांकि उनकी प्रेरणा रूबी रैक और जावा की तुलना में पायथन की डब्ल्यूएसजीआई है)


सबसे महत्वपूर्ण अंतर यह है कि जेवीएम में एक स्पष्ट विनिर्देश है जो पूरी तरह से बायटेकोड को कवर करता है। यह एक विशिष्ट JVM कार्यान्वयन द्वारा केवल निष्पादन से अधिक के लिए पोर्टेबल और उपयोगी बाइटकोड फ़ाइलों को बनाता है।

PHP में भाषा विनिर्देश भी नहीं है। PHP opcodes एक विशिष्ट PHP इंजन का कार्यान्वयन विवरण है, इसलिए आप वास्तव में उनके साथ कुछ भी दिलचस्प नहीं कर सकते हैं और उन्हें अधिक दृश्यमान बनाने में बहुत कम बिंदु हैं।