[RFC] Add Random Extension (before: Add Random class)

php.internals

zeriyoshi

5 years ago
Hello Internals. RFC has been reorganized for finalization. https://wiki.php.net/rfc/rng_extension The changes from the previous version are as follows: - Changed again to a class-based approach. The argument can be omitted, in which case an instance of XorShift128Plus will be created automatically. - Future scope was specified in the RFC and the functionality was separated as a Random extension. - Changed to separate it as a Random extension and use the appropriate namespace. - In order to extend the versatility of the final class, Random, a RandomInterface has been added, similar in approach to the DateTimeInterface. I've done a tidy implementation to make this final, but I'm currently suffering from error detection by Valgrind for unknown reasons. Implementation is here: https://github.com/php/php-src/pull/7079 This can be reproduced with the following code. ```sh # Success $ valgrind ./sapi/cli/php -r '$random = new Random(); $random->nextInt();' ==95522== Memcheck, a memory error detector ==95522== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==95522== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info ==95522== Command: ./sapi/cli/php -r $random\ =\ new\ Random();\ $random-\>nextInt(); ==95522== ==95522== ==95522== HEAP SUMMARY: ==95522== in use at exit: 1,286 bytes in 32 blocks ==95522== total heap usage: 28,445 allocs, 28,413 frees, 4,333,047 bytes allocated ==95522== ==95522== LEAK SUMMARY: ==95522== definitely lost: 0 bytes in 0 blocks ==95522== indirectly lost: 0 bytes in 0 blocks ==95522== possibly lost: 0 bytes in 0 blocks ==95522== still reachable: 1,286 bytes in 32 blocks ==95522== suppressed: 0 bytes in 0 blocks ==95522== Rerun with --leak-check=full to see details of leaked memory ==95522== ==95522== For counts of detected and suppressed errors, rerun with: -v ==95522== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) # Fail $ valgrind ./sapi/cli/php -r '$random = new Random(); $random->nextInt() === $random->nextInt();' ==95395== Memcheck, a memory error detector ==95395== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. ==95395== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info ==95395== Command: ./sapi/cli/php -r $random\ =\ new\ Random();\ $random-\>nextInt()\ ===\ $random-\>nextInt(); ==95395== ==95395== Conditional jump or move depends on uninitialised value(s) ==95395== at 0x966925: ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER (zend_vm_execute.h:27024) ==95395== by 0x99AC27: execute_ex (zend_vm_execute.h:57236) ==95395== by 0x99C902: zend_execute (zend_vm_execute.h:59026) ==95395== by 0x8DB6B4: zend_eval_stringl (zend_execute_API.c:1191) ==95395== by 0x8DB861: zend_eval_stringl_ex (zend_execute_API.c:1233) ==95395== by 0x8DB8D6: zend_eval_string_ex (zend_execute_API.c:1243) ==95395== by 0xA4DAE4: do_cli (php_cli.c:995) ==95395== by 0xA4E8E2: main (php_cli.c:1366) ==95395== ==95395== ==95395== HEAP SUMMARY: ==95395== in use at exit: 1,286 bytes in 32 blocks ==95395== total heap usage: 28,445 allocs, 28,413 frees, 4,333,070 bytes allocated ==95395== ==95395== LEAK SUMMARY: ==95395== definitely lost: 0 bytes in 0 blocks ==95395== indirectly lost: 0 bytes in 0 blocks ==95395== possibly lost: 0 bytes in 0 blocks ==95395== still reachable: 1,286 bytes in 32 blocks ==95395== suppressed: 0 bytes in 0 blocks ==95395== Rerun with --leak-check=full to see details of leaked memory ==95395== ==95395== For counts of detected and suppressed errors, rerun with: -v ==95395== Use --track-origins=yes to see where uninitialised values come from ==95395== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) ``` However, the detection is internal to the Zend VM and the cause has not been identified. From the code, it looks like memory management is being done properly. I have a somewhat tricky way of allocating memory to make the process common, do I need to give some hints to Valgrind? If you know, I would appreciate your advice on this issue. Regards, Go Kudo

Kamil Tekiela

5 years ago
Hi Go Kudo, I find this iteration acceptable, but I have one last complaint. Why the double namespace? Can it not be simply Random/RandomNumberGenerator? Can you also clarify what happens when serialization or cloning fails? Regards, Kamil

zeriyoshi

5 years ago
> Can it not be simply Random/RandomNumberGenerator?
The interface should be named NumberGenerator\Generator, but since it is confused with the built-in Generator, it is named RandomNumberGenerator. The reason for using the NumberGenerator namespace is that some class using random numbers may be implemented in the future.
> Can you also clarify what happens when serialization or cloning fails?
OK, I've updated it. But these are not special behaviors, they are built on top of the standard PHP mechanisms. Regards, Go Kudo 2021年6月26日(土) 17:55 Kamil Tekiela <tekiela246@gmail.com>:

Mel Dafert

5 years ago
On 26 June 2021 02:39:52 CEST, Go Kudo <zeriyoshi@gmail.com> wrote:
>Hello Internals. > >RFC has been reorganized for finalization. > >https://wiki.php.net/rfc/rng_extension > >The changes from the previous version are as follows: > >- Changed again to a class-based approach. The argument can be omitted, in >which case an instance of XorShift128Plus will be created automatically. >- Future scope was specified in the RFC and the functionality was separated >as a Random extension. >- Changed to separate it as a Random extension and use the appropriate >namespace. >- In order to extend the versatility of the final class, Random, a >RandomInterface has been added, similar in approach to the >DateTimeInterface. > >I've done a tidy implementation to make this final, but I'm currently >suffering from error detection by Valgrind for unknown reasons. > >Implementation is here: https://github.com/php/php-src/pull/7079 > >This can be reproduced with the following code. > >```sh ># Success >$ valgrind ./sapi/cli/php -r '$random = new Random(); $random->nextInt();' >==95522== Memcheck, a memory error detector >==95522== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. >==95522== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info >==95522== Command: ./sapi/cli/php -r $random\ =\ new\ Random();\ >$random-\>nextInt(); >==95522== >==95522== >==95522== HEAP SUMMARY: >==95522== in use at exit: 1,286 bytes in 32 blocks >==95522== total heap usage: 28,445 allocs, 28,413 frees, 4,333,047 bytes >allocated >==95522== >==95522== LEAK SUMMARY: >==95522== definitely lost: 0 bytes in 0 blocks >==95522== indirectly lost: 0 bytes in 0 blocks >==95522== possibly lost: 0 bytes in 0 blocks >==95522== still reachable: 1,286 bytes in 32 blocks >==95522== suppressed: 0 bytes in 0 blocks >==95522== Rerun with --leak-check=full to see details of leaked memory >==95522== >==95522== For counts of detected and suppressed errors, rerun with: -v >==95522== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0) > ># Fail >$ valgrind ./sapi/cli/php -r '$random = new Random(); $random->nextInt() >=== $random->nextInt();' >==95395== Memcheck, a memory error detector >==95395== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al. >==95395== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info >==95395== Command: ./sapi/cli/php -r $random\ =\ new\ Random();\ >$random-\>nextInt()\ ===\ $random-\>nextInt(); >==95395== >==95395== Conditional jump or move depends on uninitialised value(s) >==95395== at 0x966925: ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER >(zend_vm_execute.h:27024) >==95395== by 0x99AC27: execute_ex (zend_vm_execute.h:57236) >==95395== by 0x99C902: zend_execute (zend_vm_execute.h:59026) >==95395== by 0x8DB6B4: zend_eval_stringl (zend_execute_API.c:1191) >==95395== by 0x8DB861: zend_eval_stringl_ex (zend_execute_API.c:1233) >==95395== by 0x8DB8D6: zend_eval_string_ex (zend_execute_API.c:1243) >==95395== by 0xA4DAE4: do_cli (php_cli.c:995) >==95395== by 0xA4E8E2: main (php_cli.c:1366) >==95395== >==95395== >==95395== HEAP SUMMARY: >==95395== in use at exit: 1,286 bytes in 32 blocks >==95395== total heap usage: 28,445 allocs, 28,413 frees, 4,333,070 bytes >allocated >==95395== >==95395== LEAK SUMMARY: >==95395== definitely lost: 0 bytes in 0 blocks >==95395== indirectly lost: 0 bytes in 0 blocks >==95395== possibly lost: 0 bytes in 0 blocks >==95395== still reachable: 1,286 bytes in 32 blocks >==95395== suppressed: 0 bytes in 0 blocks >==95395== Rerun with --leak-check=full to see details of leaked memory >==95395== >==95395== For counts of detected and suppressed errors, rerun with: -v >==95395== Use --track-origins=yes to see where uninitialised values come >from >==95395== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0) >``` > >However, the detection is internal to the Zend VM and the cause has not >been identified. From the code, it looks like memory management is being >done properly. > >I have a somewhat tricky way of allocating memory to make the process >common, do I need to give some hints to Valgrind? > >If you know, I would appreciate your advice on this issue. > >Regards, >Go Kudo
>Hello Internals. > >RFC has been reorganized for finalization. > >https://wiki.php.net/rfc/rng_extension
I think this is a good reorganization. I would like to point out that this does not quite follow the Namespace Policy (https://wiki.php.net/rfc/namespaces_in_bundled_extensions): Notably it says:
> All symbols defined in the extension should be part of the extension's top-level > namespace or a sub-namespace.
This means that the Random class and RandomInterface interface should be Random\Random and Random\RandomInterface respectively. The symbols in the Random\NumberGenerator sub-namespace are okay, as per the policy. Note, however, that the policy says "should", and if there is a good argument made, the guidelines must not be followed.

Larry Garfield

5 years ago
On Fri, Jun 25, 2021, at 7:39 PM, Go Kudo wrote:
> Hello Internals. > > RFC has been reorganized for finalization. > > https://wiki.php.net/rfc/rng_extension > > The changes from the previous version are as follows: > > - Changed again to a class-based approach. The argument can be omitted, in > which case an instance of XorShift128Plus will be created automatically. > - Future scope was specified in the RFC and the functionality was separated > as a Random extension. > - Changed to separate it as a Random extension and use the appropriate > namespace. > - In order to extend the versatility of the final class, Random, a > RandomInterface has been added, similar in approach to the > DateTimeInterface. > > I've done a tidy implementation to make this final, but I'm currently > suffering from error detection by Valgrind for unknown reasons. > > Implementation is here: https://github.com/php/php-src/pull/7079 > > This can be reproduced with the following code.
This looks a lot nicer! Question: Why `interface RandomInterface` but `interface RandomNumberGenerator`? I would expect either both to have an Interface suffix or neither to. (Preferably neither.) For that matter, I don't get why RandomInterface exists, if you'll just always use Random all the time, and it's final. --Larry Garfield

Nikita Popov

5 years ago
On Sat, Jun 26, 2021 at 2:40 AM Go Kudo <zeriyoshi@gmail.com> wrote:
> Hello Internals. > > RFC has been reorganized for finalization. > > https://wiki.php.net/rfc/rng_extension > > The changes from the previous version are as follows: > > - Changed again to a class-based approach. The argument can be omitted, in > which case an instance of XorShift128Plus will be created automatically. > - Future scope was specified in the RFC and the functionality was separated > as a Random extension. > - Changed to separate it as a Random extension and use the appropriate > namespace. > - In order to extend the versatility of the final class, Random, a > RandomInterface has been added, similar in approach to the > DateTimeInterface. >
The updated proposal looks quite nice :) I think this is close to done. Some small bits of feedback: * The first bit is just clarification. After a cursory look at the implementation, my understanding is that the getInt(), shuffleArray() and shuffleString() APIs will always produce consistent results on 32-bit and 64-bit, as long as your inputs are 32-bit as well (i.e., min/max are 32-bit and string is smaller than 4G). Is that correct? The only APIs that would exhibit different behavior are nextInt() and getBytes(), right? * Looking at the implementation, nextInt() performs a >> 1 operation on the RNG result. I assume the motivation is to get back a non-negative number. But why do we want that? The "nextInt()" name doesn't really indicate that it's a positive number. I think more generally, my question here may be "Why does this method exist at all? When would you use it instead of getInt()?" * Another bit of clarification: For the user-defined RNG, which range is generate() expected to return? I assume that it must return the native integer size, i.e. 32-bit on 32-bit and 64-bit on 64-bit? * I don't really get why we need RandomInterface. I think if the choice is between "final + interface" and "non-final without interface", I'd prefer the latter (though I'm also happy with "final without interface"). * I'm not entirely happy with the naming. Unfortunately, I don't have great suggestions either. I think in your current hierarchy, I would make the interface Random\NumberGenerator (with implementation in the sub-namespace), rather than Random\NumberGenerator\RandomNumberGenerator. Regards, Nikita I've done a tidy implementation to make this final, but I'm currently

zeriyoshi

5 years ago
> * The first bit is just clarification. After a cursory look at the
implementation, my understanding is that the getInt(), shuffleArray() and shuffleString() APIs will always produce consistent results on 32-bit and 64-bit, as long as your inputs are 32-bit as well (i.e., min/max are 32-bit and string is smaller than 4G). Is that correct? The only APIs that would exhibit different behavior are nextInt() and getBytes(), right? Yes. I do not want to break the compatibility of the implementation. I would prefer to be able to migrate code that uses the current internal state.
> * Looking at the implementation, nextInt() performs a >> 1 operation on
the RNG result. I assume the motivation is to get back a non-negative number. But why do we want that? The "nextInt()" name doesn't really indicate that it's a positive number. I think more generally, my question here may be "Why does this method exist at all? When would you use it instead of getInt()?" This was to allow for future forward compatibility. When PHP_INT_SIZE exceeds 8, the result will be incompatible without bit shifting. This is similar to the way mt_rand() does bit shifting now. However, I can agree that such a day will never come in reality. And as the comments on GitHub show, there are ways to keep the values compatible even if such a time comes. After thinking about it for a while, I finally came to the conclusion that there is no benefit to this other than to make mt_rand() and Random\NumberGenerator\MT19937 directly compatible. If compatibility is needed, it can be achieved by bit shifting in the PHP code, so direct compatibility is probably unnecessary. I will change the implementation and remove this option.
> "Why does this method exist at all? When would you use it instead of
getInt()?" The case for this would be if you want to get a raw unrounded random number sequence as a number. The situations where this is required would certainly be limited, but it would be nice to have. (At least, I know of several production codes that use the result of mt_rand() with no arguments.)
> * I don't really get why we need RandomInterface. I think if the choice
is between "final + interface" and "non-final without interface", I'd prefer the latter (though I'm also happy with "final without interface"). I had completely lost my train of thought on this. The interface makes the Random class unextensible. I have removed this.
> I'm not entirely happy with the naming. Unfortunately, I don't have
great suggestions either. I think in your current hierarchy, I would make the interface Random\NumberGenerator (with implementation in the sub-namespace), rather than Random\NumberGenerator\RandomNumberGenerator. Deep-rooted problem. For now, I'm going to change RandomNumberGenerator to Random\NumberGenerator. It's the best one so far. I continue to be plagued by Valgrind warnings and crashes of Windows ZTS builds... I'd like to make a voting phase that is fixed ... Regards, Go Kudo 2021年6月29日(火) 23:01 Nikita Popov <nikita.ppv@gmail.com>:

=?utf-8?B?5rGf5rmW5aSn6Jm+5LuB?=

5 years ago
>> "Why does this method exist at all? When would you use it instead of >> getInt()?" >> > The case for this would be if you want to get a raw unrounded random number sequence as a number. The situations where this is required would certainly be limited, but it would be nice to have. (At least, I know of several production codes that use the result of mt_rand() with no arguments.)
These two methods confused me at first as well, but I think it's ok with me after I check the documentation of mt_rand(), which also supports calling without range. So, compatibility is one of the reasons why this method exists, although I still feel we should find a better name for them. They are too similar now, you won't be able to tell the difference without looking into the documentation or source code. Besides the name issue, I have another question for nextInt(). What's the range of its return? It's not clear in the RFC. The range of mt_rand() (without min and max) is 0 to mt_getrandmax(), so how about nextInt()? is there any equivalent method/constant for it? Regards, CHU Zhaowei

zeriyoshi

5 years ago
I was late in noticing the email. I'm sorry.
> I still feel we should find a better name for them.
This is based on Java's Random.nextInt(), which may indeed be confusing. How about generateInt()?
> What's the range of its return? It's not clear in the RFC.
Currently, there is no way to check this, but we believe that since the RNG implementation is now class-based, there is no need to check this anymore. The size of the RNG to be generated is clear at the time of implementation, and implementing a way to check this would override the method and break consistency. Regards, Go Kudo 2021年7月3日(土) 4:15 CHU Zhaowei <me@jhdxr.com>:

Nikita Popov

5 years ago
On Fri, Jul 2, 2021 at 3:58 PM Go Kudo <zeriyoshi@gmail.com> wrote:
> > * The first bit is just clarification. After a cursory look at the > implementation, my understanding is that the getInt(), shuffleArray() and > shuffleString() APIs will always produce consistent results on 32-bit and > 64-bit, as long as your inputs are 32-bit as well (i.e., min/max are 32-bit > and string is smaller than 4G). Is that correct? The only APIs that would > exhibit different behavior are nextInt() and getBytes(), right? > > Yes. I do not want to break the compatibility of the implementation. I > would prefer to be able to migrate code that uses the current internal > state. > > > * Looking at the implementation, nextInt() performs a >> 1 operation on > the RNG result. I assume the motivation is to get back a non-negative > number. But why do we want that? The "nextInt()" name doesn't really > indicate that it's a positive number. I think more generally, my question > here may be "Why does this method exist at all? When would you use it > instead of getInt()?" > > This was to allow for future forward compatibility. When PHP_INT_SIZE > exceeds 8, the result will be incompatible without bit shifting. This is > similar to the way mt_rand() does bit shifting now. > > However, I can agree that such a day will never come in reality. And as > the comments on GitHub show, there are ways to keep the values compatible > even if such a time comes. > > After thinking about it for a while, I finally came to the conclusion that > there is no benefit to this other than to make mt_rand() and > Random\NumberGenerator\MT19937 directly compatible. > If compatibility is needed, it can be achieved by bit shifting in the PHP > code, so direct compatibility is probably unnecessary. I will change the > implementation and remove this option. > > > "Why does this method exist at all? When would you use it instead of > getInt()?" > > The case for this would be if you want to get a raw unrounded random > number sequence as a number. The situations where this is required would > certainly be limited, but it would be nice to have. (At least, I know of > several production codes that use the result of mt_rand() with no > arguments.) >
Could you share some example of where you use it? Maybe that will help understand the motivation for it. Also, I think it's worth pointing out that it's always possible to use $random->getNumberGenerator()->generate() to access the raw RNG stream. Regards, Nikita

zeriyoshi

5 years ago
> Could you share some example of where you use it?
It looks like mt_rand() could be replaced by mt_rand(0, getrandmax()), but that is not the case, mt_rand() with a specified range is an implementation that generates random numbers until the desired value is obtained, which may unintentionally advance the random state. This can be undesirable for pseudo-random numbers with periodicity. Also, shouldn't compatibility with mt_rand() be maintained? Currently, NumberGenerator\MT19937 is fully compatible with mt_rand(), do We need to drop it?
> $random->getNumberGenerator()->generate() to access the raw RNG stream.
Indeed. I think nextInt() can be removed from Random, since it currently returns exactly the same value. (However, I think NumberGenerator::generate() should be kept). Regards, Go Kudo 2021年7月6日(火) 23:35 Nikita Popov <nikita.ppv@gmail.com>:

Nikita Popov

5 years ago
On Tue, Jul 6, 2021 at 4:54 PM Go Kudo <zeriyoshi@gmail.com> wrote:
> > Could you share some example of where you use it? > > It looks like mt_rand() could be replaced by mt_rand(0, getrandmax()), but > that is not the case, mt_rand() with a specified range is an implementation > that generates random numbers until the desired value is obtained, which > may unintentionally advance the random state. This can be undesirable for > pseudo-random numbers with periodicity. > > Also, shouldn't compatibility with mt_rand() be maintained? Currently, > NumberGenerator\MT19937 is fully compatible with mt_rand(), do We need to > drop it? > > > $random->getNumberGenerator()->generate() to access the raw RNG stream. > > Indeed. I think nextInt() can be removed from Random, since it currently > returns exactly the same value. (However, I think > NumberGenerator::generate() should be kept). >
Yes, I think that would be best. As the value returned by nextInt() is already available through generate(), and use cases for nextInt() probably aren't common, I don't think we need the separate nextInt() method. We can always add it later if it turns out to be a common requirement (but not the other way around...) Regards, Nikita

Remi Collet

5 years ago
Le 26/06/2021 à 02:39, Go Kudo a écrit :
> Hello Internals. > > RFC has been reorganized for finalization. > > https://wiki.php.net/rfc/rng_extension
1st I dislike the name "random_ext", why this "_ext" part ? 2nd why not following the standard process ? 1/ publish on pecl 2/ merge in php-src if enough success and good feedback Remi

zeriyoshi

5 years ago
> 1st
This is to avoid conflicts with the implementation in ext/standard. I don't want to do it this way either, but I have to do it this way. Since random in ext/standard does not use namespaces, I would like to change the ext/standard side.
> 2nd
Although it goes back quite a long time, this implementation was originally based on an extension I submitted to PECL. https://pecl.php.net/package/orng After I posted this to PECL, I found that an object scope RNG had been proposed in the past in the Internals ML, and there was positive feedback about it. https://externals.io/message/112525 However, the proposal never actually took place. This RFC is a realization of that proposal. Is that what you asked? Regards, Go Kudo 2021年7月6日(火) 22:46 Remi Collet <remi@php.net>:

Nikita Popov

5 years ago
On Tue, Jul 6, 2021 at 4:38 PM Go Kudo <zeriyoshi@gmail.com> wrote:
> > 1st > > This is to avoid conflicts with the implementation in ext/standard. I don't > want to do it this way either, but I have to do it this way. > Since random in ext/standard does not use namespaces, I would like to > change the ext/standard side. >
To clarify, are you referring to the php_random.h header in ext/standard? I agree with Remi that the extension should be in ext/random, not ext/random_ext. We can rename the ext/standard header. Alternatively, you could also use ext/rng, with names RNG\Random, RNG\NumberGenerator\XorShift128Plus etc. Regards, Nikita

zeriyoshi

5 years ago
> We can rename the ext/standard header.
OK. I'll rename random in ext/standard. This will not be BC break maybe. 2021年7月7日(水) 19:32 Nikita Popov <nikita.ppv@gmail.com>:

zeriyoshi

5 years ago
Incidentally, what would be the preferred name for the ext/standard random? I was going to rename it to random_func, but I have a feeling that would be controversial. - random_func.c / php_random_func.h / RANDOM_FUNC_G / php_random_func_bytes() / php_random_func_int() - std_random.c ... - standard_random.c ... Which would be better? Regards, Go Kudo 2021年7月7日(水) 19:32 Nikita Popov <nikita.ppv@gmail.com>:

Nikita Popov

5 years ago
On Wed, Jul 7, 2021 at 2:33 PM Go Kudo <zeriyoshi@gmail.com> wrote:
> Incidentally, what would be the preferred name for the ext/standard random? > I was going to rename it to random_func, but I have a feeling that would > be controversial. > > - random_func.c / php_random_func.h / RANDOM_FUNC_G / > php_random_func_bytes() / php_random_func_int() > - std_random.c ... > - standard_random.c ... > > Which would be better? >
We already have another php_rand.h header, so I think you can just merge them. Name of the C file shouldn't matter. Regards, Nikita

zeriyoshi

5 years ago
We'll do it that way. Thanks for fixing the memory issue. I'm not quite sure I understand the principle, so I will investigate. By the way, are you working on something now? If so, I'll pause the work. Regards, Go Kudo 2021年7月7日(水) 21:41 Nikita Popov <nikita.ppv@gmail.com>:

zeriyoshi

5 years ago
Hello Internals. I mistakenly thought there was still time, but voting for a new RFC for PHP 8.1 has already closed. I believe that an object-scoped random number generator is a necessity for PHP and I will continue to work on it. We will continue to improve the RFC. I will also work on getting it published in PECL so that features are available quickly. Regards, Go Kudo 2021年6月26日(土) 9:39 Go Kudo <zeriyoshi@gmail.com>: