Skip to content

Commit

Permalink
Reduce allocations and make things go faster (#13)
Browse files Browse the repository at this point in the history
  • Loading branch information
lahma authored and sebastienros committed Dec 24, 2017
1 parent 2541d46 commit 1c5d809
Show file tree
Hide file tree
Showing 11 changed files with 925 additions and 243 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Expand Up @@ -27,4 +27,6 @@ nuget.exe
project.lock.json
.vs
.build/
.testPublish/
.testPublish/
.idea
BenchmarkDotNet.Artifacts*
13 changes: 7 additions & 6 deletions samples/Esprima.Benchmark/Esprima.Benchmark.csproj
@@ -1,14 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<AssemblyName>Esprima.Benchmark</AssemblyName>
<OutputType>Exe</OutputType>
<PackageId>Esprima.Benchmark</PackageId>
<TargetFramework>netstandard2.0</TargetFramework>
<TargetFramework>netcoreapp2.0</TargetFramework>
</PropertyGroup>

<ItemGroup>
<None Include="..\..\test\Esprima.Tests\Fixtures\3rdparty\**" CopyToOutputDirectory="PreserveNewest" LinkBase="3rdparty" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\Esprima\Esprima.csproj" />
<PackageReference Include="BenchmarkDotNet" Version="0.10.11" />
</ItemGroup>

</Project>
</Project>
49 changes: 49 additions & 0 deletions samples/Esprima.Benchmark/FileParsingBenchmark.cs
@@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using BenchmarkDotNet.Attributes;

namespace Esprima.Benchmark
{
[MemoryDiagnoser]
public class FileParsingBenchmark
{
private static readonly Dictionary<string, string> files = new Dictionary<string, string>
{
{"underscore-1.5.2", null},
{"backbone-1.1.0", null},
{"mootools-1.4.5", null},
{"jquery-1.9.1", null},
{"yui-3.12.0", null},
{"jquery.mobile-1.4.2", null},
{"angular-1.2.5", null}
};

[GlobalSetup]
public void Setup()
{
foreach (var fileName in files.Keys.ToList())
{
files[fileName] = File.ReadAllText($"3rdparty/{fileName}.js");
}
}

[ParamsSource(nameof(FileNames))]
public string FileName { get; set; }

public IEnumerable<string> FileNames()
{
foreach (var entry in files)
{
yield return entry.Key;
}
}

[Benchmark]
public void ParseProgram()
{
var parser = new JavaScriptParser(files[FileName]);
parser.ParseProgram();
}
}
}
53 changes: 4 additions & 49 deletions samples/Esprima.Benchmark/Program.cs
@@ -1,59 +1,14 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;

using BenchmarkDotNet.Running;

namespace Esprima.Benchmark
{
public class Program
{
public static void Main(string[] args)
{
var scripts =new [] {
"underscore-1.5.2",
"backbone-1.1.0",
"mootools-1.4.5",
"jquery-1.9.1",
"yui-3.12.0",
"jquery.mobile-1.4.2",
"angular-1.2.5"
};

foreach(var script in scripts)
{
Bench(script);
}
}

public static void Bench(string script)
{
var repeat = 120;
var exclude = 10;

var filename = $"../../test/Esprima.Tests/Fixtures/3rdparty/{script}.js";
var content = File.ReadAllText(filename);

var sw = new Stopwatch();
var results = new List<long>();

for(var i=0; i<repeat; i++)
{
var parser = new JavaScriptParser(content);
sw.Restart();

parser.ParseProgram();
results.Add(sw.ElapsedMilliseconds);
}

var average = results
.OrderBy(x => x)
.Skip(exclude)
.Take(repeat - exclude * 2)
.Average();

Console.WriteLine("{0} ({2}KB): {1} ms", script, Math.Round(average, 1), content.Length / 1024);
BenchmarkSwitcher.FromAssembly(typeof(Program).GetTypeInfo().Assembly).Run(args);
}

}
}
3 changes: 2 additions & 1 deletion src/Esprima/Ast/Literal.cs
Expand Up @@ -75,7 +75,8 @@ public Literal(string pattern, string flags, object value, string raw)

string PropertyKey.GetKey()
{
return Convert.ToString(Value);
var s = Value as string;
return s ?? Convert.ToString(Value);
}
}
}
8 changes: 7 additions & 1 deletion src/Esprima/Ast/Node.cs
Expand Up @@ -5,13 +5,19 @@ namespace Esprima.Ast
{
public class Node : INode
{
private Location _location;

[JsonProperty(Order = -100)]
[JsonConverter(typeof(StringEnumConverter))]
public Nodes Type { get; set; }

public int[] Range { get; set; }

[JsonProperty(PropertyName = "Loc")]
public Location Location { get; set; } = new Location();
public Location Location
{
get => _location = _location ?? new Location();
set => _location = value;
}
}
}
4 changes: 2 additions & 2 deletions src/Esprima/Character.cs
Expand Up @@ -51,7 +51,7 @@ public static bool IsIdentifierStart(char ch)
(ch >= 'A' && ch <= 'Z') ||
(ch >= 'a' && ch <= 'z') ||
(ch == '\\') ||
((ch >= 0x80) && NonAsciiIdentifierStart.IsMatch(ch.ToString()));
((ch >= 0x80) && NonAsciiIdentifierStart.IsMatch(ParserExtensions.CharToString(ch)));
}

public static bool IsIdentifierPart(char ch)
Expand All @@ -61,7 +61,7 @@ public static bool IsIdentifierPart(char ch)
(ch >= 'a' && ch <= 'z') ||
(ch >= '0' && ch <= '9') ||
(ch == '\\') ||
((ch >= 0x80) && NonAsciiIdentifierPart.IsMatch(ch.ToString()));
((ch >= 0x80) && NonAsciiIdentifierPart.IsMatch(ParserExtensions.CharToString(ch)));
}

public static bool IsIdentifierStart(string ch)
Expand Down

0 comments on commit 1c5d809

Please sign in to comment.