Skip to content

Commit 526a628

Browse files
committed
50x performance increase on javascript client prepared statement execution on linux!
1 parent 3dc12b7 commit 526a628

File tree

4 files changed

+71
-31
lines changed

4 files changed

+71
-31
lines changed

lib/connection.js

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,12 @@ p.password = function(password) {
7878
this._send(0x70, this.writer.addCString(password));
7979
};
8080

81-
p._send = function(code, writer) {
82-
return this.stream.write(writer.flush(code));
81+
p._send = function(code, more) {
82+
if(more === true) {
83+
this.writer.addHeader(code);
84+
} else {
85+
return this.stream.write(this.writer.flush(code));
86+
}
8387
}
8488

8589
var termBuffer = new Buffer([0x58, 0, 0, 0, 4]);
@@ -92,7 +96,9 @@ p.query = function(text) {
9296
this.stream.write(this.writer.addCString(text).flush(0x51));
9397
};
9498

95-
p.parse = function(query) {
99+
//send parse message
100+
//"more" === true to buffer the message until flush() is called
101+
p.parse = function(query, more) {
96102
//expect something like this:
97103
// { name: 'queryName',
98104
// text: 'select * from blah',
@@ -111,13 +117,13 @@ p.parse = function(query) {
111117
buffer.addInt32(query.types[i]);
112118
}
113119

114-
//0x50 = 'P'
115-
this._send(0x50, buffer);
116-
117-
return this;
120+
var code = 0x50;
121+
this._send(code, more);
118122
};
119123

120-
p.bind = function(config) {
124+
//send bind message
125+
//"more" === true to buffer the message until flush() is called
126+
p.bind = function(config, more) {
121127
//normalize config
122128
config = config || {};
123129
config.portal = config.portal || '';
@@ -141,11 +147,12 @@ p.bind = function(config) {
141147
}
142148
buffer.addInt16(0); //no format codes, use text
143149
//0x42 = 'B'
144-
145-
this._send(0x42, buffer);
150+
this._send(0x42, more);
146151
};
147152

148-
p.execute = function(config) {
153+
//send execute message
154+
//"more" === true to buffer the message until flush() is called
155+
p.execute = function(config, more) {
149156
config = config || {};
150157
config.portal = config.portal || '';
151158
config.rows = config.rows || '';
@@ -154,28 +161,34 @@ p.execute = function(config) {
154161
.addInt32(config.rows);
155162

156163
//0x45 = 'E'
157-
this._send(0x45, buffer);
164+
this._send(0x45, more);
158165
};
159166

160167
var emptyBuffer = Buffer(0);
161168

162169
p.flush = function() {
163170
//0x48 = 'H'
164-
this._send(0x48,this.writer.add(emptyBuffer));
171+
this.writer.add(emptyBuffer)
172+
this._send(0x48);
165173
}
166174

167175
p.sync = function() {
168-
//0x53 = 'S'
169-
this._send(0x53, this.writer.add(emptyBuffer));
176+
//clear out any pending data in the writer
177+
this.writer.flush(0)
178+
179+
this.writer.add(emptyBuffer);
180+
this._send(0x53);
170181
};
171182

172183
p.end = function() {
173184
//0x58 = 'X'
174-
this._send(0x58, this.writer.add(emptyBuffer));
185+
this.writer.add(emptyBuffer);
186+
this._send(0x58);
175187
};
176188

177-
p.describe = function(msg) {
178-
this._send(0x44, this.writer.addCString(msg.type + (msg.name || '')));
189+
p.describe = function(msg, more) {
190+
this.writer.addCString(msg.type + (msg.name || ''));
191+
this._send(0x44, more);
179192
};
180193

181194
//parsing methods

lib/query.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ p.getRows = function(connection) {
106106
connection.execute({
107107
portal: this.name,
108108
rows: this.rows
109-
});
109+
}, true);
110110
connection.flush();
111111
};
112112

@@ -121,7 +121,7 @@ p.prepare = function(connection) {
121121
text: self.text,
122122
name: self.name,
123123
types: self.types
124-
});
124+
}, true);
125125
connection.parsedStatements[this.name] = true;
126126
}
127127

@@ -137,12 +137,12 @@ p.prepare = function(connection) {
137137
portal: self.name,
138138
statement: self.name,
139139
values: self.values
140-
});
140+
}, true);
141141

142142
connection.describe({
143143
type: 'P',
144144
name: self.name || ""
145-
});
145+
}, true);
146146

147147
this.getRows(connection);
148148
};

lib/writer.js

Lines changed: 23 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ var Writer = function(size) {
22
this.size = size || 1024;
33
this.buffer = new Buffer(this.size + 5);
44
this.offset = 5;
5+
this.headerPosition = 0;
56
};
67

78
var p = Writer.prototype;
@@ -70,18 +71,32 @@ p.add = function(otherBuffer) {
7071
}
7172

7273
p.clear = function() {
73-
this.offset=5;
74+
this.offset = 5;
75+
this.headerPosition = 0;
76+
this.lastEnd = 0;
77+
}
78+
79+
//appends a header block to all the written data since the last
80+
//subsequent header or to the beginning if there is only one data block
81+
p.addHeader = function(code, last) {
82+
var origOffset = this.offset;
83+
this.offset = this.headerPosition;
84+
this.buffer[this.offset++] = code;
85+
//length is everything in this packet minus the code
86+
this.addInt32(origOffset - (this.headerPosition+1))
87+
//set next header position
88+
this.headerPosition = origOffset;
89+
//make space for next header
90+
this.offset = origOffset;
91+
if(!last) {
92+
this._ensure(5);
93+
this.offset += 5;
94+
}
7495
}
7596

7697
p.join = function(code) {
7798
if(code) {
78-
var end = this.offset;
79-
this.offset = 0;
80-
this.buffer[this.offset++] = code;
81-
//write the length which is length of entire packet not including
82-
//message type code byte
83-
this.addInt32(end - 1);
84-
this.offset = end;
99+
this.addHeader(code, true);
85100
}
86101
return this.buffer.slice(code ? 0 : 5, this.offset);
87102
}

test/unit/writer-tests.js

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ test("resizing to much larger", function() {
156156
assert.equalBuffers(result, [33, 33, 33, 33, 33, 33, 33, 33, 0])
157157
})
158158

159-
test("header", function() {
159+
test("flush", function() {
160160
test('added as a hex code to a full writer', function() {
161161
var subject = new Writer(2);
162162
var result = subject.addCString("!").flush(0x50)
@@ -175,3 +175,15 @@ test("header", function() {
175175
assert.equalBuffers(result, [0x50, 0, 0, 0, 0x0D, 33, 33, 33, 33, 33, 33, 33, 33, 0]);
176176
})
177177
})
178+
179+
test("header", function() {
180+
test('adding two packets with headers', function() {
181+
var subject = new Writer(10).addCString("!");
182+
subject.addHeader(0x50);
183+
subject.addCString("!!");
184+
subject.addHeader(0x40);
185+
subject.addCString("!");
186+
var result = subject.flush(0x10);
187+
assert.equalBuffers(result, [0x50, 0, 0, 0, 6, 33, 0, 0x40, 0, 0, 0, 7, 33, 33, 0, 0x10, 0, 0, 0, 6, 33, 0 ]);
188+
})
189+
})

0 commit comments

Comments
 (0)