-
Notifications
You must be signed in to change notification settings - Fork 11.3k
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
[5.2] Validation performance optimisation #12651
Conversation
I'm not sure it's a safe idea to bring dot notation in
To be more consistent your I think the best solution might be to not touch |
$attributeData = []; | ||
|
||
foreach ((array) $keys as $key) { | ||
if (! $keyValue = data_get($array, $key)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You miss all falsy values because of this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmmm, this one is to pass the following test:
$array = ['name' => 'taylor', 'age' => 26];
$this->assertEquals(['name' => 'taylor'], array_only($array, ['name']));
$this->assertSame([], array_only($array, ['nonExistingKey']));
Not sure if there are other cases I missed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahaaa, you mean null
, 0
, false
, etc..? You are right, this should be fixed.
Well giving it a deep thought I find the new addition to I'm thinking of API response for example, maybe you want to present |
Indeed it would be useful, I only say I think this goes outside of the scope of Just some idea for later, creating some new class |
I see, maybe a |
*/ | ||
protected function getExplicitAddress($attribute) | ||
{ | ||
return str_replace_last('.', '', explode('*', $attribute)[0]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should use the Str::replaceLast
method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or maybe just rtrim( ... , '.')
?
@vlakoff updates were made. Thanks for the notes. |
continue; | ||
} | ||
|
||
data_set($attributeData, $key, $keyValue); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do your $key contain "*" ? I think the data_set
is too "useful", Arr::set
should work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@vlakoff Yes, the Arr::set works on dots
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, right. So you could use Arr::get/set
in this modified Arr::only
. It would be a much better fit, while still working with the code in Validator.
This modifed Arr::only
is probably slower, that's the only caveat I can think of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because of the |
Would it be possible for people to bypass validation by passing missing as their value? Could that possibly be exploited in any way? |
What did the before / after benchmarks look like on this? |
@taylorotwell If the value passed was |
@taylorotwell doing a very basic benchmarking, applying the distinct rule on 1,656 array items exceeded 30 seconds of execution. Applying the change and only passing the data the rule needs dropped it to 8 seconds. The test is on an array that looks like:
The rules are:
The difference in execution time is that before we pass all the data to the distinct rule to check for only the ones we need:
The change is:
Here |
Just as a suggestion, how about this:
|
Closes #12651 Signed-off-by: Graham Campbell <graham@alt-three.com>
The use case for testing performance is that I'm uploading a large excel file, convert it to array, validate the array before saving into the database.
The array looks like:
Inside the validator we flatten the data to the
dot.format
and iterate over the results in multiple areas in the code, like in thevalidateDistinct
,validateArray
, andinitializeAttributeOnData
.The issue here is that we hit all the flattened records even the ones that don't belong to the attribute we're checking, and this is causing a huge performance issue.
This PR grabs only the required attribute values before flattening them with
Arr::dot
, so based on the example above if I'm validatingproducts.code
is distinct I'll only iterate overproducts
only, not the whole data.Sometimes the data is nested:
Here we only need to flatten
$data['foo']['bar']
for the check, andArr::only
was only working for single dimensional arrays, so I modifiedArr::only
to accept dot-keys and used the explicit part of the attribute namefoo.bar
to get only this data before passing it toArr:dot
.UPDATE:
The
Arr::only
method was left untouched, and a new method was added to the ValidatorextractData()
.