-
Notifications
You must be signed in to change notification settings - Fork 147
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The JavaScript driver is about 4 times slower than the C# one #1223
Comments
I also tried hacking together a custom client that uses the HTTP API and the same query takes up to ~11 seconds less
async function execute(pass: string) {
const conn = new Connection("http://localhost:7474/db/neo4j/tx/commit", authBasic("neo4j", pass));
console.time("query");
const out = [];
for await (const elm of conn.run`MATCH (master:Cont_SCH_Master)-[:HAS]->(x:Cont_SCH) RETURN master, collect(x) as details`)
out.push(elm);
console.timeEnd("query");
return out;
} The source code of the custom client(If you want to test it for yourself) import { JSONParser, ParsedElementInfo } from "@streamparser/json";
/** Oggetto che rappresenta una singola query Neo4j */
export type Statement = { statement: string, parameters?: object };
/** Oggetto che permette di evitare di ripetere l'autenticazione per ogni query */
export class Connection {
constructor(public url: string, public auth: string) { }
/**
* Crea uno {@link Statement} passando i parametri a {@link stmt} e lo esegue tramite {@link query}
* @param str La stringa contenente la query in Cypher
* @param args I parametri della query
*/
run(str: TemplateStringsArray, ...args: any[]) {
return this.query([ stmt(str, args) ]);
}
/**
* Esegue una lista di istruzioni
* @param list La lista di istruzioni da eseguire
*/
async *query(list: Statement[]) {
const res = await fetch(this.url, createRequest(this.auth, list));
const reader = res
.body!
.pipeThrough(new TextDecoderStream())
.pipeThrough(createJSONParserStream(["$.results.*.data.*"]));
for await (const elm of reader)
yield elm.value;
}
}
/**
* Funzione che codifica le credenziali di una autenticazione basica
* @param user L'utente col quale autenticarsi
* @param pass La password di {@link user}
*/
export function authBasic(user: string, pass: string) {
return `Basic ${btoa(`${user}:${pass}`)}`;
}
/**
* Crea uno {@link Statement} usando una stringa template
* @param str La stringa contenente la query in Cypher
* @param args I parametri della query
*/
export function stmt(str: TemplateStringsArray, ...args: any[]): Statement {
var statement = str[0];
const parameters: Record<string, any> = {};
for (var i = 0; i < args.length; i++) {
const k = `v${i}`;
parameters[k] = args[i];
statement += `$${k}${str[i + 1]}`;
}
return { statement, parameters };
}
/**
* Crea un {@link TransformStream} che parsa un pezzo per volta un flusso di stringhe
* @param paths Percorsi JSON da emettere
*/
export function createJSONParserStream(paths?: string[]) {
const parser = new JSONParser({ paths });
return new TransformStream<string, ParsedElementInfo.ParsedElementInfo>({
start: controller => parser.onValue = controller.enqueue.bind(controller),
transform: chunk => parser.write(chunk)
});
}
/**
* Crea il boilerplate per eseguire una richiesta
* @param auth L'header di autenticazione
* @param statements La lista delle istruzioni da eseguire
*/
function createRequest(auth: string, statements: Statement[]): RequestInit {
return {
method: "post",
body: JSON.stringify({ statements }),
headers: {
"Accept": "application/json;charset=UTF-8",
"Content-Type": "application/json",
"Authorization": auth
}
};
} |
Hi, thanks for reaching out!
Short answer: Yes Long answer: The JS driver is slower when it comes to parsing large records, which I would guess is what is taking up the bulk of the time in your test. JSON.parse is going to be faster, but the driver parses from Bolt, which is a binary protocol, and applies special handling to some parts of responses. |
Is there maybe some possibility to speed up the binary parsing by taking advantage of WebAssembly? |
That's potentially quite a good suggestion. There's currently a number of more pressing features and changes to be implemented, but I will take some time, when available, to look into the feasibility and cost/benefit of that work. Thank you for raising this, I'll get back to you when I have an update. |
Bug Report
The JavaScript driver is about 4 times slower than the C# one, but the query takes the same amount on the database side.
It's the fact alone that one is written in C# enough to justify this big increase in execution times?
My code
JavaScript
C#
Timings
JavaScript
C#
My Environment
Javascript Runtime Version: Edge 128.0.2739.67
Driver Version: 5.24.1
Neo4j Version and Edition: 5.23.0 (enterprise)
Operating System: Windows 11
The text was updated successfully, but these errors were encountered: