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

Improve performance of getValueByPath() #126

Open
samdark opened this issue Mar 2, 2023 · 4 comments
Open

Improve performance of getValueByPath() #126

samdark opened this issue Mar 2, 2023 · 4 comments
Labels
status:ready for adoption Feel free to implement this issue. type:enhancement Enhancement

Comments

@samdark
Copy link
Member

samdark commented Mar 2, 2023

No description provided.

@samdark samdark added type:enhancement Enhancement status:ready for adoption Feel free to implement this issue. labels Mar 2, 2023
@butschster
Copy link

Here is a benchamark code

<?php

declare(strict_types=1);

namespace App\Endpoint\Console;

use Illuminate\Support\Arr;
use Spiral\Console\Command;
use DragonCode\Benchmark\Benchmark;
use Spiral\Http\Request\InputBag;
use Yiisoft\Arrays\ArrayHelper;

class BenchCommand extends Command
{
    protected const NAME = 'bench';
    protected const DESCRIPTION = '';

    private const ARR_PATH = 'foo.quux.corge.grault.garply.xyzzy.quux.corge.grault.garply.xyzzy.quux.corge.grault.garply.xyzzy.quux.corge.grault.garply.xyzzy.thud';

    protected function perform(): void
    {
        $array = $this->getArray();

        $bag = new InputBag($array);

        (new Benchmark())
            ->iterations(100000)
            ->withoutData()
            ->compare([
                'Spiral' => fn () => $bag->get(self::ARR_PATH),
                'Yii' => fn () => ArrayHelper::getValueByPath(
                    $array,
                    self::ARR_PATH,
                ),
                'Laravel' => fn () => Arr::get(
                    $array,
                    self::ARR_PATH,
                ),
            ]);
    }

    private function getArray(): array
    {
        return [
            'foo' => [
                'bar' => [
                    'baz' => 'qux',
                ],
                'quux' => [
                    'corge' => [
                        'grault' => [
                            'garply' => [
                                'waldo' => [
                                    'fred' => 'plugh',
                                ],
                                'xyzzy' => [
                                    'quux' => [
                                        'corge' => [
                                            'grault' => [
                                                'garply' => [
                                                    'waldo' => [
                                                        'fred' => 'plugh',
                                                    ],
                                                    'xyzzy' => [
                                                        'quux' => [
                                                            'corge' => [
                                                                'grault' => [
                                                                    'garply' => [
                                                                        'waldo' => [
                                                                            'fred' => 'plugh',
                                                                        ],
                                                                        'xyzzy' => [
                                                                            'quux' => [
                                                                                'corge' => [
                                                                                    'grault' => [
                                                                                        'garply' => [
                                                                                            'waldo' => [
                                                                                                'fred' => 'plugh',
                                                                                            ],
                                                                                            'xyzzy' => [
                                                                                                'thud' => 'Hello world!',
                                                                                            ],
                                                                                        ],
                                                                                    ],
                                                                                ],
                                                                            ],
                                                                        ],
                                                                    ],
                                                                ],
                                                            ],
                                                        ],
                                                    ],
                                                ],
                                            ],
                                        ],
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
            'garply' => [
                'waldo' => [
                    'fred' => 'plugh',
                ],
                'xyzzy' => [
                    'thud' => 'thud',
                ],
            ],
            'thud' => [
                'thud' => [
                    'thud' => 'thud',
                ],
            ],
        ];
    }
}

And results

image

@vjik
Copy link
Member

vjik commented Mar 2, 2023

Seems, problem here:

https://github.com/yiisoft/strings/blob/b35142c92c8108a872b0ed5d83d2c62426a056dd/src/StringHelper.php#L538

It's allow escape separate symbols. For example:

array: ['x']['a.b']['c']
path: x.a\.b.c

For boost may prepare key via explode('.', self::ARR_PATH).

@samdark
Copy link
Member Author

samdark commented Mar 2, 2023

Need to try this:

<?php

$key = 'x.a\.b.c';

$parts = splitIt($key);
var_dump($parts);

function splitIt(string $key, string $delimiter = '.', $escape = '\\')
{
    $prev = 0;
    $parts = [];
        
    for ($i = 0, $len = strlen($key); $i < $len; $i++) {
        if ($key[$i] === $delimiter && ($i === 0 || $key[$i-1] !== $escape)) {
            $parts[] = str_replace($escape, '', substr($key, $prev, $i - $prev));
            $prev = $i + 1;
        }
    }
    $parts[] = substr($key, $prev, $i - $prev);
    return $parts;
}

@samdark
Copy link
Member Author

samdark commented Mar 2, 2023

Also

$array = preg_split('~\\\\.(*SKIP)(*FAIL)|\|~s', $string);

See https://stackoverflow.com/questions/6243778/split-string-by-delimiter-but-not-if-it-is-escaped

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status:ready for adoption Feel free to implement this issue. type:enhancement Enhancement
Projects
None yet
Development

No branches or pull requests

3 participants