2016-10-14 12 views
6

を持っている私は、.NETのための公式のNeo4jドライバを使用してプロジェクトのためのNeo4jを使用していますここで見つける:のNeo4jは非常に高遅延

https://www.nuget.org/packages/Neo4j.Driver

をこのドライバは、私の仮定がされ、ボルトプロトコル上で動作します特殊なバイナリプロトコルがHTTP APIより効率的であることを示しています。しかし、プロジェクトの開始以来、私は非常に簡単な操作でさえ、Neo4jからのレイテンシが比較的高いことに気付きました。 UserIDは、インデックスフィールドがあり、データベースがそうでなければ完全に空にするときは、次の撮影のような試合は30-60msのような:

match(n:User { UserID: 1 }) return n.UserID 

この現象は、両方の私のローカルマシン上で、当社の生産環境(ゼロネットワークオーバーヘッド近く) 。私は今日これを調査し始めて、クエリがすぐに返されることを発見しましたが、実際に結果をストリームするには時間がかかります。たとえば、ローカルホストで呼び出しが返される前に0.2msを受け取るが、ToArray()result(この場合は単一の整数フィールドであるレコードをバッファリングする)を呼び出すと、60msに時間が長くなります。

using (var driver = GraphDatabase.Driver($"bolt://localhost:7687", AuthTokens.Basic("neo4j", "1"))) 
{  
    using (var session = driver.Session()) 
    { 
     // 0.2ms to return from this call 
     var result = session.Run("match(n:User { ID: 1}) return n.ID"); 

     // Uncommenting this makes the whole thing take 60ms 
     // result.ToArray(); 
    } 
} 

私は、コミュニティはHTTP上で動作Neo4jClientパッケージ、後援試してみました:同じクエリで

https://github.com/Readify/Neo4jClient

を、合計時間はちょうど0.5msのに縮小されています

var client = new GraphClient(new Uri("http://localhost:7474/db/data"), "neo4j", "1"); 
client.Connect(); 

client.Cypher.Match("(n:User { ID: 1})").Return<int>("n.ID").Results.ToArray(); 

より公式なベンチマークを実行すると、ボルト駆動の公式ドライバとHTTPベースのNeo4jClientとの大きな違い、次の結果が得られます。

Host Process Environment Information: 
BenchmarkDotNet.Core=v0.9.9.0 
OS=Microsoft Windows NT 6.2.9200.0 
Processor=Intel(R) Core(TM) i7-4770 CPU 3.40GHz, ProcessorCount=8 
Frequency=3312642 ticks, Resolution=301.8739 ns, Timer=TSC 
CLR=MS.NET 4.0.30319.42000, Arch=32-bit RELEASE 
GC=Concurrent Workstation 
JitModules=clrjit-v4.6.1586.0 

Type=Neo4jBenchmarks Mode=Throughput Platform=X64 
Jit=RyuJit 

     Method |   Median |  StdDev | Scaled | Scaled-SD | 
------------- |--------------- |------------ |------- |---------- | 
    Neo4jClient | 382.5675 us | 3.3771 us | 1.00 |  0.00 | 
Neo4jSession | 61,299.9382 us | 690.1626 us | 160.02 |  2.24 | 

だから、HTTPクライアントは、ネットワークのオーバーヘッドが無視できるとき160X高速です。

私たちの実稼働環境でもベンチマークを実行しましたが、その差はそれほど大きくはありませんでしたが、HTTPメソッドはまだ6倍高速でした(ネットワーク接続がかなり遅い)。

フルベンチマークコード:

public class Neo4jBenchmarks 
{ 
    private readonly IDriver _driver; 
    private readonly GraphClient _client; 

    public Neo4jBenchmarks() 
    { 
     _driver = GraphDatabase.Driver("bolt://localhost:7687", AuthTokens.Basic("neo4j", "1")); 
     _client = new GraphClient(new Uri("http://localhost:7474/db/data"), "neo4j", "1"); 
     _client.Connect(); 
    } 

    [Benchmark(Baseline = true)] 
    public void Neo4jClient() 
    { 
     _client.Cypher.Match("(n:User { ID: 1})").Return<int>("n.ID").Results.ToArray(); 
    } 

    [Benchmark] 
    public void Neo4jSession() 
    { 
     using (var session = _driver.Session()) 
     { 
     session.Run("match(n:User { ID: 1}) return n.ID").ToArray(); 
     } 
    } 
} 

私は、Windows 10および生産上でそれを実行しているのに、私のマシンと生産の両方が、のNeo4j CE 3.0.4(現在はコミュニティ版)を実行しているがLinuxマシンであります。私は自分の知る限り設定を微調整していませんが、パフォーマンス上の違いが160倍になるとは思えません。

セッションを作成するにはトランザクションを作成する必要があるため、セッションオブジェクトを再利用しようとしました(これはスレッドセーフではないので非常に悪い考えです)目立つ。

私はNeo4jClientを使うことができますが、実際には任意の文字列クエリを実行する必要があります。Neo4jClientは流暢なAPIに大いに依存していますが、低レベルの文字列モードを提供します。

+0

私は、文字列をクエリに使用できるようにするために全面的にオープンしています。必要な構文を使用してバグを立てたり、理想的にバグを修正することができます。 –

+0

@ChrisSkardon - これは素晴らしいことだ!私が何かをハックすることができるかどうか見てみましょう。私が基本的に探しているのは、Neo4jのDapperです:低レベル、入力は文字列とパラメータで、結果をオブジェクトにマッピングするだけです。 – JulianR

答えて

4

さらに掘り下げた後、私はNeo4jにその問題を追跡しました。ドライバパッケージは特に、NodeJSのドライバは同じ問題を抱えていませんでした。

パッケージの現在のsourceをクローニングし、DLLを構築してNuGetパッケージの代わりにDLLを直接参照することで、この問題は完全に解消されました。 NuGet(1.0.2)上の現在のバージョンは62秒のローカルホストに対して1000回の単純一致要求を行いますが、現在のソースは0.3秒でこれを行います(NodeJSドライバを10倍)。

私はそれほど確かではありませんが、現在のパッケージのrda.SocketsForPCL依存関係と関係があります。これは、ソケットをクロスプラットフォームで動作させるための接着ライブラリと思われます。しかし、現在のソースはそのためにSystem.Net.Socketsパッケージを参照しています。

結論として、この問題はソースの現在のビルドを参照することで回避でき、新しいバージョンのパッケージがリリースされると完全に解決されます。

関連する問題