Skip to content

Commit 2d1e016

Browse files
authored
Improve performance for packstream in browser. (#809)
The buffer and utf-8 encoding implementation in browser was using the heap and `text-encoding-utf-8` library respectively. This process was really slower than in nodejs. For example, a string with 85000 length was taking 180 seconds to serialize in the browser, the same string takes milliseconds to be serialised in nodejs. This performance issue was resolved by using the libraries `buffer` and `string_decoder`, libraries which is already available in nodejs, also in browser. This substitution bring the serialisation of the 85000 length string to take only 350 ms when it's done in browser. The `text-encoding-utf-8` was removed from the project dependency in the process.
1 parent 259d0b9 commit 2d1e016

File tree

18 files changed

+192
-217
lines changed

18 files changed

+192
-217
lines changed

packages/bolt-connection/package-lock.json

+34-5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/bolt-connection/package.json

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@
3838
"typescript": "^4.4.4"
3939
},
4040
"dependencies": {
41+
"buffer": "^6.0.3",
4142
"neo4j-driver-core": "^4.4.0-dev",
42-
"text-encoding-utf-8": "^1.0.2"
43+
"string_decoder": "^1.3.0"
4344
}
4445
}

packages/bolt-connection/src/channel/browser/browser-buf.js

-76
This file was deleted.

packages/bolt-connection/src/channel/browser/browser-channel.js

+4-4
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* limitations under the License.
1818
*/
1919

20-
import HeapBuffer from './browser-buf'
20+
import ChannelBuffer from '../channel-buf'
2121
import { newError, internal } from 'neo4j-driver-core'
2222

2323
const {
@@ -83,7 +83,7 @@ export default class WebSocketChannel {
8383
}
8484
this._ws.onmessage = event => {
8585
if (self.onmessage) {
86-
const b = new HeapBuffer(event.data)
86+
const b = new ChannelBuffer(event.data)
8787
self.onmessage(b)
8888
}
8989
}
@@ -130,14 +130,14 @@ export default class WebSocketChannel {
130130

131131
/**
132132
* Write the passed in buffer to connection
133-
* @param {HeapBuffer} buffer - Buffer to write
133+
* @param {ChannelBuffer} buffer - Buffer to write
134134
*/
135135
write (buffer) {
136136
// If there is a pending queue, push this on that queue. This means
137137
// we are not yet connected, so we queue things locally.
138138
if (this._pending !== null) {
139139
this._pending.push(buffer)
140-
} else if (buffer instanceof HeapBuffer) {
140+
} else if (buffer instanceof ChannelBuffer) {
141141
try {
142142
this._ws.send(buffer._buffer)
143143
} catch (error) {

packages/bolt-connection/src/channel/browser/browser-utf8.js

-49
This file was deleted.

packages/bolt-connection/src/channel/browser/index.js

-5
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@
1717
* limitations under the License.
1818
*/
1919

20-
import HeapBuffer from './browser-buf'
2120
import WebSocketChannel from './browser-channel'
2221
import BrowserHosNameResolver from './browser-host-name-resolver'
23-
import utf8Codec from './browser-utf8'
2422

2523
/*
2624
@@ -32,8 +30,5 @@ Such imports are replaced at build time with `browser/index.js` when building a
3230
NOTE: exports in this module should have exactly the same names/structure as exports in `node/index.js`.
3331
3432
*/
35-
36-
export const alloc = arg => new HeapBuffer(arg)
3733
export const Channel = WebSocketChannel
3834
export const HostNameResolver = BrowserHosNameResolver
39-
export const utf8 = utf8Codec

packages/bolt-connection/src/channel/node/node-buf.js renamed to packages/bolt-connection/src/channel/channel-buf.js

+22-11
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,12 @@
1717
* limitations under the License.
1818
*/
1919

20-
import node from 'buffer'
21-
import BaseBuffer from '../../buf'
20+
import buffer from 'buffer'
21+
import BaseBuffer from '../buf'
2222

23-
export default class NodeBuffer extends BaseBuffer {
23+
export default class ChannelBuffer extends BaseBuffer {
2424
constructor (arg) {
25-
const buffer = newNodeJSBuffer(arg)
25+
const buffer = newChannelJSBuffer(arg)
2626
super(buffer.length)
2727
this._buffer = buffer
2828
}
@@ -52,7 +52,7 @@ export default class NodeBuffer extends BaseBuffer {
5252
}
5353

5454
putBytes (position, val) {
55-
if (val instanceof NodeBuffer) {
55+
if (val instanceof ChannelBuffer) {
5656
const bytesToCopy = Math.min(
5757
val.length - val.position,
5858
this.length - position
@@ -70,22 +70,33 @@ export default class NodeBuffer extends BaseBuffer {
7070
}
7171

7272
getSlice (start, length) {
73-
return new NodeBuffer(this._buffer.slice(start, start + length))
73+
return new ChannelBuffer(this._buffer.slice(start, start + length))
7474
}
7575
}
7676

77-
function newNodeJSBuffer (arg) {
78-
if (arg instanceof node.Buffer) {
77+
/**
78+
* Allocate a buffer
79+
*
80+
* @param {number} size The buffer sizzer
81+
* @returns {BaseBuffer} The buffer
82+
*/
83+
export function alloc (size) {
84+
return new ChannelBuffer(size)
85+
}
86+
87+
88+
function newChannelJSBuffer (arg) {
89+
if (arg instanceof buffer.Buffer) {
7990
return arg
8091
} else if (
8192
typeof arg === 'number' &&
82-
typeof node.Buffer.alloc === 'function'
93+
typeof buffer.Buffer.alloc === 'function'
8394
) {
8495
// use static factory function present in newer NodeJS versions to allocate new buffer with specified size
85-
return node.Buffer.alloc(arg)
96+
return buffer.Buffer.alloc(arg)
8697
} else {
8798
// fallback to the old, potentially deprecated constructor
8899
// eslint-disable-next-line node/no-deprecated-api
89-
return new node.Buffer(arg)
100+
return new buffer.Buffer(arg)
90101
}
91102
}

packages/bolt-connection/src/channel/chunking.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
import BaseBuffer from '../buf/base-buf'
21-
import { alloc } from './node'
21+
import { alloc } from './channel-buf'
2222
import CombinedBuffer from './combined-buf'
2323

2424
const _CHUNK_HEADER_SIZE = 2

packages/bolt-connection/src/channel/combined-buf.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
*/
1919

2020
import { BaseBuffer } from '../buf'
21-
import { alloc } from './node'
21+
import { alloc } from './channel-buf'
2222

2323
/**
2424
* Buffer that combines multiple buffers, exposing them as one single buffer.

packages/bolt-connection/src/channel/index.js

+3-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
import ChannelConfig from './channel-config'
2-
31
/**
42
* Copyright (c) "Neo4j"
53
* Neo4j Sweden AB [http://neo4j.com]
@@ -18,6 +16,9 @@ import ChannelConfig from './channel-config'
1816
* See the License for the specific language governing permissions and
1917
* limitations under the License.
2018
*/
19+
2120
export * from './node'
2221
export * from './chunking'
2322
export { default as ChannelConfig } from './channel-config'
23+
export { alloc } from './channel-buf'
24+
export { default as utf8 } from './utf8'

packages/bolt-connection/src/channel/node/index.js

+1-4
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,8 @@
1717
* limitations under the License.
1818
*/
1919

20-
import NodeBuffer from './node-buf'
2120
import NodeChannel from './node-channel'
2221
import NodeHostNameResolver from './node-host-name-resolver'
23-
import utf8Codec from './node-utf8'
2422

2523
/*
2624
@@ -33,7 +31,6 @@ NOTE: exports in this module should have exactly the same names/structure as exp
3331
3432
*/
3533

36-
export const alloc = arg => new NodeBuffer(arg)
3734
export const Channel = NodeChannel
3835
export const HostNameResolver = NodeHostNameResolver
39-
export const utf8 = utf8Codec
36+

0 commit comments

Comments
 (0)