"यदि कोई कर्मचारी अपना काम अच्छी तरह से करना चाहता है, तो उसे पहले अपने औजारों को तेज करना होगा।" - कन्फ्यूशियस, "द एनालेक्ट्स ऑफ कन्फ्यूशियस। लू लिंगगोंग"
मुखपृष्ठ > प्रोग्रामिंग > बहुत दोहरा उद्धरण है या नहीं, यही सवाल है!

बहुत दोहरा उद्धरण है या नहीं, यही सवाल है!

2024-08-27 को प्रकाशित
ब्राउज़ करें:963

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

"सबकुछ पहले ही कहा जा चुका है, लेकिन अभी तक सभी ने नहीं कहा है" - कार्ल वैलेन्टिन

यह इसी भावना से है कि मैं उसी विषय पर एक लेख लिख रहा हूं जो निकिता पोपोव ने 12 साल पहले लिखा था (यदि आप उनका लेख पढ़ रहे हैं, तो आप यहां पढ़ना बंद कर सकते हैं)।

आख़िर फ़ज़ क्या है?

PHP स्ट्रिंग इंटरपोलेशन करता है, जिसमें यह एक स्ट्रिंग में वेरिएबल के उपयोग की खोज करता है और उन्हें उपयोग किए गए वेरिएबल के मान से बदल देता है:

$juice = "apple";
echo "They drank some $juice juice.";
// will output: They drank some apple juice.

यह सुविधा डबल कोट्स और हेरेडोक में स्ट्रिंग्स तक सीमित है। एकल उद्धरण (या nowdoc) का उपयोग करने से एक अलग परिणाम प्राप्त होगा:

$juice = "apple";
echo 'They drank some $juice juice.';
// will output: They drank some $juice juice.

उसे देखें: PHP उस एकल उद्धृत स्ट्रिंग में वेरिएबल की खोज नहीं करेगा। इसलिए हम हर जगह सिंगल कोट्स का उपयोग शुरू कर सकते हैं। तो लोगों ने इस तरह के बदलावों का सुझाव देना शुरू कर दिया..

- $juice = "apple";
  $juice = 'apple';

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

मामला बंद?

स्पष्ट रूप से सिंगल कोट्स बनाम डबल कोट्स का उपयोग करने में अंतर है, लेकिन यह समझने के लिए कि क्या हो रहा है हमें थोड़ा और गहराई से जानने की जरूरत है।

भले ही PHP एक व्याख्या की गई भाषा है, यह एक संकलन चरण का उपयोग कर रही है जिसमें कुछ हिस्से एक साथ खेलते हैं ताकि वर्चुअल मशीन वास्तव में निष्पादित हो सके, जो कि ऑपकोड है। तो हम PHP स्रोत कोड से ऑपकोड तक कैसे पहुँच सकते हैं?

लेक्सर

लेक्सर स्रोत कोड फ़ाइल को स्कैन करता है और इसे टोकन में तोड़ देता है। इसका मतलब क्या है इसका एक सरल उदाहरण टोकन_गेट_ऑल() फ़ंक्शन दस्तावेज़ में पाया जा सकता है। केवल

T_OPEN_TAG (



हम इस 3v4l.org स्निपेट में इसे क्रियाशील रूप में देख सकते हैं और इसके साथ खेल सकते हैं।

पार्सर

पार्सर इन टोकन को लेता है और उनसे एक अमूर्त सिंटैक्स ट्री बनाता है। उपरोक्त उदाहरण का AST प्रतिनिधित्व JSON के रूप में प्रस्तुत किए जाने पर इस तरह दिखता है:

{
  "data": [
    {
      "nodeType": "Stmt_Echo",
      "attributes": {
        "startLine": 1,
        "startTokenPos": 1,
        "startFilePos": 6,
        "endLine": 1,
        "endTokenPos": 4,
        "endFilePos": 13
      },
      "exprs": [
        {
          "nodeType": "Scalar_String",
          "attributes": {
            "startLine": 1,
            "startTokenPos": 3,
            "startFilePos": 11,
            "endLine": 1,
            "endTokenPos": 3,
            "endFilePos": 12,
            "kind": 2,
            "rawValue": "\"\""
          },
          "value": ""
        }
      ]
    }
  ]
}

यदि आप इसके साथ भी खेलना चाहते हैं और देखना चाहते हैं कि अन्य कोड के लिए एएसटी कैसा दिखता है, तो मुझे रयान चांडलर द्वारा https://phpast.com/ और https://php-ast-viewer.com/ मिला जो दोनों आपको PHP कोड के दिए गए भाग का AST दिखाते हैं।

संकलक

कंपाइलर एएसटी लेता है और ऑपकोड बनाता है। ऑपकोड वे चीजें हैं जिन्हें वर्चुअल मशीन निष्पादित करती है, यह वह भी है जो ओपी कैश में संग्रहीत किया जाएगा यदि आपके पास वह सेटअप और सक्षम है (जिसकी मैं अत्यधिक अनुशंसा करता हूं)।

ऑपकोड देखने के लिए हमारे पास कई विकल्प हैं (शायद अधिक, लेकिन मैं इन तीन को जानता हूं):

  1. वल्कन लॉजिक डम्पर एक्सटेंशन का उपयोग करें। इसे 3v4l.org में भी बेक किया गया है
  2. ऑपकोड को डंप करने के लिए phpdbg -p स्क्रिप्ट.php का उपयोग करें
  3. या ऑपकोड को प्रिंट करने के लिए OPcache के लिए opcache.opt_debug_level INI सेटिंग का उपयोग करें
    • अनुकूलन से पहले 0x10000 आउटपुट ऑपकोड का मान
    • अनुकूलन के बाद 0x20000 आउटपुट ऑपकोड का मान
$ echo ' foo.php
$ php -dopcache.opt_debug_level=0x10000 foo.php
$_main:
...
0000 ECHO string("")
0001 RETURN int(1)

परिकल्पना

सिंगल कोट्स बनाम डबल कोट्स का उपयोग करते समय सीपीयू चक्रों को बचाने के प्रारंभिक विचार पर वापस आते हुए, मुझे लगता है कि हम सभी इस बात से सहमत हैं कि यह केवल तभी सच होगा जब PHP हर एक अनुरोध के लिए रनटाइम पर इन स्ट्रिंग्स का मूल्यांकन करेगा।

रनटाइम पर क्या होता है?

तो आइए देखें कि PHP दो अलग-अलग संस्करणों के लिए कौन सा ऑपकोड बनाता है।

दोहरे उद्धरण:







0000 ECHO string("apple")
0001 RETURN int(1)

बनाम. एकल कोट:







0000 ECHO string("apple")
0001 RETURN int(1)

अरे रुको, कुछ अजीब हुआ। यह एक जैसा दिखता है! मेरा सूक्ष्म अनुकूलन कहां गया?

ठीक है, हो सकता है कि ईसीएचओ ऑपकोड हैंडलर का कार्यान्वयन दिए गए स्ट्रिंग को पार्स करता है, हालांकि कोई मार्कर या कुछ और नहीं है जो इसे ऐसा करने के लिए कहता है ... हम्म?

आइए एक अलग दृष्टिकोण आज़माएं और देखें कि लेक्सर उन दो मामलों के लिए क्या करता है:

दोहरे उद्धरण:

T_OPEN_TAG (



बनाम. एकल कोट:

Line 1: T_OPEN_TAG (



टोकन अभी भी डबल और सिंगल कोट्स के बीच अंतर कर रहे हैं, लेकिन एएसटी की जांच करने से हमें दोनों मामलों के लिए एक समान परिणाम मिलेगा - एकमात्र अंतर स्केलर_स्ट्रिंग नोड विशेषताओं में रॉवैल्यू है, जिसमें अभी भी सिंगल/डबल कोट्स हैं, लेकिन मान दोनों मामलों में दोहरे उद्धरण चिह्नों का उपयोग करता है।

नई परिकल्पना

क्या ऐसा हो सकता है कि स्ट्रिंग इंटरपोलेशन वास्तव में संकलन समय पर किया गया हो?

आइए थोड़ा अधिक "परिष्कृत" उदाहरण से जांच करें:





इस फ़ाइल के लिए टोकन हैं:

T_OPEN_TAG (



अंतिम दो टोकन देखें! स्ट्रिंग इंटरपोलेशन को लेक्सर में नियंत्रित किया जाता है और यह एक संकलन समय की चीज़ है और इसका रनटाइम से कोई लेना-देना नहीं है।

Too double quote or not, that

पूर्णता के लिए, आइए इसके द्वारा उत्पन्न ऑपकोड पर एक नजर डालें (अनुकूलन के बाद, 0x20000 का उपयोग करके):

0000 ASSIGN CV0($juice) string("apple")
0001 T2 = FAST_CONCAT string("juice: ") CV0($juice)
0002 ECHO T2
0003 RETURN int(1)

यह हमारे सरल

मुद्दे पर आएं: क्या मुझे संक्षेपण या प्रक्षेप करना चाहिए?

आइए इन तीन अलग-अलग संस्करणों पर एक नजर डालें:





  • पहला संस्करण स्ट्रिंग इंटरपोलेशन का उपयोग कर रहा है
  • दूसरा अल्पविराम पृथक्करण का उपयोग कर रहा है (जो AFAIK केवल प्रतिध्वनि के साथ काम करता है न कि चर या कुछ और निर्दिष्ट करने के साथ)
  • और तीसरा विकल्प स्ट्रिंग संयोजन का उपयोग करता है

पहला ऑपकोड वेरिएबल $juice को स्ट्रिंग "सेब" निर्दिष्ट करता है:

0000 ASSIGN CV0($juice) string("apple")

पहला संस्करण (स्ट्रिंग इंटरपोलेशन) अंतर्निहित डेटा संरचना के रूप में एक रस्सी का उपयोग कर रहा है, जिसे यथासंभव कम स्ट्रिंग प्रतियां बनाने के लिए अनुकूलित किया गया है।

0001 T2 = ROPE_INIT 4 string("juice: ")
0002 T2 = ROPE_ADD 1 T2 CV0($juice)
0003 T2 = ROPE_ADD 2 T2 string(" ")
0004 T1 = ROPE_END 3 T2 CV0($juice)
0005 ECHO T1

दूसरा संस्करण सबसे अधिक मेमोरी प्रभावी है क्योंकि यह एक मध्यवर्ती स्ट्रिंग प्रतिनिधित्व नहीं बनाता है। इसके बजाय यह ECHO को कई कॉल करता है जो कि I/O परिप्रेक्ष्य से एक ब्लॉकिंग कॉल है, इसलिए आपके उपयोग के मामले के आधार पर यह एक नकारात्मक पहलू हो सकता है।

0006 ECHO string("juice: ")
0007 ECHO CV0($juice)
0008 ECHO string(" ")
0009 ECHO CV0($juice)

तीसरा संस्करण मध्यवर्ती स्ट्रिंग प्रतिनिधित्व बनाने के लिए CONCAT/FAST_CONCAT का उपयोग करता है और इस प्रकार रस्सी संस्करण की तुलना में अधिक मेमोरी का उपयोग कर सकता है।

0010 T1 = CONCAT string("juice: ") CV0($juice)
0011 T2 = FAST_CONCAT T1 string(" ")
0012 T1 = CONCAT T2 CV0($juice)
0013 ECHO T1

तो... यहां क्या करना सही है और यह स्ट्रिंग इंटरपोलेशन क्यों है?

इको "जूस: $जूस" के मामले में स्ट्रिंग इंटरपोलेशन या तो FAST_CONCAT का उपयोग करता है; या इको "जूस: $जूस $जूस" के मामले में अत्यधिक अनुकूलित ROPE_* ऑपकोड;, लेकिन सबसे महत्वपूर्ण बात यह है कि यह स्पष्ट रूप से इरादे को संप्रेषित करता है और इनमें से किसी भी PHP एप्लिकेशन में बाधा नहीं आई है, जिसके साथ मैंने अब तक काम किया है, इसलिए इनमें से कोई भी वास्तव में मायने नहीं रखता।

टीएलडीआर

स्ट्रिंग इंटरपोलेशन एक संकलन समय की चीज़ है। माना, OPcache के बिना लेक्सर को प्रत्येक अनुरोध पर डबल उद्धृत स्ट्रिंग्स में उपयोग किए गए वेरिएबल्स की जांच करनी होगी, भले ही कोई भी सीपीयू चक्र बर्बाद न हो, लेकिन ईमानदारी से: समस्या डबल उद्धृत स्ट्रिंग्स की नहीं है, बल्कि OPcache का उपयोग करने की नहीं है!

हालाँकि, एक चेतावनी है: 4 तक PHP (और मेरा मानना ​​​​है कि 5.0 और शायद 5.1 भी शामिल है, मुझे नहीं पता) ने रनटाइम पर स्ट्रिंग इंटरपोलेशन किया था, इसलिए इन संस्करणों का उपयोग करना ... हम्म, मुझे लगता है अगर कोई भी वास्तव में अभी भी PHP 5 का उपयोग करता है, ऊपर जैसा ही लागू होता है: समस्या दोहरे उद्धृत स्ट्रिंग्स की नहीं है, बल्कि पुराने PHP संस्करण के उपयोग की है।

अंतिम सलाह

नवीनतम PHP संस्करण में अपडेट करें, OPcache सक्षम करें और हमेशा के लिए खुशी से जिएं!

विज्ञप्ति वक्तव्य यह आलेख यहां पुन: प्रस्तुत किया गया है: https://dev.to/realflowcontrol/too-double-quote-or-not-thats-the-question-78l?1 यदि कोई उल्लंघन है, तो कृपया हटाने के लिए स्टडी_गोलंग@163.com पर संपर्क करें यह
नवीनतम ट्यूटोरियल अधिक>

चीनी भाषा का अध्ययन करें

अस्वीकरण: उपलब्ध कराए गए सभी संसाधन आंशिक रूप से इंटरनेट से हैं। यदि आपके कॉपीराइट या अन्य अधिकारों और हितों का कोई उल्लंघन होता है, तो कृपया विस्तृत कारण बताएं और कॉपीराइट या अधिकारों और हितों का प्रमाण प्रदान करें और फिर इसे ईमेल पर भेजें: [email protected] हम इसे आपके लिए यथाशीघ्र संभालेंगे।

Copyright© 2022 湘ICP备2022001581号-3