Skip to content

Commit 2cd5d66

Browse files
authored
Merge pull request #57 from JeringTech/improve-api
Expanded API.
2 parents b2666f1 + aa5b806 commit 2cd5d66

25 files changed

+2587
-749
lines changed

Changelog.md

+14-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,20 @@ This project uses [semantic versioning](http://semver.org/spec/v2.0.0.html). Ref
33
*[Semantic Versioning in Practice](https://www.jering.tech/articles/semantic-versioning-in-practice)*
44
for an overview of semantic versioning.
55

6-
## [Unreleased](https://github.com/JeringTech/Javascript.NodeJS/compare/5.1.1...HEAD)
6+
## [Unreleased](https://github.com/JeringTech/Javascript.NodeJS/compare/5.2.0...HEAD)
7+
8+
## [5.2.0](https://github.com/JeringTech/Javascript.NodeJS/compare/5.1.1...5.2.0) - Dec 4, 2019
9+
### Fixes
10+
- Expanded API. ([#57](https://github.com/JeringTech/Javascript.NodeJS/pull/57)). Added `INodeJSService` members for invocations without return values and
11+
atomic/simplified caching-invoking:
12+
- `Task InvokeFromFileAsync(string modulePath, string exportName = null, object[] args = null, CancellationToken cancellationToken = default);`
13+
- `Task InvokeFromStringAsync(string moduleString, string newCacheIdentifier = null, string exportName = null, object[] args = null, CancellationToken cancellationToken = default);`
14+
- `Task<T> InvokeFromStringAsync<T>(Func<string> moduleFactory, string cacheIdentifier, string exportName = null, object[] args = null, CancellationToken cancellationToken = default);`
15+
- `Task InvokeFromStringAsync(Func<string> moduleFactory, string cacheIdentifier, string exportName = null, object[] args = null, CancellationToken cancellationToken = default);`
16+
- `Task InvokeFromStreamAsync(Stream moduleStream, string newCacheIdentifier = null, string exportName = null, object[] args = null, CancellationToken cancellationToken = default);`
17+
- `Task<T> InvokeFromStreamAsync<T>(Func<Stream> moduleFactory, string cacheIdentifier, string exportName = null, object[] args = null, CancellationToken cancellationToken = default);`
18+
- `Task InvokeFromStreamAsync(Func<Stream> moduleFactory, string cacheIdentifier, string exportName = null, object[] args = null, CancellationToken cancellationToken = default);`
19+
- `Task<bool> TryInvokeFromCacheAsync(string moduleCacheIdentifier, string exportName = null, object[] args = null, CancellationToken cancellationToken = default);`
720

821
## [5.1.1](https://github.com/JeringTech/Javascript.NodeJS/compare/5.1.0...5.1.1) - Nov 29, 2019
922
### Fixes

ReadMe.md

+142-84
Large diffs are not rendered by default.

perf/NodeJS/ConcurrencyBenchmarks.cs

+10-10
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88

99
namespace Jering.Javascript.NodeJS.Performance
1010
{
11-
// TODO after adding invoke method with no return value (analagous to execute method in js engines), remove string type parameters
1211
[MemoryDiagnoser]
1312
public class ConcurrencyBenchmarks
1413
{
15-
private const string DUMMY_CONCURRENCY_MODULE = "dummyConcurrencyModule.js";
14+
private const string DUMMY_WARMUP_MODULE = "module.exports = (callback) => callback()";
15+
private const string DUMMY_CONCURRENCY_MODULE_FILE = "dummyConcurrencyModule.js";
1616

1717
private ServiceProvider _serviceProvider;
1818
private INodeJSService _nodeJSService;
@@ -29,11 +29,11 @@ public void INodeJSService_Concurrency_MultiProcess_Setup()
2929
_serviceProvider = services.BuildServiceProvider();
3030
_nodeJSService = _serviceProvider.GetRequiredService<INodeJSService>();
3131

32-
// Warm up. First few runs start Node.js processes, so they take longer. If we don't manually warm up, BenchmarkDotNet erroneously complains
32+
// Warmup. First few runs start Node.js processes, so they take longer. If we don't manually warm up, BenchmarkDotNet erroneously complains
3333
// about iteration time being too low
3434
for (int i = 0; i < Environment.ProcessorCount; i++)
3535
{
36-
_nodeJSService.InvokeFromStringAsync<string>("module.exports = (callback) => callback(null, null)", "warmup").GetAwaiter().GetResult();
36+
_nodeJSService.InvokeFromStringAsync(DUMMY_WARMUP_MODULE).GetAwaiter().GetResult();
3737
}
3838
}
3939

@@ -45,7 +45,7 @@ public async Task<string[]> INodeJSService_Concurrency_MultiProcess()
4545
var results = new Task<string>[numTasks];
4646
for (int i = 0; i < numTasks; i++)
4747
{
48-
results[i] = _nodeJSService.InvokeFromFileAsync<string>(DUMMY_CONCURRENCY_MODULE);
48+
results[i] = _nodeJSService.InvokeFromFileAsync<string>(DUMMY_CONCURRENCY_MODULE_FILE);
4949
}
5050

5151
return await Task.WhenAll(results);
@@ -60,8 +60,8 @@ public void INodeJSService_Concurrency_None_Setup()
6060
_serviceProvider = services.BuildServiceProvider();
6161
_nodeJSService = _serviceProvider.GetRequiredService<INodeJSService>();
6262

63-
// Warm up. First run starts a Node.js processes.
64-
_nodeJSService.InvokeFromStringAsync<string>("module.exports = (callback) => callback(null, null)", "warmup").GetAwaiter().GetResult();
63+
// Warmup. First run starts a Node.js processes.
64+
_nodeJSService.InvokeFromStringAsync(DUMMY_WARMUP_MODULE).GetAwaiter().GetResult();
6565
}
6666

6767
[Benchmark]
@@ -72,7 +72,7 @@ public async Task<string[]> INodeJSService_Concurrency_None()
7272
var results = new Task<string>[numTasks];
7373
for (int i = 0; i < numTasks; i++)
7474
{
75-
results[i] = _nodeJSService.InvokeFromFileAsync<string>(DUMMY_CONCURRENCY_MODULE);
75+
results[i] = _nodeJSService.InvokeFromFileAsync<string>(DUMMY_CONCURRENCY_MODULE_FILE);
7676
}
7777

7878
return await Task.WhenAll(results);
@@ -91,7 +91,7 @@ public void INodeServices_Concurrency_Setup()
9191
_serviceProvider = services.BuildServiceProvider();
9292
_nodeServices = _serviceProvider.GetRequiredService<INodeServices>();
9393

94-
// Warm up. First run starts a Node.js processes.
94+
// Warmup. First run starts a Node.js processes.
9595
_nodeServices.InvokeAsync<DummyResult>("dummyLatencyModule.js", 0).GetAwaiter().GetResult();
9696
}
9797

@@ -104,7 +104,7 @@ public async Task<string[]> INodeServices_Concurrency()
104104
var results = new Task<string>[numTasks];
105105
for (int i = 0; i < numTasks; i++)
106106
{
107-
results[i] = _nodeServices.InvokeAsync<string>(DUMMY_CONCURRENCY_MODULE);
107+
results[i] = _nodeServices.InvokeAsync<string>(DUMMY_CONCURRENCY_MODULE_FILE);
108108
}
109109

110110
return await Task.WhenAll(results);

perf/NodeJS/LatencyBenchmarks.cs

+16-12
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ namespace Jering.Javascript.NodeJS.Performance
1111
[MemoryDiagnoser]
1212
public class LatencyBenchmarks
1313
{
14-
private const string DUMMY_LATENCY_MODULE = "dummyLatencyModule.js";
14+
private const string DUMMY_WARMUP_MODULE = "module.exports = (callback) => callback()";
15+
private const string DUMMY_LATENCY_MODULE_FILE = "dummyLatencyModule.js";
1516
private const string DUMMY_MODULE_IDENTIFIER = "dummyLatencyModuleIdentifier";
1617

1718
private ServiceProvider _serviceProvider;
@@ -30,15 +31,14 @@ public void INodeJSService_Latency_InvokeFromFile_Setup()
3031
_nodeJSService = _serviceProvider.GetRequiredService<INodeJSService>();
3132
_counter = 0;
3233

33-
// Warm up. First run starts a Node.js process.
34-
_nodeJSService.InvokeFromStringAsync<string>("module.exports = (callback) => callback(null, null)", "warmup").GetAwaiter().GetResult();
34+
// Warmup. First run starts a Node.js process.
35+
_nodeJSService.InvokeFromStringAsync(DUMMY_WARMUP_MODULE).GetAwaiter().GetResult();
3536
}
3637

3738
[Benchmark]
3839
public async Task<DummyResult> INodeJSService_Latency_InvokeFromFile()
3940
{
40-
DummyResult result = await _nodeJSService.InvokeFromFileAsync<DummyResult>(DUMMY_LATENCY_MODULE, args: new object[] { _counter++ });
41-
return result;
41+
return await _nodeJSService.InvokeFromFileAsync<DummyResult>(DUMMY_LATENCY_MODULE_FILE, args: new object[] { _counter++ });
4242
}
4343

4444
[GlobalSetup(Target = nameof(INodeJSService_Latency_InvokeFromCache))]
@@ -50,15 +50,19 @@ public void INodeJSService_Latency_InvokeFromCache_Setup()
5050
_nodeJSService = _serviceProvider.GetRequiredService<INodeJSService>();
5151
_counter = 0;
5252

53-
// Cache module/warmup
54-
_nodeJSService.InvokeFromStringAsync<DummyResult>("module.exports = (callback, result) => callback(null, { result: result });", DUMMY_MODULE_IDENTIFIER, args: new object[] { _counter++ }).GetAwaiter().GetResult();
53+
// Warmup/cache.
54+
_nodeJSService.InvokeFromStringAsync<DummyResult>(DummyModuleFactory, DUMMY_MODULE_IDENTIFIER, args: new object[] { _counter++ }).GetAwaiter().GetResult();
5555
}
5656

5757
[Benchmark]
5858
public async Task<DummyResult> INodeJSService_Latency_InvokeFromCache()
5959
{
60-
(bool _, DummyResult result) = await _nodeJSService.TryInvokeFromCacheAsync<DummyResult>(DUMMY_MODULE_IDENTIFIER, args: new object[] { _counter++ });
61-
return result;
60+
return await _nodeJSService.InvokeFromStringAsync<DummyResult>(DummyModuleFactory, DUMMY_MODULE_IDENTIFIER, args: new object[] { _counter++ });
61+
}
62+
63+
private string DummyModuleFactory()
64+
{
65+
return File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "../../../..", DUMMY_LATENCY_MODULE_FILE));
6266
}
6367

6468
[Obsolete]
@@ -75,15 +79,15 @@ public void INodeServices_Latency_Setup()
7579
_nodeServices = _serviceProvider.GetRequiredService<INodeServices>();
7680
_counter = 0;
7781

78-
// Warm up. First run starts a Node.js process.
79-
_nodeServices.InvokeAsync<DummyResult>(DUMMY_LATENCY_MODULE, 0).GetAwaiter().GetResult();
82+
// Warmup. First run starts a Node.js process.
83+
_nodeServices.InvokeAsync<DummyResult>(DUMMY_LATENCY_MODULE_FILE, 0).GetAwaiter().GetResult();
8084
}
8185

8286
[Obsolete]
8387
[Benchmark]
8488
public async Task<DummyResult> INodeServices_Latency()
8589
{
86-
DummyResult result = await _nodeServices.InvokeAsync<DummyResult>(DUMMY_LATENCY_MODULE, _counter++);
90+
DummyResult result = await _nodeServices.InvokeAsync<DummyResult>(DUMMY_LATENCY_MODULE_FILE, _counter++);
8791
return result;
8892
}
8993

perf/NodeJS/RealWorkloadBenchmarks.cs

+12-6
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ namespace Jering.Javascript.NodeJS.Performance
1111
[MemoryDiagnoser]
1212
public class RealWorkloadBenchmarks
1313
{
14-
private const string DUMMY_REAL_WORKLOAD_MODULE = "dummyRealWorkloadModule.js";
14+
private const string DUMMY_CACHE_IDENTIFIER = "dummyRealWorkloadModuleIdentifier";
15+
private const string DUMMY_REAL_WORKLOAD_MODULE_FILE = "dummyRealWorkloadModule.js";
1516
// Realistically, you aren't going to pass the same string for highlighting every time, so use a format that we alter slightly every interation
1617
private const string DUMMY_CODE_FORMAT = @"public class HelloWorld
1718
{{
@@ -39,11 +40,11 @@ public void INodeJSService_RealWorkload_Setup()
3940
_nodeJSService = _serviceProvider.GetRequiredService<INodeJSService>();
4041
_counter = 0;
4142

42-
// Warm up. First few runs start Node.js processes, so they take longer. If we don't manually warm up, BenchmarkDotNet erroneously complains
43+
// Warmup/cache. First few runs start Node.js processes, so they take longer. If we don't manually warm up, BenchmarkDotNet erroneously complains
4344
// about iteration time being too low
4445
for (int i = 0; i < Environment.ProcessorCount; i++)
4546
{
46-
_nodeJSService.InvokeFromStringAsync<string>("module.exports = (callback) => callback(null, null)", "warmup").GetAwaiter().GetResult();
47+
_nodeJSService.InvokeFromStringAsync(DummyModuleFactory, DUMMY_CACHE_IDENTIFIER, args: new object[] { string.Format(DUMMY_CODE_FORMAT, _counter++) }).GetAwaiter().GetResult();
4748
}
4849
}
4950

@@ -56,12 +57,17 @@ public async Task<string[]> INodeJSService_RealWorkload()
5657
for (int i = 0; i < numTasks; i++)
5758
{
5859
// The module uses Prism.js to perform syntax highlighting
59-
results[i] = _nodeJSService.InvokeFromFileAsync<string>(DUMMY_REAL_WORKLOAD_MODULE, args: new object[] { string.Format(DUMMY_CODE_FORMAT, _counter++) });
60+
results[i] = _nodeJSService.InvokeFromStringAsync<string>(DummyModuleFactory, DUMMY_CACHE_IDENTIFIER, args: new object[] { string.Format(DUMMY_CODE_FORMAT, _counter++) });
6061
}
6162

6263
return await Task.WhenAll(results);
6364
}
6465

66+
private string DummyModuleFactory()
67+
{
68+
return File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "../../../..", DUMMY_REAL_WORKLOAD_MODULE_FILE));
69+
}
70+
6571
[Obsolete]
6672
[GlobalSetup(Target = nameof(INodeServices_RealWorkload))]
6773
public void INodeServices_RealWorkload_Setup()
@@ -76,7 +82,7 @@ public void INodeServices_RealWorkload_Setup()
7682
_nodeServices = _serviceProvider.GetRequiredService<INodeServices>();
7783
_counter = 0;
7884

79-
// Warm up. First run starts a Node.js process.
85+
// Warmup. First run starts a Node.js process.
8086
_nodeServices.InvokeAsync<DummyResult>("dummyLatencyModule.js", 0).GetAwaiter().GetResult(); // Doesn't support invoke from string, so this is the simplest/quickest
8187
}
8288

@@ -89,7 +95,7 @@ public async Task<string[]> INodeServices_RealWorkload()
8995
var results = new Task<string>[numTasks];
9096
for (int i = 0; i < numTasks; i++)
9197
{
92-
results[i] = _nodeServices.InvokeAsync<string>(DUMMY_REAL_WORKLOAD_MODULE, string.Format(DUMMY_CODE_FORMAT, _counter++));
98+
results[i] = _nodeServices.InvokeAsync<string>(DUMMY_REAL_WORKLOAD_MODULE_FILE, string.Format(DUMMY_CODE_FORMAT, _counter++));
9399
}
94100

95101
return await Task.WhenAll(results);

0 commit comments

Comments
 (0)