Jul*_*anR 6 .net performance latency neo4j neo4jclient
我正在使用Neo4j进行使用官方Neo4j驱动程序for .NET的项目:
https://www.nuget.org/packages/Neo4j.Driver
这个驱动程序适用于bolt协议,我的假设是专用二进制协议比HTTP API更有效.但是从项目开始以来,我注意到Neo4j的延迟相对较高,即使是非常简单的操作也是如此.比如下面的匹配,如果UserID是索引字段,则数据库取30-60ms,否则数据库完全为空:
match(n:User { UserID: 1 }) return n.UserID
Run Code Online (Sandbox Code Playgroud)
在我的本地计算机(接近零网络开销)和我们的生产环境中都会发生此行为.我今天开始调查此问题并发现查询很快返回,但实际流式传输结果需要很长时间.例如,下面的查询需要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();
}
}
Run Code Online (Sandbox Code Playgroud)
然后我尝试了社区赞助的Neo4jClient包,它可以通过HTTP工作:
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();
Run Code Online (Sandbox Code Playgroud)
运行更官方的基准测试会得到以下结果,螺栓驱动的官方驱动程序和基于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 |
Run Code Online (Sandbox Code Playgroud)
因此,当网络开销可以忽略不计时,HTTP客户端的速度提高了160倍.
我还在我们的生产环境中运行了基准测试,虽然差异不是很大,但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();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的机器和生产都运行Neo4j CE 3.0.4(目前是社区版),虽然我在Windows 10上运行它,生产是Linux机器.我们没有根据我的知识调整任何设置,但我怀疑这可以解释160倍的性能差异.
我也尝试重用会话对象(我认为这是一个非常糟糕的主意,因为它不是线程安全的)因为创建一个会话涉及创建一个事务,看看是否有所作为,但它并不明显.
我希望我可以使用Neo4jClient,但是我们真的需要能够执行任意字符串查询,而Neo4jClient在很大程度上依赖于流畅的API,虽然它提供了低级别的字符串模式,但它已被弃用并且在文档中不鼓励.
经过进一步挖掘,我将问题追溯到 Neo4j.Driver 包,因为 NodeJS 的驱动程序没有遇到同样的问题。
克隆包的当前源、构建它并直接引用 DLL(而不是 NuGet 包)完全消除了问题。客观地说:NuGet 上的当前版本 (1.0.2) 需要62 秒才能对 localhost 执行 1000 个简单匹配请求,而当前源代码只需0.3 秒即可完成(甚至比 NodeJS 驱动程序快 10 倍) 。
我不太清楚为什么,但我很确定它与当前包的依赖关系有关rda.SocketsForPCL,当前包似乎是一个使套接字跨平台工作的粘合库。然而,当前的源代码引用了System.Net.Sockets该包。
总之,这个问题可以通过引用源代码的当前版本来解决,并且在发布新版本的包时将得到完全解决。
| 归档时间: |
|
| 查看次数: |
371 次 |
| 最近记录: |