neo4j / neo4j-javascript-driver

Neo4j Bolt driver for JavaScript

Home Page:https://neo4j.com/docs/javascript-manual/current/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Driver Performance

Sydney-o9 opened this issue · comments

We are Neo4j cloud users and are measuring performance using Sentry.

Our backend application simply leverages the neo4j-javascript-driver to make calls to our Neo4j cloud db.

It takes almost 750ms for the driver to initialise and fulfil the request

Neo4j

I'm looking for ways to improve this, ideally would like to know how long it takes for:

  • the driver to be initialised
  • the request to Neo4j to fulfil
  • the parsing to be complete

Overall, I found the driver to be slow, but I have no proof, I want to measure this.

Can you give us ways to assess the performance of the driver in our application?

Hi Team, if you could please give some indication here - that'd be appreciated

Hi @Sydney-o9,

the internal timings in the driver are not exposed, but you can troubleshooting by check:

import neo4j from 'neo4j-driver'

const mydbname = "the database name, usually 'neo4j'"
const driver = neo4j.driver(...)

// Check the timing for this request
// This one should just bootstrap the driver and do a handshake with the database
await driver.getServerInfo({ database: mydbname }) 


// Measure the time for running the query
const { records, summary } = await driver.executeQuery(query, params, { database: mydbname })

You an also check in the summary, the time the database get to consume the result (https://neo4j.com/docs/api/javascript-driver/current/class/lib6/result-summary.js~ResultSummary.html#instance-member-resultConsumedAfter), this can be useful for checking if the issue are in the query.

Could you inform also the NodeJS version, Driver version, Database version and some snippet to see what you're doing?

Hello,
We're facing similar performance issues :

  • Our database is hosted on neo4j aura, in Francfort (we're in France) version 4.4 (we're facing the problem on 2 different DBs, staging and production, production db is 4x larger than staging)
  • We're using the latest version of neo4j-javascript-driver
  • node 18.10

All timings are captured around this snipped of code

export class Neo4jHelper {
  private driver: Driver

  constructor() {
      this.driver = neo4j.driver(
        neo4jAccount?.uri,
        neo4j.auth.basic(neo4jAccount?.user, neo4jAccount?.password),
        { disableLosslessIntegers: true },
      )
  }

  public async read(query: string, config?: TransactionConfig) {
    const session = this.driver.session()
    try {
      return await session.executeRead(tx => tx.run(query, config))
    } finally {
      await session.close()
    }
  }
}

A few examples that caught our attention, they are reproducible and don't appear to be some random variation. Almost all of our call exhibit the same patterns.

Example 1

The call to read took 700ms, to return the label of a single node.
Consuming the records themselves takes 0 time units (0 ms).

image image

Example 2

A slightly more complex query, that took approximately 2.4s to read() and returns about 2k records (with 10 fields each)

image

The query itself took 260 ms for records to be consumed, which leaves an overhead of 2.2s in the driver itself.

image

Questions

  • Is there something obviously wrong about our code above ? I haven't added the tracing code, but it just wraps the call to read, nothing else (and I've tried with an without instrumentation, top level timings are similar)
  • I initially suspected transport latency between our DB and my server, but the numbers are so large especially the second one, that it feels way off. Am I correct, or does this look like transport latency ?

The time measures reported in the resultConsumedAfter and resultAvailableAfter are calculated without taking in consideration any networking.

The driver itself take some work to bootstrap, so if you are creating a driver for each request, you will might have issues. Setting the database name in the session creation is highly recommend in the environments with high latency, since when the database name is not set, the driver will take an extra round trip to resolve the database name. In Aura, the database name is neo4j. So, you might create the session like:

const session = this.driver.session({ database: 'neo4j' })

The first request might get a bit more time because the driver will fetch the cluster formation before trigger the first query, but the next requests should be faster.