comparison perf-test.js @ 33:e9a0f66ee81c

Quick in-browser performance test
author Chris Cannam
date Sat, 24 Sep 2016 16:26:04 +0100
parents
children 3faa4e3eedac
comparison
equal deleted inserted replaced
32:30028b3c95e4 33:e9a0f66ee81c
1 "use strict";
2
3 var exampleModule = VampExamplePluginsModule();
4
5 // It is possible to declare both parameters and return values as
6 // "string", in which case Emscripten will take care of
7 // conversions. But it's not clear how one would manage memory for
8 // newly-constructed returned C strings -- the returned pointer from
9 // vampipeRequestJson would appear (?) to be thrown away by the
10 // Emscripten string converter if we declare it as returning a string,
11 // so we have no opportunity to pass it to vampipeFreeJson, which
12 // suggests this would leak memory if the string isn't static. Not
13 // wholly sure though. Anyway, passing and returning pointers (as
14 // numbers) means we can manage the Emscripten heap memory however we
15 // want in our request wrapper function below.
16
17 var vampipeRequestJson = exampleModule.cwrap(
18 'vampipeRequestJson', 'number', ['number']
19 );
20
21 var vampipeProcessRaw = exampleModule.cwrap(
22 "vampipeProcessRaw", "number", ["number", "number", "number", "number"]
23 );
24
25 var vampipeFreeJson = exampleModule.cwrap(
26 'vampipeFreeJson', 'void', ['number']
27 );
28
29 function note(blah) {
30 document.getElementById("test-result").innerHTML += blah + "<br>";
31 }
32
33 function comment(blah) {
34 note("<br><i>" + blah + "</i>");
35 }
36
37 function processRaw(request) {
38
39 const nChannels = request.processInput.inputBuffers.length;
40 const nFrames = request.processInput.inputBuffers[0].values.length;
41
42 const buffersPtr = exampleModule._malloc(nChannels * 4);
43 const buffers = new Uint32Array(
44 exampleModule.HEAPU8.buffer, buffersPtr, nChannels);
45
46 for (let i = 0; i < nChannels; ++i) {
47 const framesPtr = exampleModule._malloc(nFrames * 4);
48 const frames = new Float32Array(
49 exampleModule.HEAPU8.buffer, framesPtr, nFrames);
50 frames.set(request.processInput.inputBuffers[i].values);
51 buffers[i] = framesPtr;
52 }
53
54 const responseJson = vampipeProcessRaw(
55 request.pluginHandle,
56 buffersPtr,
57 request.processInput.timestamp.s,
58 request.processInput.timestamp.n);
59
60 for (let i = 0; i < nChannels; ++i) {
61 exampleModule._free(buffers[i]);
62 }
63 exampleModule._free(buffersPtr);
64
65 const response = JSON.parse(
66 exampleModule.Pointer_stringify(responseJson));
67
68 vampipeFreeJson(responseJson);
69
70 return response;
71 }
72
73 function request(jsonStr) {
74 note("Request JSON = " + jsonStr);
75 var m = exampleModule;
76 // Inspection reveals that intArrayFromString converts the string
77 // from utf16 to utf8, which is what we want (though the docs
78 // don't mention this). Note the *Cstr values are Emscripten heap
79 // pointers
80 var inCstr = m.allocate(m.intArrayFromString(jsonStr), 'i8', m.ALLOC_NORMAL);
81 var outCstr = vampipeRequestJson(inCstr);
82 m._free(inCstr);
83 var result = m.Pointer_stringify(outCstr);
84 vampipeFreeJson(outCstr);
85 note("Returned JSON = " + result);
86 return result;
87 }
88
89 function test() {
90
91 comment("Loading zero crossings plugin...");
92 let result = request('{"type":"load","content": {"pluginKey":"vamp-example-plugins:zerocrossing","inputSampleRate":44100,"adapterFlags":["AdaptAllSafe"]}}');
93
94 const blockSize = 1024;
95
96 result = request('{"type":"configure","content":{"pluginHandle":1,"configuration":{"blockSize": ' + blockSize + ', "channelCount": 1, "stepSize": ' + blockSize + '}}}');
97
98 const nblocks = 1000;
99
100 let processInputBuffers = [new Float32Array(
101 Array.from(Array(blockSize).keys(), n => n / blockSize))
102 ];
103
104 comment("Now processing " + nblocks + " blocks of 1024 samples each...");
105
106 let start = (new Date()).getTime();
107 comment("Start at " + start);
108
109 for (let i = 0; i < nblocks; ++i) {
110 let ts = { "s": i, "n": 0 }; // wholly bogus, but ZC plugin doesn't use it
111 result = processRaw({
112 "pluginHandle": 1,
113 "processInput": {
114 "timestamp": ts,
115 "inputBuffers": processInputBuffers
116 }
117 });
118 }
119
120 let finish = (new Date()).getTime();
121 comment("Finish at " + finish + " for a time of " + (finish - start) + " ms");
122
123 comment("Again...");
124
125 start = (new Date()).getTime();
126 comment("Start at " + start);
127
128 for (let i = 0; i < nblocks; ++i) {
129 let ts = { "s": i, "n": 0 }; // wholly bogus, but ZC plugin doesn't use it
130 result = processRaw({
131 "pluginHandle": 1,
132 "processInput": {
133 "timestamp": ts,
134 "inputBuffers": processInputBuffers
135 }
136 });
137 }
138
139 finish = (new Date()).getTime();
140 comment("Finish at " + finish + " for a time of " + (finish - start) + " ms");
141
142 comment("Cleaning up the plugin and getting any remaining features...");
143 result = request('{"type":"finish","content":{"pluginHandle":1}}');
144 }
145
146 window.onload = function() {
147 test();
148 }