-
Notifications
You must be signed in to change notification settings - Fork 7.9k
ext/random: Optimized getBytes
loop processing
#14891
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
rptr = bulk_convert_generated_result_to_char_64(rptr, result.result, &to_read); | ||
} else if (EXPECTED(result.size == sizeof(uint32_t))){ | ||
rptr = bulk_convert_generated_result_to_char_32(rptr, result.result, &to_read); | ||
} else { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a possibility that this else
will be executed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes. It can happen with userland engines that return single bytes:
final class MyEngine implements \Random\Engine {
public function generate(): string { return 'x'; }
}
$r = new \Random\Randomizer(new MyEngine());
var_dump($r->getBytes(10));
CI is red, I'll fix (edit) done |
fbb5635
to
49fa32e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you. I also noticed before that getBytes()
is slower than it could be.
I'm not too happy about the additional complexity introduced here and I would prefer a solution where the compiler itself detects that this effectively is a memcpy()
for little-endian architectures, while the C code stays high level and readable.
I'll try to experiment myself when I have some time to spare, given this is a self-contained change that does not change the behavior, we could still ship this with the PHP 8.4 Betas.
@TimWolla
I could probably simplify the code a bit more, but it would still be somewhat complicated. I'm going to simplify it a bit more so you can check back later to see if it's satisfactory to you :) |
efbe1d1
to
278a1d2
Compare
@TimWolla |
ce6d08a
to
b349c69
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Thanks for the good idea and implementation!
Thank you, I'll wait for Tim's opinion :) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I also fnd the added complexity to be slightly worrying considering how difficult randomness can be
ext/random/php_random.h
Outdated
/* Bytes swap */ | ||
#ifdef _MSC_VER | ||
# include <stdlib.h> | ||
# define RANDOM_BSWAP64(u) _byteswap_uint64(u) | ||
#else | ||
# ifdef __GNUC__ | ||
# define RANDOM_BSWAP64(u) __builtin_bswap64(u) | ||
# elif defined(__has_builtin) | ||
# if __has_builtin(__builtin_bswap64) | ||
# define RANDOM_BSWAP64(u) __builtin_bswap64(u) | ||
# endif // __has_builtin(__builtin_bswap64) | ||
# endif // __GNUC__ | ||
#endif // _MSC_VER | ||
#ifndef RANDOM_BSWAP64 | ||
static inline uint64_t RANDOM_BSWAP64(uint64_t u) | ||
{ | ||
return (((u & 0xff00000000000000ULL) >> 56) | ||
| ((u & 0x00ff000000000000ULL) >> 40) | ||
| ((u & 0x0000ff0000000000ULL) >> 24) | ||
| ((u & 0x000000ff00000000ULL) >> 8) | ||
| ((u & 0x00000000ff000000ULL) << 8) | ||
| ((u & 0x0000000000ff0000ULL) << 24) | ||
| ((u & 0x000000000000ff00ULL) << 40) | ||
| ((u & 0x00000000000000ffULL) << 56)); | ||
} | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Considering that if this lands, we would be implementing this sort of logic in different extensions, does it make sense to "upstream" this into Zend via the zend_portability.h
header?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah yes, that is probably wiser. I'll create a PR for that first.
As Tim says, this can be merged even in beta, so I'm in no rush to merge this. It can be thoroughly verified before being merged. |
Of course, if there is a more clever solution I'll be happy to close this PR. |
Split the changes into multiple commits to make it easier to see the changes. |
8fb5bd1
to
e96075c
Compare
2d198a7
to
c78d5a7
Compare
I have filed a competing PR at #15228. |
Tim's changes seem better so I'm going to close my PR :) |
All measurement results are from the latest commit.
Benchmark codes
Since the description is too long,
<?php
anduse
are omitted.Using PcgOneseq128XslRr64
0.php:
1.php:
2.php
Omit constructor arguments
n0.php:
n1.php:
n2.php:
Using PcgOneseq128XslRr64
before
after Optimized bit shifting
after Using memcpy
after Loop optimization
Omit constructor arguments
before
after