I'd like to execute an arbitrary - user supplied - piece of javascript code on each line of a file. I created a simple node command line application, that will - as an example - just take each line and will output its length:
#!/usr/bin/env node
// eachline.js - execute some js per line in a file
var fs = require('fs'),
readline = require('readline');
vm = require('vm');
var args = process.argv.slice(2);
if (args.length < 1) {
console.log("Usage: eachline.js FILENAME")
process.exit(code=1)
}
var rd = readline.createInterface({
input: fs.createReadStream(args[0]),
output: process.stdout,
terminal: false
});
var context = vm.createContext({});
// this snippet should be user supplied, arbitrary javascript
var script = vm.createScript('output = input.length');
rd.on('line', function(line) {
context.input = line;
script.runInContext(context);
console.log(context.output);
});
The performance is not optimal. For a file with 1 million lines, it takes several minutes:
$ time ./eachline.js 1M.txt > /dev/null
real 4m14.366s
user 4m12.200s
sys 0m4.545s
With awk
this simple operation takes about five seconds. With a similar program , that executes arbitrary javascript a bit more than ten seconds.
I haven't worked with node before, so the program above is my first uneducated guess at a solution. How could I improve performance?
Edit: Above source code in a gist: https://gist.github.com/miku/31864156938fcd0c8430
PS. Goal is to have a program that can run arbitrary javascript on each line of a file fast.
Try this:
var context = vm.createContext({});
// this snippet should be user supplied, arbitrary javascript
var script = vm.createScript('(function (input) { return input.length; })');
var fn = script.runInContext(context);
rd.on('line', function(line) {
console.log(fn(line));
});
The idea is to wrap provided expression in a function, evaluate the script and then use the function. I think v8 doesn't optimize code inside script
because it is not supposed to run more than once.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.