Skip to content

Benchmarks & How to properly bind a Singleton in the Laravel service container #10

@emmadesilva

Description

@emmadesilva

Benchmarks using Laravel 9, PHP 8, (16 cores @ 3.60GHz)

About:

Sorry for any bad formatting. This was just a quick test I did and thought I would share :)

Test 1: Initializing generator outside the loop

$zooIdGen = RobThree\HumanoID\HumanoIDs::zooIdGenerator();
while ($i <= 1000) {
  $zooId = $zooIdGen->create($i);
  echo $zooId . '<br>';
  $i++;
}

Result: 10 000 loops took 1.3485219478607 seconds
Average: 0.13485219 milliseconds per iteration
Peak CPU utilization: ~12%

Test 2: Initializing the generator in each loop

while ($i <= 1000) {
  $zooIdGen = RobThree\HumanoID\HumanoIDs::zooIdGenerator();
  $zooId = $zooIdGen->create($i);
  echo $zooId . '<br>';
  $i++;
}

Result: Crashed after 615 iterations
Peak CPU utilazation: ~27%

Eventually finished with the following results
Result: 1000 loops took 22.121620178223 seconds
Average: 22.12162018 milliseconds per iteration

Test 3: Initializing the generator as a singleton in the service container

// In AppServiceProvider
$this->app->singleton('HumanoIDs', function ($app) {
  return new HumanoIDs($app->make(HumanoIDs::class));
});

// Benchmark
while ($i <= 10000) {
  $zooId = app('HumanoIDs')->generator->create($i);
  echo $zooId . '<br>';
  $i++;
}

Result: 10000 loops took 22.320996999741 seconds
Average: 2.2320997 milliseconds per iteration
Peak CPU utilazation: ~21%

This actually suprised me as I thought the result between test 1 and 3 would be much closer. This makes me think that I need to bind the actual generator to the service container instead.

Test 4: Initializing the generator in the service container by binding the generator method

// In AppServiceProvider
$this->app->singleton('HumanoIDGenerator', function ($app) {
  return new HumanoIDGenerator($app->make(HumanoIDGenerator::class));
});

// Intermediary class:
class HumanoIDGenerator
{
  public \RobThree\HumanoID\HumanoID $generator;
  
  public function __construct()
  {
    $this->generator = \RobThree\HumanoID\HumanoIDs::zooIdGenerator();
  }
}

// Benchmark
while ($i <= 10000) {
  $zooId = app('HumanoIDGenerator')->generator->create($i);
  echo $zooId . '<br>';
  $i++;
}

Result: 10000 loops took 1.5630679130554 seconds
Average: 0.15630679 milliseconds per iteration
Peak CPU utilazation: ~12% for a short spike

This is just a tiny tiny bit slower than the first test, which is just what I initially expected.

Conclusion

When using Laravel, make sure to bind the actual generator to the service container and not just the main class.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions