Skip to content
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

Performance optimizations #18

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

GromNaN
Copy link
Contributor

@GromNaN GromNaN commented Nov 28, 2024

  • Use use function to enable compiler optimization of some native functions.
  • Use preg_match('/(.).*\1/', $alphabet) to validate there is no duplicate char, faster than splitting into an array
  • Avoid splitting strings, and access chars directly with $string[$char]
  • Avoid functions with callback (array_reduce, array_filter), they are slower than foreach

Benchmark

PHPBench code
composer req --dev phpbench/phpbench

In phpbench.json

{
    "$schema": "./vendor/phpbench/phpbench/phpbench.schema.json",
    "runner.bootstrap": "vendor/autoload.php",
    "runner.file_pattern": "*Bench.php",
    "runner.path": "tests",
    "runner.iterations": 3
}

In tests/SqidsBench.php

<?php

namespace Sqids\Benchmark;

use PhpBench\Attributes\ParamProviders;
use PhpBench\Attributes\Revs;
use PhpBench\Attributes\Warmup;
use Sqids\Sqids;

#[Warmup(1)]
final class SqidsBench
{
    private const IDS = [
        'SvIzsqYMyQwI3GWgJAe17URxX8V924Co0DaTZLtFjHriEn5bPhcSkfmvOslpBu' => [0, 0],
        'n3qafPOLKdfHpuNw3M61r95svbeJGk7aAEgYn4WlSjXURmF8IDqZBy0CT2VxQc' => [0, 1],
        'tryFJbWcFMiYPg8sASm51uIV93GXTnvRzyfLleh06CpodJD42B7OraKtkQNxUZ' => [0, 2],
        'eg6ql0A3XmvPoCzMlB6DraNGcWSIy5VR8iYup2Qk4tjZFKe1hbwfgHdUTsnLqE' => [0, 3],
        'rSCFlp0rB2inEljaRdxKt7FkIbODSf8wYgTsZM1HL9JzN35cyoqueUvVWCm4hX' => [0, 4],
        'sR8xjC8WQkOwo74PnglH1YFdTI0eaf56RGVSitzbjuZ3shNUXBrqLxEJyAmKv2' => [0, 5],
        'uY2MYFqCLpgx5XQcjdtZK286AwWV7IBGEfuS9yTmbJvkzoUPeYRHr4iDs3naN0' => [0, 6],
        '74dID7X28VLQhBlnGmjZrec5wTA1fqpWtK4YkaoEIM9SRNiC3gUJH0OFvsPDdy' => [0, 7],
        '30WXpesPhgKiEI5RHTY7xbB1GnytJvXOl2p0AcUjdF6waZDo9Qk8VLzMuWrqCS' => [0, 8],
        'moxr3HqLAK0GsTND6jowfZz3SUx7cQ8aC54Pl1RbIvFXmEJuBMYVeW9yrdOtin' => [0, 9],
        'JSwXFaosANEOuLlYb3jHCBpeSzx7cPRrgf1dNTZqE4nDytU09isA5ahm6kKGvM' => [1_000_000, 2_000_000],
    ];

    #[Revs(1_000)]
    #[ParamProviders('provideSqids')]
    public static function benchEncodeDecode(array $params): void
    {
        foreach (self::IDS as $id => $numbers) {
            $params[0]->encode($numbers);
            $params[0]->decode($id);
        }
    }

    public static function provideSqids(): \Generator
    {
        yield 'default' => [
            new Sqids()
        ];
        yield 'custom blocklist' => [
            new Sqids(blocklist: [
                'JSwXFaosAN',
                'OCjV9JK64o',
                'rBHf',
                '79SM',
                '7tE6',
            ])
        ];
        yield 'no blocklist' => [
            new Sqids(blocklist: [])
        ];
    }
}

Before

    benchEncodeDecode # default.............I2 - Mo2.195ms (±0.47%)
    benchEncodeDecode # custom blocklist....I2 - Mo1.099ms (±0.84%)
    benchEncodeDecode # no blocklist........I2 - Mo929.423μs (±0.87%)

After

    benchEncodeDecode # default.............I2 - Mo994.363μs (±0.35%)
    benchEncodeDecode # custom blocklist....I2 - Mo681.353μs (±0.36%)
    benchEncodeDecode # no blocklist........I2 - Mo552.545μs (±0.21%)

@vinkla
Copy link
Collaborator

vinkla commented Nov 29, 2024

This looks good to me. I'll leave it up to @4kimov to merge this who has a deeper knowledge across our language implementations.

src/Sqids.php Outdated Show resolved Hide resolved
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants