"""Checking whether an array is empty with a strict comparison against the empty array is a common pattern in PHP. A GitHub search for "=== []" language:PHP reveals 44k hits. From the set of !$a, count($a) === 0, empty($a) and $a === [] it however is also the slowest option."""

https://github.com/php/php-src/pull/18571

This is a great example of how you should write whatever you find most readable and maintainable, and let us worry about efficiency. Wtih this PR, the "slow" approach becomes a "fast" one.

zend_vm: Add OPcode specialization for `=== []` by TimWolla · Pull Request #18571 · php/php-src

Checking whether an array is empty with a strict comparison against the empty array is a common pattern in PHP. A GitHub search for "=== []" language:PHP reveals 44k hits. From the set of...

GitHub
@pollita This is great! I’ve been using `=== []` because logic dictates it should be faster than a function call (i.e., `count($a) === 0`). I had no idea it was the slower option.

@ramsey @pollita sounds like $a++ is slower than ++$a because assembly used to have a different number of operations for both (or something like this)

Or COUNT(1) is faster than COUNT(*) because that last one first expands into the list of fields (disregarding the query optimizer)

Or beware the 6 fingers, that’s how you tell it’s ai generated

A lot of the early knowledge we took pains to gather, turns out to be noise

@GuillaumeRossolini @ramsey *Technically* $a++ is still slower than ++$a, because the former has to create a tempvar to save rhe value prior to the increment, what the latter can iincrement and just forward fhe new value.

Technically, because *every* compiler for *every* language quietly transforms $a++ into ++$a when it can see the result is not used.

@pollita @GuillaumeRossolini @ramsey Except C++, I guess 😜

https://godbolt.org/z/o48rcvGzz

#include <iostream>

struct Foo {
void operator++() {
std::cout << "pre\n";
}

void operator++(int) {
std::cout << "post\n";
}
};

int
main(void) {
Foo f;

f++;
}

Compiler Explorer - C++ (x86-64 gcc 15.1)

struct Foo { void operator++() { std::cout << "pre\n"; } void operator++(int) { std::cout << "post\n"; } }; int main(void) { Foo f; f++; }

@timwolla @GuillaumeRossolini @ramsey That's a contrived (and flawed) counter-example. The compiler can see that the operators are overridden, so it knows not to elide the side-effects. Same as it would if the result were consumed:

# int a; ++a;
add DWORD PTR [rbp-4], 1
# int b; b++;
add DWORD PTR [rbp-8], 1

@pollita @GuillaumeRossolini @ramsey Of course it is (as indicated by the Emoji) 😀
@timwolla @GuillaumeRossolini @ramsey Sorry, that seems obvious in hindsight. :p