andreasronge/neo4j-core — pull request #81 by subvertallchris (2014-07-03 18:41:56+00:00)
Title: single session of ExecutionEngine in embedded DB

I was researching Cypher query optimization and stumbled upon this:

> I came across a post in the Neo4j mailing list, where Michael mentioned NOT re-instantiating the ExecutionEngine so that the above said parameterized queries actually do cache.
(http://www.javacodegeeks.com/2013/01/optimizing-neo4j-cypher-queries.html)

Checked out the source and discovered this:

```ruby
# Performs a cypher query with given string.
# Remember that you should close the resource iterator.
# @param [String] q the cypher query as a String
# @return (see #query)
def _query(q, params={})
engine = Java::OrgNeo4jCypherJavacompat::ExecutionEngine.new(@graph_db)
engine.execute(q, Neo4j::Core::HashWithIndifferentAccess.new(params))
rescue Exception => e
raise Neo4j::Session::CypherError.new(e.message, e.class, 'cypher error')
end
```
Tweaking it to set `@engine` during start and reuse that the two times it appears in the code to have led to a massive performance boost for Cypher queries when using the Embedded server.

```ruby
OLD

a = 20.upto(31).to_a
15000.times { Student.create(age: a.sample) }
20.times { puts Benchmark.measure { Student.all({age: 30}).to_a.count }}
0.550000 0.020000 0.570000 ( 0.571000)
0.610000 0.010000 0.620000 ( 0.593000)
0.600000 0.000000 0.600000 ( 0.562000)
0.580000 0.010000 0.590000 ( 0.555000)
0.540000 0.000000 0.540000 ( 0.543000)
0.570000 0.000000 0.570000 ( 0.566000)
0.560000 0.010000 0.570000 ( 0.568000)
0.580000 0.000000 0.580000 ( 0.582000)
0.530000 0.000000 0.530000 ( 0.513000)
0.550000 0.010000 0.560000 ( 0.535000)
0.560000 0.000000 0.560000 ( 0.562000)
0.550000 0.000000 0.550000 ( 0.542000)
0.520000 0.000000 0.520000 ( 0.524000)
0.580000 0.010000 0.590000 ( 0.570000)
0.940000 0.020000 0.960000 ( 0.605000)
0.540000 0.000000 0.540000 ( 0.547000)
0.530000 0.000000 0.530000 ( 0.532000)
0.550000 0.000000 0.550000 ( 0.551000)
0.540000 0.010000 0.550000 ( 0.534000)
0.540000 0.000000 0.540000 ( 0.537000)

20.times { puts Benchmark.measure { Student.all({age: 30}).to_a.count }}
0.610000 0.020000 0.630000 ( 0.614000)
0.580000 0.000000 0.580000 ( 0.552000)
0.650000 0.010000 0.660000 ( 0.576000)
0.560000 0.000000 0.560000 ( 0.551000)
0.610000 0.000000 0.610000 ( 0.607000)
0.550000 0.010000 0.560000 ( 0.552000)
0.660000 0.000000 0.660000 ( 0.653000)
0.600000 0.000000 0.600000 ( 0.589000)
0.700000 0.010000 0.710000 ( 0.674000)
0.530000 0.000000 0.530000 ( 0.531000)
0.570000 0.000000 0.570000 ( 0.551000)
0.590000 0.010000 0.600000 ( 0.583000)
0.570000 0.000000 0.570000 ( 0.569000)
0.670000 0.000000 0.670000 ( 0.652000)
0.550000 0.010000 0.560000 ( 0.551000)
0.620000 0.000000 0.620000 ( 0.584000)
0.570000 0.000000 0.570000 ( 0.554000)
0.590000 0.010000 0.600000 ( 0.566000)
0.570000 0.000000 0.570000 ( 0.548000)
0.580000 0.000000 0.580000 ( 0.577000)

NEW

jruby-1.7.10 :003 > 20.times { puts Benchmark.measure { Student.all({age: 30}).to_a.count }}
4.660000 0.130000 4.790000 ( 3.222000)
0.560000 0.010000 0.570000 ( 0.404000)
0.640000 0.010000 0.650000 ( 0.405000)
0.940000 0.010000 0.950000 ( 0.358000)
0.660000 0.010000 0.670000 ( 0.331000)
0.300000 0.000000 0.300000 ( 0.243000)
0.300000 0.010000 0.310000 ( 0.263000)
0.450000 0.000000 0.450000 ( 0.239000)
0.730000 0.020000 0.750000 ( 0.270000)
0.510000 0.000000 0.510000 ( 0.204000)
0.150000 0.000000 0.150000 ( 0.156000)
0.220000 0.010000 0.230000 ( 0.192000)
0.170000 0.000000 0.170000 ( 0.147000)
0.180000 0.000000 0.180000 ( 0.162000)
0.130000 0.000000 0.130000 ( 0.136000)
0.170000 0.010000 0.180000 ( 0.163000)
0.140000 0.000000 0.140000 ( 0.138000)
0.130000 0.000000 0.130000 ( 0.134000)
0.170000 0.000000 0.170000 ( 0.175000)
0.160000 0.000000 0.160000 ( 0.154000)
=> 20

20.times { puts Benchmark.measure { Student.all({age: 30}).to_a.count }}
0.150000 0.010000 0.160000 ( 0.157000)
0.170000 0.020000 0.190000 ( 0.176000)
0.140000 0.000000 0.140000 ( 0.141000)
0.140000 0.000000 0.140000 ( 0.140000)
0.170000 0.000000 0.170000 ( 0.164000)
0.150000 0.000000 0.150000 ( 0.147000)
0.190000 0.010000 0.200000 ( 0.177000)
0.290000 0.010000 0.300000 ( 0.173000)
0.170000 0.000000 0.170000 ( 0.159000)
0.190000 0.000000 0.190000 ( 0.150000)
0.220000 0.000000 0.220000 ( 0.190000)
0.140000 0.000000 0.140000 ( 0.143000)
0.210000 0.010000 0.220000 ( 0.183000)
0.240000 0.000000 0.240000 ( 0.147000)
0.160000 0.000000 0.160000 ( 0.152000)
0.150000 0.000000 0.150000 ( 0.145000)
0.120000 0.010000 0.130000 ( 0.127000)
0.210000 0.000000 0.210000 ( 0.164000)
0.170000 0.000000 0.170000 ( 0.132000)
0.150000 0.000000 0.150000 ( 0.148000)

```
One more reason to use JRuby in production.