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
Optimize array access and add ability to hint array size #455
Conversation
Jint/Native/Array/ArrayPrototype.cs
Outdated
@@ -79,11 +79,9 @@ private JsValue LastIndexOf(JsValue thisObj, JsValue[] arguments) | |||
for (; k >= 0; k--) | |||
{ | |||
var kString = k.ToString(); |
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.
Change k
to int
and use TypeConverter.ToString(k);
? Should save the allocation and the string gen for most cases.
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.
I think I had it there but some test gave overflow, might just have needed uint or something. Worth to check again.
Jint/Native/Array/ArrayPrototype.cs
Outdated
@@ -170,14 +165,16 @@ private JsValue Filter(JsValue thisObj, JsValue[] arguments) | |||
var a = (ArrayInstance)Engine.Array.Construct(Arguments.Empty); | |||
|
|||
var to = 0; | |||
var jsValues = new JsValue[3]; |
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.
Cache that as local thread stuff as well?
For that matter, might as well create some shared cache per thread for all of that and have a property such as List
, 3 element array
, etc.
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.
Before I do own benchmarks, would you happen to know performance benefits between small array allocation and thread local data access? What I've understood small arrays are quite efficient, but probably worth checking out.
Jint/Native/Array/ArrayPrototype.cs
Outdated
var a = Engine.Array.Construct(new JsValue[] {len}); | ||
|
||
var a = Engine.Array.Construct(new JsValue[] {len}, len); | ||
var jsValues = new JsValue[3]; |
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.
Same
Jint/Native/Array/ArrayPrototype.cs
Outdated
@@ -234,14 +232,16 @@ private JsValue ForEach(JsValue thisObj, JsValue[] arguments) | |||
throw new JavaScriptException(Engine.TypeError, "Argument must be callable"); | |||
}); | |||
|
|||
var jsValues = new JsValue[3]; |
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.
Same
Jint/Native/Array/ArrayPrototype.cs
Outdated
@@ -262,14 +262,16 @@ private JsValue Some(JsValue thisObj, JsValue[] arguments) | |||
throw new JavaScriptException(Engine.TypeError, "Argument must be callable"); | |||
}); | |||
|
|||
var jsValues = new JsValue[3]; |
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.
Same
Jint/Native/Array/ArrayPrototype.cs
Outdated
@@ -294,14 +296,16 @@ private JsValue Every(JsValue thisObj, JsValue[] arguments) | |||
throw new JavaScriptException(Engine.TypeError, "Argument must be callable"); | |||
}); | |||
|
|||
var jsValues = new JsValue[3]; |
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.
Same
Jint/Native/Array/ArrayPrototype.cs
Outdated
@@ -344,10 +348,8 @@ private JsValue IndexOf(JsValue thisObj, JsValue[] arguments) | |||
for (; k < len; k++) | |||
{ | |||
var kString = k.ToString(); |
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.
Same
db116fa
to
e931502
Compare
I've implemented @ayende 's suggestions. I also updated the before and after numbers above, now rebased based on current dev. |
37bed59
to
c92046e
Compare
I think I've done most I can here now for sparse array case, you can see updated numbers above. To proceed with this we need to process other PRs first, which should also give perf boost here too. |
afcdf78
to
5e82122
Compare
I have implemented the dense array thingie. This helped to squeeze some more speed. ArrayStressBenchmark had negative change due to dense array but it's still faster than before. I guess the unrealistic test case just works better with dictionary based backend. |
That's awesome! I am very slow on reviews and merges because of the holidays, but should be back on track in two days. |
No worries, have a great new year! |
* introduce ArrayExecutionContext for thread-local call data * use TypeConverter.ToString for rest of indexes too
* harmonize xUnit versions
5e82122
to
45bb138
Compare
yield return new KeyValuePair<string, PropertyDescriptor>(TypeConverter.ToString(entry.Key), entry.Value); | ||
for (var i = 0; i < _dense.Length; i++) | ||
{ | ||
if (_dense[i] != null) |
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.
If it's dense, shouldn't the first null value mark that all subsequent ones are not used and break the loop?
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.
It's expected to be dense, but allows sparseness as currently shares the ArrayProtype API. So you could call delete in the middle if I remember right. Ideally we could natively support unshift with moving start index for array. But this requires some work and moving operations closer to arrayinstance.
ArrayBenchmark
Baseline
After sparse array optimization
After introducing dense array
ArrayStressBenchmark
Baseline
After sparse array optimization
After introducing dense array
UncacheableExpressionsBenchmark
Baseline
After sparse array optimization
After introducing dense array