Skip to content

Commit 089e064

Browse files
committed
In JavaScriptEngineSwitcher.ChakraCore improved a performance of script pre-compilation
1 parent 2f2f405 commit 089e064

File tree

10 files changed

+220
-111
lines changed

10 files changed

+220
-111
lines changed

global.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"sdk": {
3-
"version": "2.1.500"
3+
"version": "2.2.101"
44
}
55
}

src/JavaScriptEngineSwitcher.ChakraCore/ChakraCorePrecompiledScript.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Text;
1+
using System.Runtime.InteropServices;
2+
using System.Text;
23

34
using JavaScriptEngineSwitcher.Core;
45

@@ -12,6 +13,11 @@ namespace JavaScriptEngineSwitcher.ChakraCore
1213
/// </summary>
1314
internal sealed class ChakraCorePrecompiledScript : IPrecompiledScript
1415
{
16+
/// <summary>
17+
/// Callback for finalization of external buffer
18+
/// </summary>
19+
private JsObjectFinalizeCallback _externalBufferFinalizeCallback;
20+
1521
/// <summary>
1622
/// Gets a source code of the script
1723
/// </summary>
@@ -68,6 +74,8 @@ public JsSerializedLoadScriptCallback LoadScriptSourceCodeCallback
6874
public ChakraCorePrecompiledScript(string code, JsParseScriptAttributes parseAttributes, byte[] cachedBytes,
6975
string documentName)
7076
{
77+
_externalBufferFinalizeCallback = Marshal.FreeHGlobal;
78+
7179
Code = code;
7280
ParseAttributes = parseAttributes;
7381
CachedBytes = cachedBytes;
@@ -94,7 +102,7 @@ private bool LoadScriptSourceCode(JsSourceContext sourceContext,
94102

95103
try
96104
{
97-
value = JsValue.CreateExternalArrayBuffer(Code, encoding);
105+
value = JsValue.CreateExternalArrayBuffer(Code, encoding, _externalBufferFinalizeCallback);
98106
result = true;
99107
}
100108
catch (OriginalException)

src/JavaScriptEngineSwitcher.ChakraCore/Helpers/EncodingHelpers.cs

Lines changed: 21 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
1-
#if NET471 || NETSTANDARD || NETCOREAPP2_1
2-
using System;
3-
using System.Runtime.InteropServices;
1+
#if NET45 || NET471 || NETSTANDARD || NETCOREAPP2_1
2+
using System.Buffers;
43
#endif
54
using System.Text;
5+
#if NET40
6+
7+
using PolyfillsForOldDotNet.System.Buffers;
8+
#endif
69

710
namespace JavaScriptEngineSwitcher.ChakraCore.Helpers
811
{
@@ -11,41 +14,34 @@ namespace JavaScriptEngineSwitcher.ChakraCore.Helpers
1114
/// </summary>
1215
internal static class EncodingHelpers
1316
{
14-
#if NET471 || NETSTANDARD || NETCOREAPP2_1
15-
public static unsafe string UnicodeToUtf8(string value, out int byteCount)
16-
#else
17-
public static string UnicodeToUtf8(string value, out int byteCount)
18-
#endif
17+
public static string UnicodeToAnsi(string value, out int byteCount)
1918
{
2019
if (string.IsNullOrEmpty(value))
2120
{
2221
byteCount = 0;
2322
return value;
2423
}
2524

26-
string result;
27-
#if NET471 || NETSTANDARD || NETCOREAPP2_1
28-
byteCount = Encoding.UTF8.GetByteCount(value);
29-
IntPtr bufferPtr = Marshal.AllocHGlobal(byteCount);
25+
Encoding utf8Encoding = Encoding.UTF8;
26+
Encoding ansiEncoding = Encoding.GetEncoding(0);
3027

31-
try
28+
var byteArrayPool = ArrayPool<byte>.Shared;
29+
int bufferLength = utf8Encoding.GetByteCount(value);
30+
byte[] buffer = byteArrayPool.Rent(bufferLength);
31+
32+
unsafe
3233
{
3334
fixed (char* pValue = value)
35+
fixed (byte* pBuffer = buffer)
3436
{
35-
Encoding.UTF8.GetBytes(pValue, value.Length, (byte*)bufferPtr, byteCount);
37+
utf8Encoding.GetBytes(pValue, value.Length, pBuffer, bufferLength);
3638
}
37-
38-
result = Encoding.GetEncoding(0).GetString((byte*)bufferPtr, byteCount);
3939
}
40-
finally
41-
{
42-
Marshal.FreeHGlobal(bufferPtr);
43-
}
44-
#else
45-
byte[] bytes = Encoding.UTF8.GetBytes(value);
46-
byteCount = bytes.Length;
47-
result = Encoding.GetEncoding(0).GetString(bytes);
48-
#endif
40+
41+
string result = ansiEncoding.GetString(buffer, 0, bufferLength);
42+
byteCount = ansiEncoding.GetByteCount(result);
43+
44+
byteArrayPool.Return(buffer);
4945

5046
return result;
5147
}

src/JavaScriptEngineSwitcher.ChakraCore/JavaScriptEngineSwitcher.ChakraCore.csproj

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ This package does not contain the native implementations of ChakraCore. Therefor
2323
* JavaScriptEngineSwitcher.ChakraCore.Native.osx-x64</Description>
2424
<PackageIconUrl>https://raw.githubusercontent.com/Taritsyn/JavaScriptEngineSwitcher/master/Icons/JavaScriptEngineSwitcher_ChakraCore_Logo128x128.png</PackageIconUrl>
2525
<PackageTags>JavaScriptEngineSwitcher;JavaScript;ECMAScript;ChakraCore</PackageTags>
26-
<PackageReleaseNotes>1. ChakraCore was updated to version 1.11.3;
27-
2. In the `NativeMethods` class for the `netstandard` and `netcoreapp` targets was changed a calling convention from `StdCall` to `Cdecl`;
28-
3. Charset was explicitly specified in the `JsCreateString`, `JsCopyString` and `JsCreatePropertyId` methods of `NativeMethods` class;
29-
4. Added a `netcoreapp2.1` target.</PackageReleaseNotes>
26+
<PackageReleaseNotes>Improved a performance of script pre-compilation.</PackageReleaseNotes>
3027
</PropertyGroup>
3128

3229
<Import Project="../../build/common.props" />

src/JavaScriptEngineSwitcher.ChakraCore/JsRt/DefaultExternalBufferFinalizeCallback.cs

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/JavaScriptEngineSwitcher.ChakraCore/JsRt/JsContext.cs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,7 @@ public static uint Idle()
164164
public static JsValue ParseScript(string script, JsSourceContext sourceContext, string sourceUrl,
165165
ref JsParseScriptAttributes parseAttributes)
166166
{
167-
JsValue scriptValue = CreateExternalArrayBufferFromScriptCode(script, ref parseAttributes);
168-
scriptValue.AddRef();
167+
JsPooledArrayBuffer scriptBuffer = CreatePooledArrayBufferFromScriptCode(script, ref parseAttributes);
169168

170169
JsValue sourceUrlValue = JsValue.FromString(sourceUrl);
171170
sourceUrlValue.AddRef();
@@ -174,13 +173,13 @@ public static JsValue ParseScript(string script, JsSourceContext sourceContext,
174173

175174
try
176175
{
177-
JsErrorCode errorCode = NativeMethods.JsParse(scriptValue, sourceContext, sourceUrlValue,
176+
JsErrorCode errorCode = NativeMethods.JsParse(scriptBuffer.Value, sourceContext, sourceUrlValue,
178177
parseAttributes, out result);
179178
JsErrorHelpers.ThrowIfError(errorCode);
180179
}
181180
finally
182181
{
183-
scriptValue.Release();
182+
scriptBuffer.Dispose();
184183
sourceUrlValue.Release();
185184
}
186185

@@ -225,6 +224,8 @@ public static JsValue ParseSerializedScript(string script, byte[] buffer,
225224
sourceUrlValue.Release();
226225
}
227226

227+
GC.KeepAlive(buffer);
228+
228229
return result;
229230
}
230231

@@ -243,8 +244,7 @@ public static JsValue ParseSerializedScript(string script, byte[] buffer,
243244
public static JsValue RunScript(string script, JsSourceContext sourceContext, string sourceUrl,
244245
ref JsParseScriptAttributes parseAttributes)
245246
{
246-
JsValue scriptValue = CreateExternalArrayBufferFromScriptCode(script, ref parseAttributes);
247-
scriptValue.AddRef();
247+
JsPooledArrayBuffer scriptBuffer = CreatePooledArrayBufferFromScriptCode(script, ref parseAttributes);
248248

249249
JsValue sourceUrlValue = JsValue.FromString(sourceUrl);
250250
sourceUrlValue.AddRef();
@@ -253,13 +253,13 @@ public static JsValue RunScript(string script, JsSourceContext sourceContext, st
253253

254254
try
255255
{
256-
JsErrorCode errorCode = NativeMethods.JsRun(scriptValue, sourceContext, sourceUrlValue,
256+
JsErrorCode errorCode = NativeMethods.JsRun(scriptBuffer.Value, sourceContext, sourceUrlValue,
257257
parseAttributes, out result);
258258
JsErrorHelpers.ThrowIfError(errorCode);
259259
}
260260
finally
261261
{
262-
scriptValue.Release();
262+
scriptBuffer.Dispose();
263263
sourceUrlValue.Release();
264264
}
265265

@@ -284,14 +284,14 @@ public static JsValue RunScript(string script, JsSourceContext sourceContext, st
284284
public static JsValue RunSerializedScript(string script, byte[] buffer,
285285
JsSerializedLoadScriptCallback scriptLoadCallback, JsSourceContext sourceContext, string sourceUrl)
286286
{
287-
JsValue result;
288-
289287
JsValue bufferValue = JsValue.CreateExternalArrayBuffer(buffer);
290288
bufferValue.AddRef();
291289

292290
JsValue sourceUrlValue = JsValue.FromString(sourceUrl);
293291
sourceUrlValue.AddRef();
294292

293+
JsValue result;
294+
295295
try
296296
{
297297
JsErrorCode errorCode = NativeMethods.JsRunSerialized(bufferValue, scriptLoadCallback, sourceContext,
@@ -304,6 +304,8 @@ public static JsValue RunSerializedScript(string script, byte[] buffer,
304304
sourceUrlValue.Release();
305305
}
306306

307+
GC.KeepAlive(buffer);
308+
307309
return result;
308310
}
309311

@@ -325,19 +327,17 @@ public static JsValue RunSerializedScript(string script, byte[] buffer,
325327
/// <returns>The buffer to put the serialized script into</returns>
326328
public static byte[] SerializeScript(string script, ref JsParseScriptAttributes parseAttributes)
327329
{
328-
JsValue scriptValue = CreateExternalArrayBufferFromScriptCode(script, ref parseAttributes);
329-
scriptValue.AddRef();
330-
330+
JsPooledArrayBuffer scriptBuffer = CreatePooledArrayBufferFromScriptCode(script, ref parseAttributes);
331331
JsValue bufferValue;
332332

333333
try
334334
{
335-
JsErrorCode errorCode = NativeMethods.JsSerialize(scriptValue, out bufferValue, parseAttributes);
335+
JsErrorCode errorCode = NativeMethods.JsSerialize(scriptBuffer.Value, out bufferValue, parseAttributes);
336336
JsErrorHelpers.ThrowIfError(errorCode);
337337
}
338338
finally
339339
{
340-
scriptValue.Release();
340+
scriptBuffer.Dispose();
341341
}
342342

343343
byte[] buffer = bufferValue.ArrayBufferBytes;
@@ -346,12 +346,12 @@ public static byte[] SerializeScript(string script, ref JsParseScriptAttributes
346346
}
347347

348348
/// <summary>
349-
/// Creates a Javascript <c>ArrayBuffer</c> object from script code
349+
/// Creates a pooled Javascript <c>ArrayBuffer</c> object from script code
350350
/// </summary>
351351
/// <param name="script">Script code</param>
352352
/// <param name="parseAttributes">Attribute mask for parsing the script</param>
353-
/// <returns>The new <c>ArrayBuffer</c> object</returns>
354-
private static JsValue CreateExternalArrayBufferFromScriptCode(string script,
353+
/// <returns>Instance of <see cref="JsPooledArrayBuffer"/></returns>
354+
private static JsPooledArrayBuffer CreatePooledArrayBufferFromScriptCode(string script,
355355
ref JsParseScriptAttributes parseAttributes)
356356
{
357357
Encoding encoding;
@@ -366,9 +366,9 @@ private static JsValue CreateExternalArrayBufferFromScriptCode(string script,
366366
encoding = Encoding.UTF8;
367367
}
368368

369-
JsValue scriptValue = JsValue.CreateExternalArrayBuffer(script, encoding);
369+
JsPooledArrayBuffer scriptBuffer = JsPooledArrayBuffer.Create(script, encoding);
370370

371-
return scriptValue;
371+
return scriptBuffer;
372372
}
373373

374374
/// <summary>

0 commit comments

Comments
 (0)