-
Notifications
You must be signed in to change notification settings - Fork 0
/
vmalterns.js
130 lines (111 loc) · 3.44 KB
/
vmalterns.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
#!/usr/bin/node
var util = require('util');
var vm = require('vm');
var mod_crypto = require('crypto');
//--- Functions that run other functions...
function runInNewContextFunc(code, line) {
var x = {
'line': line
};
try {
return vm.runInNewContext(code, x);
} catch (e) {
console.error(e);
process.exit(1);
}
}
var CACHED_SCRIPT = null;
function scriptRunInNewContext(code, line) {
if (CACHED_SCRIPT === null) {
CACHED_SCRIPT = vm.createScript(code);
}
var x = {
'line': line
};
return CACHED_SCRIPT.runInNewContext(x);
}
function evalFunc(code, line) {
return eval(code);
}
function functionFunc(code, line) {
var f = new Function('line', 'return ' + code + ';');
return f(line);
}
var CACHED_FUNC = null;
function cachedFunctionFunc(code, line) {
if (CACHED_FUNC === null) {
CACHED_FUNC = new Function('line', 'return ' + code + ';');
}
return CACHED_FUNC(line);
}
var CACHED_FUNC_WITH_BIND = null;
function cachedFunctionWithBindFunc(code, line) {
if (CACHED_FUNC_WITH_BIND === null) {
//Adding this so the bind works...
CACHED_FUNC_WITH_BIND = new Function(
'return this.' + code + ';');
}
return CACHED_FUNC_WITH_BIND.bind({ 'line': line })();
}
var CACHED_FUNC_WITH_CALL = null;
function cachedFunctionWithCallFunc(code, line) {
if (CACHED_FUNC_WITH_CALL === null) {
CACHED_FUNC_WITH_CALL = new Function(
'line', 'return ' + code + ';');
}
return CACHED_FUNC_WITH_CALL.call(null, line);
}
//Same as previous, but binding this
var CACHED_FUNC_WITH_THIS_CALL = null;
function cachedFunctionWithThisCallFunc(code, line) {
if (CACHED_FUNC_WITH_THIS_CALL === null) {
CACHED_FUNC_WITH_THIS_CALL = new Function(
'return this.' + code + ';');
}
return CACHED_FUNC_WITH_THIS_CALL.call({ 'line': line });
}
//--- Time
function timeInvocations(f, iters, code, line) {
var start = (new Date()).getTime();
for (var i = 0; i < iters; ++i) {
f(code, line);
}
var end = (new Date()).getTime();
return (end - start);
}
//Should be the same as the "code" below...
function baseline(code, line) {
return line.split(',')[0];
}
//--- Main
var line = 'x,y,z';
var code = 'line.split(\',\')[0]';
var expected = 'x';
var funcs = [
runInNewContextFunc,
scriptRunInNewContext,
evalFunc,
functionFunc,
cachedFunctionFunc,
cachedFunctionWithBindFunc,
cachedFunctionWithCallFunc,
cachedFunctionWithThisCallFunc,
baseline
];
// First test that they will give back the same thing...
for (var i = 0; i < funcs.length; ++i) {
var f = funcs[i];
var res = f(code, line);
if (res !== expected) {
console.log(f.name + ' returned ' + res + ', expected: ' +
expected);
process.exit(1);
}
}
for (var i = 0; i < funcs.length; ++i) {
var f = funcs[i];
//Safe with run in new context
// var t = timeInvocations(f, 100000, code, line);
var t = timeInvocations(f, 100000000, code, line);
console.log(f.name + ' => ' + t);
}