Heim > Backend-Entwicklung > PHP-Tutorial > Zu doppeltes Anführungszeichen oder nicht, das ist hier die Frage!

Zu doppeltes Anführungszeichen oder nicht, das ist hier die Frage!

王林
Freigeben: 2024-08-16 16:34:49
Original
517 Leute haben es durchsucht

Erst kürzlich habe ich wieder gehört, dass PHP-Leute immer noch über einfache Anführungszeichen vs. doppelte Anführungszeichen sprechen und dass die Verwendung von einfachen Anführungszeichen nur eine Mikrooptimierung ist, aber wenn man sich daran gewöhnt, ständig einfache Anführungszeichen zu verwenden, würde man eine Menge CPU sparen Zyklen!

„Alles ist schon gesagt, aber noch nicht von allen“ – Karl Valentin

In diesem Sinne schreibe ich einen Artikel über dasselbe Thema, das Nikita Popov bereits vor 12 Jahren geschrieben hat (wenn Sie seinen Artikel lesen, können Sie hier aufhören zu lesen).

Was hat es mit dem Flaum auf sich?

PHP führt eine String-Interpolation durch, bei der es nach der Verwendung von Variablen in einem String sucht und diese durch den Wert der verwendeten Variablen ersetzt:

$juice = "apple";
echo "They drank some $juice juice.";
// will output: They drank some apple juice.
Nach dem Login kopieren

Diese Funktion ist auf Zeichenfolgen in doppelten Anführungszeichen und Heredoc beschränkt. Die Verwendung von einfachen Anführungszeichen (oder nowdoc) führt zu einem anderen Ergebnis:

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

Sehen Sie sich das an: PHP sucht nicht nach Variablen in dieser Zeichenfolge in einfachen Anführungszeichen. Wir könnten also einfach überall einfache Anführungszeichen verwenden. Also fingen die Leute an, solche Änderungen vorzuschlagen..

- $juice = "apple";
+ $juice = 'apple';
Nach dem Login kopieren

.. weil es schneller ist und bei jeder Ausführung dieses Codes eine Menge CPU-Zyklen einspart, weil PHP nicht nach Variablen in Zeichenfolgen in einfachen Anführungszeichen sucht (die im Beispiel sowieso nicht vorhanden sind) und Alle sind zufrieden, Fall abgeschlossen.

Fall abgeschlossen?

Natürlich gibt es einen Unterschied zwischen einfachen und doppelten Anführungszeichen, aber um zu verstehen, was vor sich geht, müssen wir etwas tiefer graben.

Obwohl PHP eine interpretierte Sprache ist, verwendet es einen Kompilierungsschritt, bei dem bestimmte Teile zusammenspielen, um etwas zu erhalten, das die virtuelle Maschine tatsächlich ausführen kann, nämlich Opcodes. Wie kommen wir also vom PHP-Quellcode zu Opcodes?

Der Lexer

Der Lexer scannt die Quellcodedatei und zerlegt sie in Token. Ein einfaches Beispiel dafür, was das bedeutet, finden Sie in der Dokumentation der Funktion token_get_all(). Ein PHP-Quellcode von nur

T_OPEN_TAG (<?php )
T_ECHO (echo)
T_WHITESPACE ( )
T_CONSTANT_ENCAPSED_STRING ("")
Nach dem Login kopieren
Nach dem Login kopieren

Wir können dies in diesem 3v4l.org-Snippet in Aktion sehen und damit spielen.

Der Parser

Der Parser nimmt diese Token und generiert daraus einen abstrakten Syntaxbaum. Eine AST-Darstellung des obigen Beispiels sieht in JSON-Darstellung wie folgt aus:

{
  "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": ""
        }
      ]
    }
  ]
}
Nach dem Login kopieren

Falls Sie auch damit herumspielen und sehen möchten, wie der AST für anderen Code aussieht, habe ich https://phpast.com/ von Ryan Chandler und https://php-ast-viewer.com/ gefunden Beide zeigen Ihnen den AST eines bestimmten PHP-Codestücks.

Der Compiler

Der Compiler nimmt den AST und erstellt Opcodes. Die Opcodes sind die Dinge, die die virtuelle Maschine ausführt. Sie werden auch im OPcache gespeichert, wenn Sie dies eingerichtet und aktiviert haben (was ich sehr empfehle).

Um die Opcodes anzuzeigen, haben wir mehrere Möglichkeiten (vielleicht mehr, aber ich kenne diese drei):

  1. Verwenden Sie die vulcan Logic Dumper-Erweiterung. Es ist auch in 3v4l.org integriert
  2. verwenden Sie phpdbg -p script.php, um die Opcodes auszugeben
  3. Oder verwenden Sie die INI-Einstellung opcache.opt_debug_level für OPcache, um die Opcodes auszudrucken
    • Ein Wert von 0x10000 gibt Opcodes vor der Optimierung aus
    • Ein Wert von 0x20000 gibt Opcodes nach der Optimierung aus
$ echo '<?php echo "";' > foo.php
$ php -dopcache.opt_debug_level=0x10000 foo.php
$_main:
...
0000 ECHO string("")
0001 RETURN int(1)




</p>
<h2>
  
  
  Hypothese
</h2>

<p>Um auf die ursprüngliche Idee der Einsparung von CPU-Zyklen bei der Verwendung von einfachen Anführungszeichen gegenüber doppelten Anführungszeichen zurückzukommen: Ich denke, wir sind uns alle einig, dass dies nur dann zutrifft, wenn PHP diese Zeichenfolgen zur Laufzeit für jede einzelne Anfrage auswerten würde.</p>

<h2>
  
  
  Was passiert zur Laufzeit?
</h2>

<p>Mal sehen, welche Opcodes PHP für die beiden verschiedenen Versionen erstellt.</p>

<p>Doppelte Anführungszeichen:<br>
</p>

<pre class="brush:php;toolbar:false"><?php echo "apple";
Nach dem Login kopieren
0000 ECHO string("apple")
0001 RETURN int(1)
Nach dem Login kopieren
Nach dem Login kopieren

vs. einfache Anführungszeichen:

<?php echo 'apple';
Nach dem Login kopieren
0000 ECHO string("apple")
0001 RETURN int(1)
Nach dem Login kopieren
Nach dem Login kopieren

Hey, warte, etwas Seltsames ist passiert. Das sieht identisch aus! Wo ist meine Mikrooptimierung geblieben?

Nun, vielleicht, nur vielleicht analysiert die Implementierung des ECHO-Opcode-Handlers die angegebene Zeichenfolge, obwohl es keine Markierung oder etwas anderes gibt, das sie dazu auffordert ... hmm ?

Lassen Sie uns einen anderen Ansatz ausprobieren und sehen, was der Lexer in diesen beiden Fällen tut:

Doppelte Anführungszeichen:

T_OPEN_TAG (<?php )
T_ECHO (echo)
T_WHITESPACE ( )
T_CONSTANT_ENCAPSED_STRING ("")
Nach dem Login kopieren
Nach dem Login kopieren

vs. einfache Anführungszeichen:

Line 1: T_OPEN_TAG (<?php )
Line 1: T_ECHO (echo)
Line 1: T_WHITESPACE ( )
Line 1: T_CONSTANT_ENCAPSED_STRING ('')
Nach dem Login kopieren

Die Token unterscheiden immer noch zwischen doppelten und einfachen Anführungszeichen, aber die Überprüfung des AST liefert uns in beiden Fällen ein identisches Ergebnis – der einzige Unterschied ist der rawValue in den Scalar_String-Knotenattributen, der immer noch die einfachen/doppelten Anführungszeichen enthält, aber Der Wert verwendet in beiden Fällen doppelte Anführungszeichen.

Neue Hypothese

Könnte es sein, dass die String-Interpolation tatsächlich zur Kompilierzeit erfolgt?

Lassen Sie es uns anhand eines etwas „anspruchsvolleren“ Beispiels überprüfen:

<?php
$juice="apple";
echo "juice: $juice";
Nach dem Login kopieren

Tokens für diese Datei sind:

T_OPEN_TAG (<?php)
T_VARIABLE ($juice)
T_CONSTANT_ENCAPSED_STRING ("apple")
T_WHITESPACE ()
T_ECHO (echo)
T_WHITESPACE ( )
T_ENCAPSED_AND_WHITESPACE (juice: )
T_VARIABLE ($juice)
Nach dem Login kopieren

Look at the last two tokens! String interpolation is handled in the lexer and as such is a compile time thing and has nothing to do with runtime.

Too double quote or not, that

For completeness, let's have a look at the opcodes generated by this (after optimisation, using 0x20000):

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

This is different opcode than we had in our simple

Get to the point: should I concat or interpolate?

Let's have a look at these three different versions:

<?php
$juice = "apple";
echo "juice: $juice $juice";
echo "juice: ", $juice, " ", $juice;
echo "juice: ".$juice." ".$juice;
Nach dem Login kopieren
  • the first version is using string interpolation
  • the second is using a comma separation (which AFAIK only works with echo and not with assigning variables or anything else)
  • and the third option uses string concatenation

The first opcode assigns the string "apple" to the variable $juice:

0000 ASSIGN CV0($juice) string("apple")
Nach dem Login kopieren

The first version (string interpolation) is using a rope as the underlying data structure, which is optimised to do as little string copies as possible.

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
Nach dem Login kopieren

The second version is the most memory effective as it does not create an intermediate string representation. Instead it does multiple calls to ECHO which is a blocking call from an I/O perspective so depending on your use case this might be a downside.

0006 ECHO string("juice: ")
0007 ECHO CV0($juice)
0008 ECHO string(" ")
0009 ECHO CV0($juice)
Nach dem Login kopieren

The third version uses CONCAT/FAST_CONCAT to create an intermediate string representation and as such might use more memory than the rope version.

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

So ... what is the right thing to do here and why is it string interpolation?

String interpolation uses either a FAST_CONCAT in the case of echo "juice: $juice"; or highly optimised ROPE_* opcodes in the case of echo "juice: $juice $juice";, but most important it communicates the intent clearly and none of this has been bottle neck in any of the PHP applications I have worked with so far, so none of this actually matters.

TLDR

String interpolation is a compile time thing. Granted, without OPcache the lexer will have to check for variables used in double quoted strings on every request, even if there aren't any, waisting CPU cycles, but honestly: The problem is not the double quoted strings, but not using OPcache!

However, there is one caveat: PHP up to 4 (and I believe even including 5.0 and maybe even 5.1, I don't know) did string interpolation at runtime, so using these versions ... hmm, I guess if anyone really still uses PHP 5, the same as above applies: The problem is not the double quoted strings, but the use of an outdated PHP version.

Final advice

Update to the latest PHP version, enable OPcache and live happily ever after!

Das obige ist der detaillierte Inhalt vonZu doppeltes Anführungszeichen oder nicht, das ist hier die Frage!. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage