2016-10-14 16 views
6

Tôi đang sử dụng Neo4j cho một dự án sử dụng trình điều khiển Neo4j chính thức cho .NET tìm thấy ở đây:Neo4j qua giao thức tia có độ trễ rất cao

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

lái xe này hoạt động thông qua giao thức bu lông, giả định của tôi là rằng một giao thức nhị phân chuyên biệt sẽ hiệu quả hơn API HTTP. Nhưng kể từ khi bắt đầu dự án, tôi đã nhận thấy độ trễ tương đối cao từ Neo4j cho các hoạt động thậm chí rất đơn giản. Chẳng hạn như một trận đấu như việc lấy sau 30-60ms khi UserID là một lĩnh vực được lập chỉ mục và cơ sở dữ liệu bằng cách khác là hoàn toàn trống rỗng:

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

Hành vi này xảy ra cả trên máy tính địa phương của tôi (gần bằng không mạng overhead) và môi trường sản xuất của chúng tôi . Tôi bắt đầu điều tra điều này ngày hôm nay và thấy rằng truy vấn trả về một cách nhanh chóng, nhưng phải mất một thời gian dài để thực sự truyền trong các kết quả. Ví dụ, truy vấn dưới đây có 0.2ms trước khi trả về cuộc gọi trên máy chủ cục bộ, nhưng sau đó gọi ToArray() trên result (đệm các bản ghi, trong trường hợp này là trường số nguyên duy nhất) tăng thời gian lên 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(); 
    } 
} 

sau đó tôi đã cố gắng cộng đồng tài trợ Neo4jClient gói, trong đó hoạt động trên HTTP:

https://github.com/Readify/Neo4jClient

Với cùng một truy vấn, tổng thời gian được giảm xuống chỉ còn 0.5 ms:

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(); 

Chạy một chuẩn mực chính thức hơn cho kết quả sau đây, một sự khác biệt lớn giữa trình điều khiển chính thức bằng bolt và Neo4jClient dựa trên HTTP.

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 | 

Vì vậy, các khách hàng HTTP là 160x nhanh khi mạng overhead là không đáng kể.

Tôi cũng chạy điểm chuẩn trên môi trường sản xuất của chúng tôi và khi chênh lệch không lớn, phương pháp HTTP vẫn nhanh hơn 6 lần (và kết nối mạng của tôi với sản xuất khá chậm).

Mã chuẩn đầy đủ:

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(); 
     } 
    } 
} 

Cả hai máy và sản xuất của tôi đang chạy Neo4j CE 3.0.4 (hiện tại phiên bản cộng đồng), mặc dù tôi đang chạy nó trên Windows 10 và sản xuất là một máy Linux . Chúng tôi chưa tinh chỉnh bất kỳ cài đặt nào cho kiến ​​thức của mình, nhưng tôi nghi ngờ rằng có thể giải thích sự khác biệt về hiệu suất 160x. Tôi cũng đã cố gắng sử dụng lại đối tượng phiên (mà tôi nghĩ là một ý tưởng rất tồi vì nó không an toàn cho luồng) vì tạo phiên liên quan đến việc tạo giao dịch, để xem điều đó có tạo sự khác biệt hay không, nhưng nó không phải là ' t đáng chú ý.

Tôi muốn tôi có thể sử dụng Neo4jClient, nhưng chúng tôi thực sự cần khả năng thực hiện truy vấn chuỗi tùy ý, trong khi Neo4jClient dựa chủ yếu vào API thông thạo và trong khi nó cung cấp chế độ chuỗi cấp thấp, nó không được chấp nhận và actively discouraged in the documentation.

+0

Tôi hoàn toàn mở để làm cho khả năng sử dụng chuỗi truy vấn, hoặc là kéo hoặc nâng cao lỗi lý tưởng với cú pháp bạn muốn và chúng tôi có thể thấy những gì chúng tôi có thể làm! –

+0

@ChrisSkardon - Điều đó thật tuyệt! Những gì tôi đang tìm kiếm cơ bản là một Dapper cho Neo4j: mức độ thấp, đầu vào là một chuỗi và các thông số và tôi chỉ nhận được trợ giúp với ánh xạ kết quả cho một đối tượng. – JulianR

Trả lời

4

Sau khi đào sâu hơn, tôi đã theo dõi sự cố với Neo4j.Trình điều khiển gói đặc biệt, như trình điều khiển cho NodeJS không bị vấn đề tương tự.

Nhân bản gói source hiện tại của gói, xây dựng nó và tham chiếu DLL trực tiếp thay vì gói NuGet đã loại bỏ hoàn toàn vấn đề. Để đưa vào quan điểm: phiên bản hiện tại trên NuGet (1.0.2) mất 62 giây để thực hiện 1000 yêu cầu đối sánh đơn giản đối với máy chủ cục bộ, trong khi nguồn hiện tại làm như vậy trong 0,3 giây (thậm chí đánh bại trình điều khiển NodeJS) hệ số 10).

Tôi không hoàn toàn chắc chắn tại sao, nhưng tôi khá chắc chắn nó có liên quan đến sự phụ thuộc rda.SocketsForPCL của gói hiện tại, có vẻ là thư viện keo để làm cho ổ cắm hoạt động đa nền tảng. Tuy nhiên, nguồn hiện tại tham chiếu đến gói System.Net.Sockets cho điều đó. Vì vậy, trong kết luận, vấn đề này có thể được giải quyết bằng cách tham chiếu một bản dựng nguồn hiện tại và sẽ được giải quyết hoàn toàn khi một phiên bản mới của gói được phát hành.

Các vấn đề liên quan