Skip to content

Commit e260c79

Browse files
author
moxious
authored
Merge pull request #3 from moxious/v0.4.0
V0.4.0
2 parents 69ce345 + 1efcdcd commit e260c79

20 files changed

+147
-86
lines changed

README.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ Create a lot of nodes as fast as possible:
7575
npm run graph-workload -- -a localhost -u neo4j -p admin --query 'Unwind range(1,1000000) as id create (n);' -n 50 --concurrency 4
7676
```
7777

78+
# Neo4j 4.0 / Multidatabase
79+
80+
As of Neo4j 4.0, sessions support multi-database. Use the `-d` or `--database` argument to direct
81+
where the workload should go. By default, the workload goes to the default database (usually `neo4j`).
82+
83+
Example:
84+
85+
```
86+
npm run graph-workload -- -a neo4j://my-cluster -u neo4j -p admin --database mydb
87+
```
88+
7889
# Tests
7990

8091
```

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "graph-workload",
3-
"version": "0.3.1",
3+
"version": "0.4.0",
44
"description": "Tool for generating workloads running on Neo4j",
55
"main": "src/run-workload.js",
66
"scripts": {
@@ -23,9 +23,9 @@
2323
"es6-promise-pool": "^2.5.0",
2424
"faker": "^4.1.0",
2525
"generic-pool": "^3.6.1",
26-
"lodash": "^4.17.11",
26+
"lodash": "^4.17.15",
2727
"moment": "^2.24.0",
28-
"neo4j-driver": "^1.7.2",
28+
"neo4j-driver": "^4.0.1",
2929
"randomstring": "^1.1.5",
3030
"uuid": "^3.3.2",
3131
"yargs": "^12.0.5"

src/Strategy.js

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,18 @@ class Strategy {
99
this.timings = [];
1010
}
1111

12+
sessionOptions() {
13+
const opts = {};
14+
15+
if (this.props.runConfig && this.props.runConfig.database) {
16+
opts.database = this.props.runConfig.database;
17+
} else if (!this.props.runConfig) {
18+
throw new Error('Strategy initialized without runConfig');
19+
}
20+
21+
return opts;
22+
}
23+
1224
setup(driver) {
1325
this.driver = driver;
1426
return Promise.resolve(true);
@@ -65,6 +77,16 @@ class Strategy {
6577
console.log(`${this.name}: ${runs} runs avg ${avgV.toFixed(2)} ms min ${minV} ms max ${maxV} ms\n`);
6678
}
6779

80+
ignore(e, match) {
81+
const str = `${e}`;
82+
83+
if (str.indexOf(match) > -1) {
84+
return true;
85+
}
86+
87+
throw e;
88+
}
89+
6890
time(somePromiseFunc, data={}) {
6991
const start = new Date().getTime();
7092

src/read-strategy/RandomAccessReadStrategy.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
const Strategy = require('../Strategy');
2+
const neo4j = require('neo4j-driver');
23

34
class RandomAccessReadStrategy extends Strategy {
45
constructor(props) {
56
super(props);
67
this.name = 'RandomAccessRead';
7-
this.prime = props.prime || 1093;
8-
this.limit = props.limit || 50;
8+
this.prime = neo4j.int(props.prime || 1093);
9+
this.limit = neo4j.int(props.limit || 50);
910
}
1011

1112
run() {
12-
const nth = Math.floor(Math.random() * this.prime) + 1;
13-
const skip = Math.floor(Math.random() * 1000) + 1;
13+
const nth = neo4j.int(Math.floor(Math.random() * this.prime) + 1);
14+
const skip = neo4j.int(Math.floor(Math.random() * 1000) + 1);
1415

1516
const f = (s) => s.readTransaction(tx => tx.run(`
1617
MATCH (node)
1718
WHERE id(node) % $prime = $nth
1819
RETURN keys(node)
1920
SKIP $skip LIMIT $limit`,
20-
{ prime: this.prime, nth, skip, limit: this.limit }));
21+
{ prime: this.prime, nth, skip, limit: this.limit }));
2122

2223
return this.time(f);
2324
}

src/run-configuration.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ const generateFromArgs = (args) => {
125125
checkpointFreq: args.checkpoint || process.env.CHECKPOINT_FREQUENCY || 5000,
126126
failFast,
127127
phase: 'NOT_STARTED',
128+
database: args.database || args.d || null,
128129
}, terminationType, probabilityTable, connectionDetails, concurrency);
129130

130131
if (obj.runType === 'counted') {
@@ -147,6 +148,7 @@ module.exports = {
147148
.describe('a', 'address to connect to')
148149
.describe('u', 'username')
149150
.describe('p', 'password')
151+
.describe('d', 'database')
150152
.describe('n', 'number of hits on the database')
151153
.describe('ms', 'number of milliseconds to execute')
152154
.describe('workload', 'absolute path to JSON probability table/workload')

src/sessionPool.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ let sessionPool = null;
1111
* ones who are pulling these sessions.
1212
*/
1313
module.exports = {
14-
getPool: (driver, poolSize) => {
14+
getPool: (driver, options) => {
1515
if (sessionPool) {
1616
return sessionPool;
1717
}
@@ -20,7 +20,11 @@ module.exports = {
2020
// See the generic-pool module for more details.
2121
const factory = {
2222
create: () => {
23-
const s = driver.session();
23+
const config = {};
24+
if (options.database) {
25+
config.database = options.database;
26+
}
27+
const s = driver.session(config);
2428
return s;
2529
},
2630
destroy: session => {
@@ -32,7 +36,7 @@ module.exports = {
3236
.catch(err => false),
3337
};
3438

35-
const sessionPoolOpts = { min: 1, max: poolSize };
39+
const sessionPoolOpts = { min: 1, max: options.concurrency || 10 };
3640
console.log('Creating session pool with ', sessionPoolOpts);
3741
sessionPool = genericPool.createPool(factory, sessionPoolOpts);
3842
sessionPool.on('factoryCreateError', err => console.log('SESSION POOL ERROR', err));

src/strategies.js

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -26,21 +26,21 @@ const RandomAccessReadStrategy = require('./read-strategy/RandomAccessReadStrate
2626
const builder = (sessionPool, runConfig) => {
2727
const defaultStratTable = {
2828
// WRITE STRATEGIES
29-
naryWrite: new NAryTreeStrategy({ n: 2, sessionPool }),
30-
fatnodeWrite: new FatNodeAppendStrategy({ sessionPool }),
31-
mergeWrite: new MergeWriteStrategy({ n: 1000000, sessionPool }),
32-
rawWrite: new RawWriteStrategy({ n: 10, sessionPool }),
33-
randomLinkage: new RandomLinkageStrategy({ n: 1000000, sessionPool }),
34-
starWrite: new StarWriteStrategy({ sessionPool }),
35-
indexHeavy: new IndexHeavyStrategy({ sessionPool }),
36-
lockTorture: new LockTortureStrategy({ sessionPool }),
37-
luceneWrite: new LuceneWriteStrategy({ sessionPool }),
29+
naryWrite: new NAryTreeStrategy({ n: 2, sessionPool, runConfig }),
30+
fatnodeWrite: new FatNodeAppendStrategy({ sessionPool, runConfig }),
31+
mergeWrite: new MergeWriteStrategy({ n: 1000000, sessionPool, runConfig }),
32+
rawWrite: new RawWriteStrategy({ n: 10, sessionPool, runConfig }),
33+
randomLinkage: new RandomLinkageStrategy({ n: 1000000, sessionPool, runConfig }),
34+
starWrite: new StarWriteStrategy({ sessionPool, runConfig }),
35+
indexHeavy: new IndexHeavyStrategy({ sessionPool, runConfig }),
36+
lockTorture: new LockTortureStrategy({ sessionPool, runConfig }),
37+
luceneWrite: new LuceneWriteStrategy({ sessionPool, runConfig }),
3838

3939
// READ STRATEGIES
40-
aggregateRead: new AggregateReadStrategy({ sessionPool }),
41-
metadataRead: new MetadataReadStrategy({ sessionPool }),
42-
longPathRead: new LongPathReadStrategy({ sessionPool }),
43-
randomAccess: new RandomAccessReadStrategy({ sessionPool }),
40+
aggregateRead: new AggregateReadStrategy({ sessionPool, runConfig }),
41+
metadataRead: new MetadataReadStrategy({ sessionPool, runConfig }),
42+
longPathRead: new LongPathReadStrategy({ sessionPool, runConfig }),
43+
randomAccess: new RandomAccessReadStrategy({ sessionPool, runConfig }),
4444
};
4545

4646
if (runConfig) {

src/workload.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
const pool = require('./sessionPool');
22
const strategies = require('./strategies');
33
const WorkloadStats = require('./stats');
4-
const neo4j = require('neo4j-driver').v1;
4+
const neo4j = require('neo4j-driver');
55
const uuid = require('uuid');
66
const PromisePool = require('es6-promise-pool');
77

@@ -65,7 +65,7 @@ class Workload {
6565
this.driver = neo4j.driver(this.runConfig.address,
6666
neo4j.auth.basic(this.runConfig.username, this.runConfig.password));
6767

68-
this.sessionPool = pool.getPool(this.driver, this.runConfig.concurrency);
68+
this.sessionPool = pool.getPool(this.driver, this.runConfig);
6969
this.strategyTable = strategies.builder(this.sessionPool, this.runConfig);
7070
this.stats = new WorkloadStats(this.runConfig);
7171

src/write-strategy/IndexHeavyStrategy.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ class IndexHeavyStrategy extends Strategy {
1414

1515
setup(driver) {
1616
super.setup(driver);
17-
const session = driver.session();
17+
const session = driver.session(this.sessionOptions());
1818

1919
const queries = [
2020
'CREATE INDEX ON :Customer(id)',
@@ -40,8 +40,12 @@ class IndexHeavyStrategy extends Strategy {
4040
'CREATE INDEX ON :Address(score)',
4141
];
4242

43-
return Promise.map(queries, q => session.run(q))
44-
.then(() => session.close());
43+
return Promise.all(queries.map(q => {
44+
const session = driver.session(this.sessionOptions());
45+
return session.run(q)
46+
.then(() => session.close())
47+
.catch(e => this.ignore(e, 'An equivalent index already exists'));
48+
}));
4549
}
4650

4751
run() {

src/write-strategy/LockTortureStrategy.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ class LockTortureStrategy extends Strategy {
1919

2020
setup(driver) {
2121
super.setup(driver);
22-
const session = driver.session();
22+
const session = driver.session(this.sessionOptions());
2323

2424
// Set up some basic nodes and index.
2525
const queries = [

0 commit comments

Comments
 (0)