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 (in that particular situation you're probably better served by the Intl extension's MessageFormatter class).