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

Function call performance improvements #703

Merged
merged 6 commits into from
Jan 20, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
74 changes: 74 additions & 0 deletions Jint.Benchmark/DictionaryBenchmark.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
using System.Collections.Generic;
using Jint.Collections;
using BenchmarkDotNet.Attributes;

namespace Jint.Benchmark
{
[MemoryDiagnoser]
public class DictionaryBenchmark
{
private static readonly string[] _keys =
{
"some",
"key and",
"another",
"varying",
"---the --",
"keys and more",
"aa bbb",
"asasd asd ",
"asdsad asd as s",
"asdadsasa",
"23323232323",
"asdadsada sa213"
};

[Params(0, 2, 3, 5, 8, 9, 10)]
public int N { get; set; }

[Benchmark]
public void HybridDictionary()
{
var hybridDictionary = new HybridDictionary<string, object>();
for (var i = 0; i < N; i++)
{
hybridDictionary.Add(_keys[i], _keys);
}

foreach (var key in _keys)
{
hybridDictionary.ContainsKey(key);
}
}

[Benchmark]
public void Dictionary()
{
var dictionary = new Dictionary<string, object>();
for (var i = 0; i < N; i++)
{
dictionary.Add(_keys[i], _keys);
}

foreach (var key in _keys)
{
dictionary.ContainsKey(key);
}
}

[Benchmark]
public void StringDictionarySlim()
{
var dictionary = new StringDictionarySlim<object>();
for (var i = 0; i < N; i++)
{
dictionary[_keys[i]] =_keys;
}

foreach (var key in _keys)
{
dictionary.ContainsKey(key);
}
}
}
}
2 changes: 2 additions & 0 deletions Jint.Benchmark/Jint.Benchmark.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<GenerateAssemblyCopyrightAttribute>false</GenerateAssemblyCopyrightAttribute>
<GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>
<GenerateAssemblyFileVersionAttribute>false</GenerateAssemblyFileVersionAttribute>
<AssemblyOriginatorKeyFile>..\Jint\Jint.snk</AssemblyOriginatorKeyFile>
<SignAssembly>true</SignAssembly>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
Expand Down
88 changes: 13 additions & 75 deletions Jint.Benchmark/UncacheableExpressionsBenchmark.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,18 @@ public class UncacheableExpressionsBenchmark
private string targetObject;
private JsValue[] targetJsObject;

private const string script = @"
private const string NonArrowFunctionScript = @"
function output(d) {
var doc = d.SubDocuments.find(function(x){return x.Id==='testing';});
return { Id : d.Id, Deleted : d.Deleted, SubTestId : (doc!==null&&doc!==undefined)?doc.Id:null, Values : d.SubDocuments.map(function(x){return {TargetId:x.TargetId,TargetValue:x.TargetValue,SubDocuments:x.SubDocuments.filter(function(s){return (s!==null&&s!==undefined);}).map(function(s){return {TargetId:s.TargetId,TargetValue:s.TargetValue};})};}) };
}
";

private const string ArrowFunctionScript = @"
function output(d) {
var doc = d.SubDocuments.find(x => x.Id==='testing');
return { Id : d.Id, Deleted : d.Deleted, SubTestId : (doc!==null&&doc!==undefined)?doc.Id:null, Values : d.SubDocuments.map(x => ({ TargetId:x.TargetId,TargetValue:x.TargetValue,SubDocuments:x.SubDocuments.filter(s => (s!==null&&s!==undefined)).map(s => ({ TargetId: s.TargetId, TargetValue: s.TargetValue}))})) };
}
";

private Engine engine;
Expand Down Expand Up @@ -72,7 +79,7 @@ public void Setup()
}
}

CreateEngine();
CreateEngine(Arrow ? ArrowFunctionScript : NonArrowFunctionScript);
}

private static void InitializeEngine(Options options)
Expand All @@ -87,6 +94,9 @@ private static void InitializeEngine(Options options)
[Params(500)]
public int N { get; set; }

[Params(true, false)]
public bool Arrow { get; set; }

[Benchmark]
public void Benchmark()
{
Expand All @@ -97,84 +107,12 @@ public void Benchmark()
}
}

private void CreateEngine()
private void CreateEngine(string script)
{
engine = new Engine(InitializeEngine);
engine.Execute(Polyfills);
engine.Execute(script);
engine.Execute(targetObject);
targetJsObject = new[] {engine.GetValue("d")};
}

private const string Polyfills = @"
//https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
if (!String.prototype.endsWith) {
String.prototype.endsWith = function (searchStr, position) {
if (!(position < this.length))
position = this.length;
else
position |= 0; // round position
return this.substr(position - searchStr.length,
searchStr.length) === searchStr;
};
}
//https://github.com/jsPolyfill/Array.prototype.find/blob/master/find.js
if (!Array.prototype.find) {
Array.prototype.find = Array.prototype.find || function(callback) {
if (this === null) {
throw new TypeError('Array.prototype.find called on null or undefined');
} else if (typeof callback !== 'function') {
throw new TypeError('callback must be a function');
}
var list = Object(this);
// Makes sures is always has an positive integer as length.
var length = list.length >>> 0;
var thisArg = arguments[1];
for (var i = 0; i < length; i++) {
var element = list[i];
if ( callback.call(thisArg, element, i, list) ) {
return element;
}
}
};
}

if (!Array.prototype.fastFilter) {
Array.prototype.fastFilter = function(callback) {
var results = [];
var item;
var len = this.length;
for (var i = 0, len = len; i < len; i++) {
item = this[i];
if (callback(item)) results.push(item);
}
return results;
}
}

if (!Array.prototype.fastMap) {
Array.prototype.fastMap = function(callback) {
var h = [];
var len = this.length;
for (var i = 0, len = len; i < len; i++) {
h.push(callback(this[i]));
}
return h;
}
}


if (!Array.prototype.fastFind) {
Array.prototype.fastFind = function(callback) {
var item;
var len = this.length;
for (var i = 0, len = len; i < len; i++) {
item = this[i];
if (callback(item)) return item;
}
}
}

";
}
}
3 changes: 3 additions & 0 deletions Jint.Tests.Ecma/Jint.Tests.Ecma.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,7 @@
<PackageReference Include="xunit.runner.console" Version="2.4.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<None Remove="TestCases\ch*\**" />
</ItemGroup>
</Project>
4 changes: 4 additions & 0 deletions Jint.Tests.Test262/Jint.Tests.Test262.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@
<PackageReference Include="xunit.runner.console" Version="2.4.1" />
<DotNetCliToolReference Include="dotnet-xunit" Version="2.3.1" />
</ItemGroup>
<ItemGroup>
<None Remove="harness\**" />
<None Remove="test\**" />
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions Jint/AssemblyInfoExtras.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Jint.Benchmark, PublicKey=0024000004800000940000000602000000240000525341310004000001000100bf2553c9f214cb21f1f64ed62cadad8fe4f2fa11322a5dfa1d650743145c6085aba05b145b29867af656e0bb9bfd32f5d0deb1668263a38233e7e8e5bad1a3c6edd3f2ec6c512668b4aa797283101444628650949641b4f7cb16707efba542bb754afe87ce956f3a5d43f450d14364eb9571cbf213d1061852fb9dd47a6c05c4")]