Skip to content
This repository was archived by the owner on Mar 28, 2023. It is now read-only.

Commit 507cf08

Browse files
committed
Add scenarios for lightweight asynchronous Ops
--HG-- extra : amend_source : d1959638383976d274837bfb842c4a91e07e487f
1 parent ff47f27 commit 507cf08

File tree

11 files changed

+510
-0
lines changed

11 files changed

+510
-0
lines changed

Diff for: Makefile

+2
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,12 @@ initialise:
66

77
benchmark:
88
node scenarios/serial/index.js
9+
node scenarios/light-serial/index.js
910
node scenarios/parallel/index.js
1011

1112
benchmark-harmony:
1213
node --harmony-generators scenarios/serial/index.js
14+
node --harmony-generators scenarios/light-serial/index.js
1315
node --harmony-generators scenarios/parallel/index.js
1416

1517
.PHONY: benchmark

Diff for: scenarios/light-serial/async.js

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// -- Dependencies -----------------------------------------------------
2+
var fs = require('fs')
3+
var path = require('path')
4+
var async = require('async')
5+
6+
7+
// -- Helpers ----------------------------------------------------------
8+
function concatenate(xs, done) {
9+
done( null
10+
, xs.reduce( function(as, bs) { return as.concat(bs) }
11+
, [] ))}
12+
13+
14+
function join(separator){ return function(xs, done) {
15+
done( null
16+
, xs.join(separator)) }}
17+
18+
19+
function withParent(dir){ return function(file) {
20+
return path.join(dir, file) }}
21+
22+
23+
function isString(a) {
24+
return typeof a === 'string' }
25+
26+
27+
// -- Generators -------------------------------------------------------
28+
function noiseList(n) { return function(done) {
29+
done( null
30+
, n <= 0? []
31+
: /* _ */ Array(n + 1).join(0)
32+
.split(0)
33+
.map(function(_, i){ return i })) }}
34+
35+
36+
function read(filename, done) {
37+
return isString(filename)? fs.lstat(filename, done)
38+
: /* otherwise */ done(null, String(filename)) }
39+
40+
41+
function readFiles(dir) { return function(done) {
42+
fs.readdir(dir, function(err, files) {
43+
if (err) done(err)
44+
else done(null, files.map(withParent(dir))) })}}
45+
46+
47+
function makeLists(dir, noiseFactor) { return function(done) {
48+
async.parallel([ noiseList(noiseFactor)
49+
, readFiles(dir)
50+
]
51+
, done )}}
52+
53+
54+
function readAll(xs, done) {
55+
return async.mapSeries(xs, read, done) }
56+
57+
58+
// -- Core -------------------------------------------------------------
59+
module.exports = function(dir, noiseFactor, done) { return function(deferred) {
60+
61+
async.waterfall([ makeLists(dir, noiseFactor)
62+
, concatenate
63+
, readAll
64+
]
65+
, function(err, results) {
66+
done(deferred, err, results) })
67+
68+
}}

Diff for: scenarios/light-serial/callbacks.js

+84
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
// -- Dependencies -----------------------------------------------------
2+
var fs = require('fs')
3+
var path = require('path')
4+
5+
6+
// -- Helpers ----------------------------------------------------------
7+
function parallel(fs, done) {
8+
var length = fs.length
9+
var results = new Array(length)
10+
11+
fs.forEach(function(f, i) { f(resolver(i)) })
12+
13+
function resolver(i){ return function(err, value) {
14+
if (err) done(err)
15+
else { results[i] = value
16+
if (--length == 0) done(null, results) }}}}
17+
18+
function mapSequentially(xs, f, done) {
19+
var length = xs.length
20+
var results = new Array(length)
21+
var index = 0
22+
23+
function next() {
24+
f(xs[index], function(x) {
25+
results[index] = x
26+
if (++index >= length) done(null, results)
27+
else next() })}
28+
29+
next() }
30+
31+
function concatenate(xs, done) {
32+
done( null
33+
, xs.reduce( function(as, bs) { return as.concat(bs) }
34+
, [] ))}
35+
36+
37+
function join(xs, separator, done) {
38+
done( null
39+
, xs.join(separator)) }
40+
41+
42+
function withParent(dir){ return function(file) {
43+
return path.join(dir, file) }}
44+
45+
46+
function isString(a) {
47+
return typeof a === 'string' }
48+
49+
50+
// -- Generators -------------------------------------------------------
51+
function noiseList(n){ return function(done) {
52+
done( null
53+
, n <= 0? []
54+
: /* _ */ Array(n + 1).join(0)
55+
.split(0)
56+
.map(function(_, i){ return i })) }}
57+
58+
function read(filename, done) {
59+
return isString(filename)? fs.lstat(filename, done)
60+
: /* otherwise */ done(null, String(filename)) }
61+
62+
function readFiles(dir) { return function(done) {
63+
fs.readdir(dir, function(err, files) {
64+
if (err) done(err)
65+
else done(null, files.map(withParent(dir))) })}}
66+
67+
68+
function makeLists(dir, noiseFactor, done) {
69+
parallel([ noiseList(noiseFactor)
70+
, readFiles(dir)
71+
], done )}
72+
73+
function readAll(xs, done) {
74+
mapSequentially(xs, read, done) }
75+
76+
// -- Core -------------------------------------------------------------
77+
module.exports = function(dir, noiseFactor, done){ return function(deferred) {
78+
79+
makeLists(dir, noiseFactor, function(err, items) {
80+
concatenate(items, function(err, files) {
81+
readAll(files, function(err, texts) {
82+
done(deferred, err, texts) })})})
83+
84+
}}

Diff for: scenarios/light-serial/co.js

+77
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
// -- Dependencies -----------------------------------------------------
2+
var fs = require('fs')
3+
var path = require('path')
4+
var co = require('co')
5+
6+
7+
// -- Helpers ----------------------------------------------------------
8+
function parallel(fs){ return function(done) {
9+
var length = fs.length
10+
var results = new Array(length)
11+
12+
fs.forEach(function(f, i) { f(resolver(i)) })
13+
14+
function resolver(i){ return function(err, value) {
15+
if (err) done(err)
16+
else { results[i] = value
17+
if (--length == 0) done(null, results) }}}}}
18+
19+
20+
function *mapSequentially(xs, f){
21+
var length = xs.length
22+
var results = new Array(length)
23+
for (var i = 0; i < length; ++i)
24+
results[i] = yield f(xs[i])
25+
26+
return results }
27+
28+
29+
function concatenate(xs){
30+
return xs.reduce( function(as, bs) { return as.concat(bs) }
31+
, [] )}
32+
33+
34+
function withParent(dir){ return function(file) {
35+
return path.join(dir, file) }}
36+
37+
38+
function isString(a) {
39+
return typeof a === 'string' }
40+
41+
42+
// -- Generators -------------------------------------------------------
43+
function noiseList(n){
44+
return n <= 0? []
45+
: /* _ */ Array(n + 1).join(0)
46+
.split(0)
47+
.map(function(_, i){ return i }) }
48+
49+
var readFile = co.wrap(fs.readFile)
50+
var readDir = co.wrap(fs.readdir)
51+
var lstat = co.wrap(fs.lstat)
52+
53+
function *read(filename) {
54+
return isString(filename)? yield lstat(filename)
55+
: /* otherwise */ String(filename) }
56+
57+
58+
function *readFiles(dir) {
59+
var files = yield readDir(dir)
60+
return files.map(withParent(dir)) }
61+
62+
63+
function *readAll(xs) {
64+
return yield mapSequentially(xs, read) }
65+
66+
// -- Core -------------------------------------------------------------
67+
module.exports = function(dir, noiseFactor){ return function(deferred) {
68+
69+
co(function *() {
70+
var noise = noiseList(noiseFactor)
71+
var files = yield readFiles(dir)
72+
var wholeList = yield readAll(concatenate([noise, files]))
73+
74+
deferred.resolve(wholeList)
75+
})
76+
77+
}}

Diff for: scenarios/light-serial/deferred.js

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
var deferred = require('deferred')
2+
3+
var listTest = require('./promises')(function(f) {
4+
var d = deferred()
5+
f(d.resolve, d.reject)
6+
return d.promise })
7+
8+
function raise(e) { process.nextTick(function(){ throw e }) }
9+
10+
module.exports = function(path, noiseFactor){ return function(deferred) {
11+
return listTest(path, noiseFactor)
12+
.then(function(v){ deferred.resolve() }
13+
,raise)
14+
}}

Diff for: scenarios/light-serial/index.js

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
var path = require('path')
2+
var benchmark = require('../../benchmark')
3+
4+
var isHarmony = benchmark.isHarmony
5+
var dirname = path.join(__dirname, '../../fixtures/files')
6+
7+
function done(deferred) { deferred.resolve() }
8+
9+
function run(noise, bench) {
10+
if (isHarmony()) bench('Co', require('./co')(dirname, noise))
11+
bench('Callbacks (baseline)', require('./callbacks')(dirname, noise, done))
12+
bench('Async', require('./async')(dirname, noise, done))
13+
bench('Pinky', require('./pinky')(dirname, noise))
14+
bench('Pinky (synchronous)', require('./pinky-sync')(dirname, noise))
15+
bench('Q', require('./q')(dirname, noise))
16+
bench('When', require('./when')(dirname, noise))
17+
bench('Deferred', require('./deferred')(dirname, noise))
18+
}
19+
20+
benchmark.suite('Lightweight serial (no noise)', function(bench) {
21+
run(0, bench)
22+
})
23+
24+
benchmark.suite('Lightweight serial (some noise)', function(bench) {
25+
run(50, bench)
26+
})
27+
28+
benchmark.suite('Lightweight serial (noisy)', function(bench) {
29+
run(100, bench)
30+
})
31+
32+
benchmark.suite('Lightweight serial (mostly noise)', function(bench) {
33+
run(300, bench)
34+
})

Diff for: scenarios/light-serial/pinky-sync.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var pinky = require('pinky-sync')
2+
3+
var listTest = require('./promises')(function(f) {
4+
var p = pinky()
5+
f(p.fulfill, p.reject)
6+
return p })
7+
8+
function raise(e) {
9+
process.nextTick(function(){ throw e })}
10+
11+
12+
module.exports = function(path, noiseFactor) { return function(deferred) {
13+
return listTest(path, noiseFactor)
14+
.then(function(v) { deferred.resolve() })
15+
.otherwise(raise)
16+
}}

Diff for: scenarios/light-serial/pinky.js

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
var pinky = require('pinky')
2+
3+
var listTest = require('./promises')(function(f) {
4+
var p = pinky()
5+
f(p.fulfill, p.reject)
6+
return p })
7+
8+
function raise(e) {
9+
process.nextTick(function(){ throw e })}
10+
11+
12+
module.exports = function(path, noiseFactor) { return function(deferred) {
13+
return listTest(path, noiseFactor)
14+
.then(function(v) { deferred.resolve() })
15+
.otherwise(raise)
16+
}}

0 commit comments

Comments
 (0)