A tweak tosprintf
.
Just fiddling around and stumbled on this change.
Consider the statement $m =sprintf("Message (%s): %s\n", date('Y-m-d h:i:s'), $message_slug);
. This could have been written more performantly as $m = "Message (" . date('Y-m-d h:i:s') . "): $message_slug\n";
, but that's harder to read and more fraught if the format changes.
In PHP 8.3, the bytecode for that sprintf
call would look something like:
INIT_FCALL 3 128 string("sprintf")
SEND_VAL string("Message (%s): %s\n") 1
INIT_FCALL 1 96 string("date")
SEND_VAL string("Y-m-d h:i:s") 1
V1 = DO_ICALL
SEND_VAR V1 2
SEND_VAR CV0($message_slug) 3
V2 = DO_ICALL
In 8.4, it becomes
INIT_FCALL 1 96 string("date")
SEND_VAL string("Y-m-d h:i:s") 1
V1 = DO_ICALL
T3 = ROPE_INIT 5 string("Message (")
T3 = ROPE_ADD 1 T3 V1
T3 = ROPE_ADD 2 T3 string("): ")
T3 = ROPE_ADD 3 T3 CV0($message_slug)
T2 = ROPE_END 4 T3 string("\n")
Yes, that's exactly what it looks like: what you'd have if you'd written $temp = date('Y-m-d h:i:s'); $m ="Message ($temp): $message_slug\n";
Basically, what happens is that a v?[sf]?printf()
call in which the format pattern contains only plain %s
(and %d
) specifiers is converted into concatenations before being compiled to bytecode. PHP is very efficient at concatenating strings, and this also saves the costs of a function call and parsing the format string. Win-win-win.
There are limitations. As soon as any format specifier gets fancier (like %14s
) then it's back to a sprintf
call. Also, the format string has to be provided literally, so it won't work if said format came from, say, an i18n multilingual collection.