amphp / parallel

An advanced parallelization library for PHP, enabling efficient multitasking, optimizing resource use, and application responsiveness through multiple CPU threads.
MIT License
781 stars 64 forks source link

Cannot `serialize()` object returned from worker pool "Serialization of 'class@anonymous' is not allowed" #80

Closed andrewdalpino closed 4 years ago

andrewdalpino commented 5 years ago

Hi @kelunik

So far Amp Parallel has been working fantastic in Rubix ML

I noticed an issue when saving the models (that implement Parallel i.e. that do multiprocessing under the hood) created in Rubix after training.

Here's the stack trace

PHP Fatal error:  Uncaught Exception: Serialization of 'class@anonymous' is not allowed in C:\Users\User\Wo
rkspace\Rubix\Autism\vendor\rubix\ml\src\Persisters\Serializers\Native.php:26
Stack trace:
#0 [internal function]: SplObjectStorage->serialize()
#1 C:\Users\User\Workspace\Rubix\Autism\vendor\rubix\ml\src\Persisters\Serializers\Native.php(26): serializ
e(Object(Rubix\ML\Pipeline))
#2 C:\Users\User\Workspace\Rubix\Autism\vendor\rubix\ml\src\Persisters\Filesystem.php(87): Rubix\ML\Persist
ers\Serializers\Native->serialize(Object(Rubix\ML\Pipeline))
#3 C:\Users\User\Workspace\Rubix\Autism\vendor\rubix\ml\src\PersistentModel.php(160): Rubix\ML\Persisters\F
ilesystem->save(Object(Rubix\ML\Pipeline))
#4 C:\Users\User\Workspace\Rubix\Autism\train.php(75): Rubix\ML\PersistentModel->save()
#5 {main}
  thrown in C:\Users\User\Workspace\Rubix\Autism\vendor\rubix\ml\src\Persisters\Serializers\Native.php on l
ine 26

This error does not occur when saving a Parallel learner using the Serial backend under the hood.

My guess is that somewhere in the process an anonymous object is getting injected somewhere but you'll probably know better than me

Thanks again for making such a great impact on Rubix

Andrew

kelunik commented 5 years ago

Hey Andrew,

I don't know where that happens, but there aren't many anonymous classes in the vendor directory of your project.

➜ composer install --ignore-platform-reqs --no-dev
➜ rgrep 'new class' vendor           
vendor/amphp/amp/docs/utils/struct.md:$obj = new class {
vendor/amphp/amp/docs/utils/struct.md:$obj = new class {
vendor/amphp/amp/lib/Loop.php:            self::$driver = new class extends Driver {
vendor/amphp/amp/lib/Deferred.php:        $this->resolver = new class implements Promise {
vendor/amphp/amp/lib/CancellationTokenSource.php:        $this->token = new class($this->onCancel) implements CancellationToken {
vendor/amphp/amp/lib/Emitter.php:        $this->emitter = new class implements Iterator {
vendor/amphp/parallel/lib/Worker/BasicEnvironment.php:        $struct = new class {

Usually, PHP prints the location of the anonymous class right after class@anonymous, but unfortunately, exceptions aren't NUL-byte safe and thus the location is lost.

➜ php -r 'var_dump(get_class(new class {}));'
Command line code:1:
string(47) "class@anonymous\000Command line code0x7f9a1da7a136"

Maybe you can get the class name from var_dump'ing $persistable right before the serialize call?

kelunik commented 4 years ago

I'm closing this due to the lack of activity.