http: server code refactor #6533

Merged
merged 8 commits into from Dec 29, 2016

Projects

None yet

9 participants

@mscdex
Contributor
mscdex commented May 2, 2016 edited
Checklist
  • tests and code linting passes
  • the commit message follows commit guidelines
Affected core subsystem(s)
  • http
  • streams
Description of change

This PR consists of a refactor of http server-related code as well as various cleanups and minor optimizations in the http and writable stream modules.

Here are some benchmark results with these changes:

http/simple.js type=bytes length=4 chunks=0 c=50: ./node: 25895 ./node-http-before: 21780 ........ 18.90%
http/simple.js type=bytes length=4 chunks=0 c=500: ./node: 24965 ./node-http-before: 21956 ....... 13.70%
http/simple.js type=bytes length=4 chunks=1 c=50: ./node: 21823 ./node-http-before: 20029 ......... 8.96%
http/simple.js type=bytes length=4 chunks=1 c=500: ./node: 21403 ./node-http-before: 17624 ....... 21.44%
http/simple.js type=bytes length=4 chunks=4 c=50: ./node: 1197.3 ./node-http-before: 1197.1 ....... 0.01%
http/simple.js type=bytes length=4 chunks=4 c=500: ./node: 11844 ./node-http-before: 11817 ........ 0.22%
http/simple.js type=bytes length=1024 chunks=0 c=50: ./node: 22803 ./node-http-before: 21585 ...... 5.65%
http/simple.js type=bytes length=1024 chunks=0 c=500: ./node: 21938 ./node-http-before: 20275 ..... 8.20%
http/simple.js type=bytes length=1024 chunks=1 c=50: ./node: 18782 ./node-http-before: 17787 ...... 5.59%
http/simple.js type=bytes length=1024 chunks=1 c=500: ./node: 17992 ./node-http-before: 16139 .... 11.48%
http/simple.js type=bytes length=1024 chunks=4 c=50: ./node: 1197.8 ./node-http-before: 1195.8 .... 0.17%
http/simple.js type=bytes length=1024 chunks=4 c=500: ./node: 11656 ./node-http-before: 11675 .... -0.17%
http/simple.js type=bytes length=102400 chunks=0 c=50: ./node: 1487.3 ./node-http-before: 1466.3 .. 1.44%
http/simple.js type=bytes length=102400 chunks=0 c=500: ./node: 1494.2 ./node-http-before: 1470.5 . 1.61%
http/simple.js type=bytes length=102400 chunks=1 c=50: ./node: 1125.4 ./node-http-before: 1132.1 . -0.60%
http/simple.js type=bytes length=102400 chunks=1 c=500: ./node: 1084.6 ./node-http-before: 1079.8 . 0.44%
http/simple.js type=bytes length=102400 chunks=4 c=50: ./node: 4260.3 ./node-http-before: 4279.6 . -0.45%
http/simple.js type=bytes length=102400 chunks=4 c=500: ./node: 4241.2 ./node-http-before: 4148.5 . 2.23%
http/simple.js type=buffer length=4 chunks=0 c=50: ./node: 21961 ./node-http-before: 20022 ........ 9.68%
http/simple.js type=buffer length=4 chunks=0 c=500: ./node: 20901 ./node-http-before: 19318 ....... 8.20%
http/simple.js type=buffer length=4 chunks=1 c=50: ./node: 20613 ./node-http-before: 19061 ........ 8.15%
http/simple.js type=buffer length=4 chunks=1 c=500: ./node: 19639 ./node-http-before: 18314 ....... 7.23%
http/simple.js type=buffer length=4 chunks=4 c=50: ./node: 17262 ./node-http-before: 15158 ....... 13.89%
http/simple.js type=buffer length=4 chunks=4 c=500: ./node: 16812 ./node-http-before: 15758 ....... 6.69%
http/simple.js type=buffer length=1024 chunks=0 c=50: ./node: 21184 ./node-http-before: 20191 ..... 4.92%
http/simple.js type=buffer length=1024 chunks=0 c=500: ./node: 18821 ./node-http-before: 18476 .... 1.87%
http/simple.js type=buffer length=1024 chunks=1 c=50: ./node: 19632 ./node-http-before: 16735 .... 17.31%
http/simple.js type=buffer length=1024 chunks=1 c=500: ./node: 18979 ./node-http-before: 17733 .... 7.02%
http/simple.js type=buffer length=1024 chunks=4 c=50: ./node: 14943 ./node-http-before: 14621 ..... 2.20%
http/simple.js type=buffer length=1024 chunks=4 c=500: ./node: 16062 ./node-http-before: 15061 .... 6.65%
http/simple.js type=buffer length=102400 chunks=0 c=50: ./node: 17115 ./node-http-before: 15099 .. 13.35%
http/simple.js type=buffer length=102400 chunks=0 c=500: ./node: 16807 ./node-http-before: 15763 .. 6.62%
http/simple.js type=buffer length=102400 chunks=1 c=50: ./node: 14429 ./node-http-before: 13821 ... 4.39%
http/simple.js type=buffer length=102400 chunks=1 c=500: ./node: 15486 ./node-http-before: 13636 . 13.57%
http/simple.js type=buffer length=102400 chunks=4 c=50: ./node: 14031 ./node-http-before: 12521 .. 12.06%
http/simple.js type=buffer length=102400 chunks=4 c=500: ./node: 14034 ./node-http-before: 13554 .. 3.54%

Probably the more controversial changes here would be the ones in the writable stream module because of:

  • var -> const changes
    • Thinking about the readable-stream module in particular here, which would see problems with older versions of node (e.g. v0.10), unless these changes were specifically not pulled in there (is this even feasible, despite older node versions going unmaintained at the end of this year?).
  • passing of the stream to write() callbacks as a second argument
    • This may be considered a semver-major change, as it may or may not affect modules that use (directly or indirectly) arguments inside callbacks passed to write()
    • The reason for this particular change is that (AFAICT) it is the only way to keep v8 from having to constantly recompile/reoptimize the write() callback used in OutgoingMessage.prototype.end(), since writable streams do not call their write() callbacks within the context of the stream (e.g. they use cb() instead of cb.call(stream).

/cc @nodejs/http

@mscdex mscdex changed the title from Http server refactor to http server code refactor May 2, 2016
@mscdex mscdex changed the title from http server code refactor to http: server code refactor May 2, 2016
@jasnell
Member
jasnell commented May 2, 2016

First off, thank you for doing this. This module needed some love badly. Glad to see it getting some attention.

The readable-stream changes are certainly just a bit concerning. Let's see what @nodejs/streams has to say.

@mscdex
Contributor
mscdex commented May 29, 2016

/cc @nodejs/collaborators @nodejs/streams Any comments, especially on the controversial changes?

@benjamingr benjamingr commented on an outdated diff May 29, 2016
lib/_http_server.js
- while (incoming.length) {
- var req = incoming.shift();
- req.emit('aborted');
- req.emit('close');
+function onParserExecuteCommon(parser, ret, d) {
+ const socket = parser.socket;
+ if (ret instanceof Error) {
+ debug('parse error');
+ onSocketError.call(socket, ret);
+ } else if (parser.incoming && parser.incoming.upgrade) {
+ // Upgrade or CONNECT
+ const bytesParsed = ret;
+ const req = parser.incoming;
+ debug('SERVER upgrade or connect', req.method);
+
+ if (!d)
@benjamingr
benjamingr May 29, 2016 Member

I'd find it more readable if this was on the same line or with {}s

@benjamingr benjamingr and 2 others commented on an outdated diff May 29, 2016
lib/_stream_writable.js
@@ -175,8 +175,7 @@ function writeAfterEnd(stream, cb) {
// watermarks determine how many objects to keep in the buffer, rather than
// how many bytes or characters.
function validChunk(stream, state, chunk, cb) {
- var valid = true;
- var er = false;
+ var er;
@benjamingr
benjamingr May 29, 2016 Member

nit - I think it would be a nice idea to assign null to it (undefined is better than false though). Also - is let still slower than var?

@mscdex
mscdex May 29, 2016 Contributor

Yes, let is still slower. I'm not sure if v8 5.1 changes things or not.

@ofrobots
ofrobots May 30, 2016 Contributor

Crankshaft doesn't deal well with let inside loops. In this case I don't expect a difference.

@benjamingr benjamingr commented on the diff May 29, 2016
lib/_http_incoming.js
if (this.complete) {
- raw = this.rawTrailers;
+ this.rawTrailers = headers;
@benjamingr
benjamingr May 29, 2016 Member

I'm not sure about this change, why was a separate array needed before? Can we assume this won't cause issues with the array being modified from the outside?

@mscdex
mscdex May 29, 2016 Contributor

I don't know why a separate array was being created in this function. A new array is already created for every parse of an incoming message, so this particular change just holds onto that reference instead of having it go unused and being GC'ed after parsing.

@benjamingr
benjamingr May 29, 2016 Member

Sounds good to me.

@benjamingr benjamingr and 2 others commented on an outdated diff May 29, 2016
lib/_http_common.js
for (var i = 0; i < val.length; i++) {
const ch = val.charCodeAt(i);
- if (ch === 9) continue;
- if (ch <= 31 || ch > 255 || ch === 127) return true;
+ if (ch !== 9 && (ch <= 31 || ch > 255 || ch === 127))
@benjamingr
benjamingr May 29, 2016 Member

Why is this change from continue to return OK? It looks like it changes the meaning of the above code - if it does so intentionally would you mind adding a test case?

@mscdex
mscdex May 29, 2016 edited Contributor

There is no change in behavior here, it's merely consolidating the logic since there is no point in using a continue just to avoid one line of code. If ch === 9, it will still continue iterating, it just happens implicitly instead of explicitly with this change.

@benjamingr
benjamingr May 29, 2016 Member

I don't understand, you're changing a return to a continue, that continue will go and hit the next value in val which will iterate it.

Mind explaining how it will continue iterating explicitly? Is that code around the code that was changed?

@mscdex
mscdex May 29, 2016 Contributor

There is no return being changed here. The only change is removing the continue and moving that (negated) logic into the other if below it.

@ChALkeR
ChALkeR May 29, 2016 edited Member

@benjamingr It's a change from

for (var i = 0; i < len; i++) {
  if (a(i)) continue;
  if (b(i)) return true;
}

to

for (var i = 0; i < len; i++) {
  if (!a(i) && b(i)) return true;
}

There is no actual difference between those representations.

@benjamingr
benjamingr May 30, 2016 Member

Oh, whoops. Definitely fine.

@benjamingr benjamingr and 1 other commented on an outdated diff May 29, 2016
lib/_http_server.js
function socketOnWrap(ev, fn) {
- var res = net.Socket.prototype.on.call(this, ev, fn);
- if (!this.parser) {
- this.on = net.Socket.prototype.on;
+ const res = SocketOn.call(this, ev, fn);
+ if (this.parser === null) {
+ this.on = SocketOn;
@benjamingr
benjamingr May 29, 2016 Member

I wonder if we can toFastProperties on it here and if it would somehow help. Just curios not a nit or problem with the code.

@mscdex
mscdex May 29, 2016 Contributor

I'm not so sure it would really help. Making a "fast object" has noticeable overhead and is really only worthwhile for objects that are going to exist for a very long time (e.g. objects created once during startup).

@benjamingr
Member

I've attempted reading it but I'm not really sure - would you mind underlying the changes I should be looking at and explaining them?

Alternatively, I would split the commits of things like var -> const and naming function expressions to a separate commit since it makes it hard to me to distil the parts that changed logic vs. cosmetic changes. I'm aware that the rest of core might not feel that way. nevermind I see you already did this and I was fooled by GH.

  • 3d6c0b7 LGTM
  • 1e824be I'll have to read again, but would appreciate more detail in the commit message. I read the code and I didn't notice any errors but I don't really understand all of its logic.
  • 131c596 LGTM (nit)
  • 1bab396 left a question, but the code itself looks fine.
  • 08d8a87 LGTM with a test request
  • 37a652c LGTM
@mscdex
Contributor
mscdex commented May 29, 2016

@benjamingr I'm not sure what in particular (in 1e824be) you're looking for in the commit message?

@mcollina mcollina and 1 other commented on an outdated diff May 30, 2016
lib/_stream_writable.js
}
- return valid;
+ return true;
}
@mcollina
mcollina May 30, 2016 Member

There might be a slight benefit in having a single return point. Not sure if it is visibile here or not.

@mcollina
mcollina May 30, 2016 Member

It's very low level and definitely valid for some old version of V8. It is due to how v8 "compiles" this code, basically having a single return statement allow V8 to produce "faster" code.

Not sure if still applies.. @trevnorris can definitely explain it better than I do.

@mcollina mcollina commented on an outdated diff May 30, 2016
lib/_stream_writable.js
}
- return ret;
+ return false;
@mcollina
mcollina May 30, 2016 Member

same here on the single return point

@mcollina mcollina added the stream label May 30, 2016
@mcollina
Member
mcollina commented May 30, 2016 edited

This is amazing work @mscdex! Some comments on your questions:

  • var -> const changes
    • Thinking about the readable-stream module in particular here, which would see problems with older versions of node (e.g. v0.10), unless these changes were specifically not pulled in there (is this even feasible, despite older node versions going unmaintained at the end of this year?).

No problem, readable-stream is already transpiled (from nodejs/readable-stream#186, 2.0.5). Go ahead and use all of the ES6 feature you like. cc @calvinmetcalf.

  • passing of the stream to write() callbacks as a second argument
    • This may be considered a semver-major change, as it may or may not affect modules that use (directly or indirectly) arguments inside callbacks passed to write()
    • The reason for this particular change is that (AFAICT) it is the only way to keep v8 from having to constantly recompile/reoptimize the write() callback used in OutgoingMessage.prototype.end(), since writable streams do not call their write() callbacks within the context of the stream (e.g. they use cb() instead of cb.call(stream).

This is not correct. See the technique I used in https://github.com/nodejs/node/blob/master/lib/_stream_writable.js#L394, in particular https://github.com/nodejs/node/blob/master/lib/_stream_writable.js#L511-L530. Yes, it is really really ugly but it gets the job done. A module that does the same trick is https://github.com/mcollina/reusify. The overhead slightly reduce the benefit, but it's better than an API change.

I would rather prefer to change the interface so that cb is called within the context of the stream. This might involve some more work, I will encourage you to do two PRs, one with the stream change and one with the HTTP one. It's a bit too much to reason about here. It might also affect fs and net differently.

On the other end, I do not see a compatibility problem in either case. I need this feature a gazillion of other places, and I do not see any way this could break as currently it's not set. I do not see a compatibility issue because this is used internally, and currently there is not a public API to run an HTTP server on top of any stream.

@bjouhier bjouhier referenced this pull request May 30, 2016
Closed

http: avoid obscure http parser error on CONNECT. #6886

3 of 4 tasks complete
@mscdex
Contributor
mscdex commented May 30, 2016

@mcollina Well actually CorkedRequest.finish() is another method that continually gets recompiled/reoptimized because it's not a prototype method, but that's a separate issue ;-)

I haven't done any benchmarks yet, but I'm not sure if adding the overhead of cb.call() (vs cb()) is a worthwhile tradeoff just to benefit the http module, since it will slow down all other stream users?

@mcollina
Member

@mcollina Well actually CorkedRequest.finish() is another method that continually gets recompiled/reoptimized because it's not a prototype method, but that's a separate issue ;-)

Not really, if clearBuffer is not called multiple times synchronously, only two of those for each stream should exists. This is 99,999% of the use case (uncork in HTTP is wrappend in process.nextTick), so that should get optimized pretty heavily. If not, then we should have a look.

I haven't done any benchmarks yet, but I'm not sure if adding the overhead of cb.call() (vs cb()) is a worthwhile tradeoff just to benefit the http module, since it will slow down all other stream users?

It's already everywhere in all the EE interface, and for each chunk it is used quite a bit. I think it will not cause a significant decrease. Note that most users do not use the callback on write, but they rely on pipe, which does not pass a callback.

@mscdex
Contributor
mscdex commented May 30, 2016

@mcollina RE: CorkedRequest.finish(), it gets recompiled/reoptimized for every http connection. This is very noticeable when you run the http benchmarks and you have --trace-opt, etc. turned on.

@mcollina
Member

@mcollina RE: CorkedRequest.finish(), it gets recompiled/reoptimized for every http connection. This is very noticeable when you run the http benchmarks and you have --trace-opt, etc. turned on.

Yes! Before #4354 it was reallocated whenever we did _writev.
Any idea to solve the problem and not having to do that gymnastic would help.

Again, I really think we should consider splitting this into 2 PRs, one stream-related and one HTTP related. It will simplify benchmarking/reviewing.

@mscdex
Contributor
mscdex commented Dec 20, 2016 edited

Alright, I've completely redone this PR now.

Things to note:

  • To avoid the constant re-optimization of some anonymous functions, I have opted to instead use fn.bind() which now actually performs well in master/node v7. This means drastic changes to the stream API are no longer necessary. However, I think it's probably best that the @nodejs/streams team not pull in the streams changes from this PR to readable-stream because most users will not be on node v7, so the usage of fn.bind() in there will make things slower for them.

  • When validating http headers/tokens, I've decided to optimize for the common case of character codes <= 255. So there will be a perf decrease for UTF-8 characters whose code is > 255. This is due to the lookup table only being 256 in size, so when access to an undefined index is made, it slows down. I could add a "char > 255" check before looking in the table which does still achieve a net perf increase for the common case, but it's nowhere near as fast as without the extra check.

  • Performance increase is not as large as it was initially, I suspect that was because of perf improvements made since this PR was first submitted. Here are the results I currently get (up to 7%):

    http/simple.js c=50 chunks=0 length=1024 type="buffer" benchmarker="wrk"         5.09 %         *** 2.321680e-15
    http/simple.js c=50 chunks=0 length=1024 type="bytes" benchmarker="wrk"          6.08 %         *** 5.745435e-15
    http/simple.js c=50 chunks=0 length=102400 type="buffer" benchmarker="wrk"       5.12 %         *** 2.096909e-17
    http/simple.js c=50 chunks=0 length=102400 type="bytes" benchmarker="wrk"       -0.35 %             3.260978e-01
    http/simple.js c=50 chunks=0 length=4 type="buffer" benchmarker="wrk"            5.52 %         *** 1.277371e-17
    http/simple.js c=50 chunks=0 length=4 type="bytes" benchmarker="wrk"             6.15 %         *** 2.696716e-17
    http/simple.js c=50 chunks=1 length=1024 type="buffer" benchmarker="wrk"         5.12 %         *** 2.151779e-14
    http/simple.js c=50 chunks=1 length=1024 type="bytes" benchmarker="wrk"          4.39 %         *** 1.425773e-15
    http/simple.js c=50 chunks=1 length=102400 type="buffer" benchmarker="wrk"       4.59 %         *** 2.692188e-15
    http/simple.js c=50 chunks=1 length=102400 type="bytes" benchmarker="wrk"        0.30 %             3.754454e-01
    http/simple.js c=50 chunks=1 length=4 type="buffer" benchmarker="wrk"            5.04 %         *** 7.873866e-14
    http/simple.js c=50 chunks=1 length=4 type="bytes" benchmarker="wrk"             4.85 %         *** 3.014973e-12
    http/simple.js c=50 chunks=4 length=1024 type="buffer" benchmarker="wrk"         3.86 %         *** 4.730619e-12
    http/simple.js c=50 chunks=4 length=1024 type="bytes" benchmarker="wrk"         -0.03 %             7.544566e-01
    http/simple.js c=50 chunks=4 length=102400 type="buffer" benchmarker="wrk"       2.30 %         *** 4.291004e-06
    http/simple.js c=50 chunks=4 length=102400 type="bytes" benchmarker="wrk"        2.61 %          ** 7.671801e-03
    http/simple.js c=50 chunks=4 length=4 type="buffer" benchmarker="wrk"            3.85 %         *** 2.555875e-13
    http/simple.js c=50 chunks=4 length=4 type="bytes" benchmarker="wrk"            -0.02 %             8.485765e-01
    http/simple.js c=500 chunks=0 length=1024 type="buffer" benchmarker="wrk"        4.72 %         *** 5.100754e-12
    http/simple.js c=500 chunks=0 length=1024 type="bytes" benchmarker="wrk"         7.10 %         *** 4.305934e-17
    http/simple.js c=500 chunks=0 length=102400 type="buffer" benchmarker="wrk"      4.67 %         *** 3.232866e-10
    http/simple.js c=500 chunks=0 length=102400 type="bytes" benchmarker="wrk"       1.03 %           * 1.166409e-02
    http/simple.js c=500 chunks=0 length=4 type="buffer" benchmarker="wrk"           5.62 %         *** 9.720317e-13
    http/simple.js c=500 chunks=0 length=4 type="bytes" benchmarker="wrk"            6.67 %         *** 1.426534e-16
    http/simple.js c=500 chunks=1 length=1024 type="buffer" benchmarker="wrk"        4.10 %         *** 4.870958e-12
    http/simple.js c=500 chunks=1 length=1024 type="bytes" benchmarker="wrk"         5.09 %         *** 2.455658e-15
    http/simple.js c=500 chunks=1 length=102400 type="buffer" benchmarker="wrk"      5.10 %         *** 6.170185e-15
    http/simple.js c=500 chunks=1 length=102400 type="bytes" benchmarker="wrk"       0.45 %           * 3.542224e-02
    http/simple.js c=500 chunks=1 length=4 type="buffer" benchmarker="wrk"           4.15 %         *** 4.757659e-14
    http/simple.js c=500 chunks=1 length=4 type="bytes" benchmarker="wrk"            4.85 %         *** 6.287268e-11
    http/simple.js c=500 chunks=4 length=1024 type="buffer" benchmarker="wrk"        5.41 %         *** 9.070252e-15
    http/simple.js c=500 chunks=4 length=1024 type="bytes" benchmarker="wrk"         3.75 %         *** 2.073711e-11
    http/simple.js c=500 chunks=4 length=102400 type="buffer" benchmarker="wrk"      4.87 %         *** 1.669781e-11
    http/simple.js c=500 chunks=4 length=102400 type="bytes" benchmarker="wrk"       1.49 %          ** 9.449434e-03
    http/simple.js c=500 chunks=4 length=4 type="buffer" benchmarker="wrk"           5.67 %         *** 1.159900e-18
    http/simple.js c=500 chunks=4 length=4 type="bytes" benchmarker="wrk"            3.75 %         *** 7.230132e-09
    

CI: https://ci.nodejs.org/job/node-test-pull-request/5493/
EDIT: The one CI failure on Linux is unrelated (timers) and there is an existing issue about that particular test.

@mscdex mscdex removed the in progress label Dec 20, 2016
@mcollina

Can you submit the changes to Streams into a different PR? I do not think it's the right time to merge those, and we should do a more overhaul on them when the next LTS comes out.
At the moment, we do not have the infrastructure to pull in or skip specific commits.

- const finish = () => {
- this.emit('finish');
- };
+ var finish = onFinish.bind(undefined, this);
@mcollina
mcollina Dec 21, 2016 Member

this use of bind is awesome. There might be more areas in which we could improve things.

+ state.onData = socketOnData.bind(undefined, this, socket, parser, state);
+ state.onError = socketOnError.bind(undefined, this, socket, state);
+ state.onEnd = socketOnEnd.bind(undefined, this, socket, parser, state);
+ state.onClose = socketOnClose.bind(undefined, socket, state);
@mcollina
mcollina Dec 21, 2016 Member

we might even bind those functions to socket.

@mscdex
mscdex Dec 21, 2016 Contributor

What do you mean?

@mcollina
mcollina Dec 21, 2016 Member

Forget it, my bad.

@mscdex
mscdex Dec 21, 2016 Contributor

If you were referring to the use of undefined instead of socket, that's because I actually noticed a perf difference when the this parameter was set to anything (including null), so I opted to bind function parameters instead.

@mcollina
mcollina Dec 22, 2016 Member

That's exactly what I imagined. Good work and good finding.

@@ -538,20 +536,21 @@ function endWritable(stream, state, cb) {
function CorkedRequest(state) {
this.next = null;
this.entry = null;
+ this.finish = onCorkedFinish.bind(undefined, this, state);
+}
@mcollina
mcollina Dec 21, 2016 Member

All of this logic is needed because we have a very slow bind. In a year or so, we might be able to remove this whole CorkedRequest  thing. I am more concerned of readable-stream rather than core.

@mscdex
Contributor
mscdex commented Dec 21, 2016

Can you submit the changes to Streams into a different PR? I do not think it's the right time to merge those, and we should do a more overhaul on them when the next LTS comes out.
At the moment, we do not have the infrastructure to pull in or skip specific commits.

If that's the case, why would putting it into a different PR help?

@mcollina
Member
mcollina commented Dec 21, 2016 edited

Can you submit the changes to Streams into a different PR? I do not think it's the right time to merge those, and we should do a more overhaul on them when the next LTS comes out.
At the moment, we do not have the infrastructure to pull in or skip specific commits.

If that's the case, why would putting it into a different PR help?

I'd rather wait some time and not loose any work. Keeping commits around is easy.

@mscdex
Contributor
mscdex commented Dec 21, 2016 edited

@mcollina I'd rather not have core be at the mercy of readable-stream when it comes to making improvements, especially when it comes to performance.

Besides, it seems the readable-stream repo already has a mechanism for replacing bits in the streams code anyway, why not simply add another case that swaps out the binds?

@mscdex
Contributor
mscdex commented Dec 22, 2016

/cc @nodejs/collaborators Any feedback on this new re-re-factor?

@mcollina
Member

@mcollina I'd rather not have core be at the mercy of readable-stream when it comes to making improvements, especially when it comes to performance.

I agree with you. However readable-stream ensure compatibility between the ecosystem and core. It runs from node 0.8 to 7, plus browsers (yes, even IE). So, we need to strike a trade-off. Let's not side-track the whole PR with this discussion, as it will be LONG :/.

Besides, it seems the readable-stream repo already has a mechanism for replacing bits in the streams code anyway, why not simply add another case that swaps out the binds?

Yes, but maintaining new rules is becoming more and more complex. You should put a comment in there, readable-stream: this must be removed or something similar, so we do not forget.
I will defer to @calvinmetcalf if such a rule is ok.

Because bind is so fast now, we can rewrite a lot of the ugly parts of streams to use bind, unwinding some of the optimizations that we did over the years. There are a lot of those, and some of them might be too hard to replace. I think we can do something about CorkedRequest as an example.

- if (ch === 124 || ch === 126)
+ if (!validTokens[val.charCodeAt(1)])
+ return false;
+ if (val.length < 3)
return true;
@mcollina
mcollina Dec 22, 2016 Member

you might want to check if setting a value and having a single return improves things.

@mscdex
mscdex Dec 22, 2016 edited Contributor

I doubt it, but the early returns are what keeps the function length small enough (it avoids the increasing indentation) and allows for more unwinding.

@mcollina
mcollina Dec 22, 2016 Member

Oh, great. Than it's perfect.

@mscdex
Contributor
mscdex commented Dec 22, 2016 edited

However readable-stream ensure compatibility between the ecosystem and core. It runs from node 0.8 to 7, plus browsers (yes, even IE). So, we need to strike a trade-off. Let's not side-track the whole PR with this discussion, as it will be LONG :/.

Ok, but the streams changes aren't a compatibility issue, they're strictly performance-related changes.

lib/_http_server.js
+ // `outgoingData` is an approximate amount of bytes queued through all
+ // inactive responses. If more data than the high watermark is queued - we
+ // need to pause TCP socket/HTTP parser, and wait until the data will be
+ // sent to the client.
@mcollina
mcollina Dec 22, 2016 Member

can you move this comment outside the function? It is long but we still are in the total number of chars to enable inlining, but it is safer for the future.

@mscdex
mscdex Dec 22, 2016 edited Contributor

I think it's probably better to keep it closer to the variable it's referring to (state.outgoingData)?

@mcollina
mcollina Dec 22, 2016 Member

updatedOutgoingData sounds like a possibly hot function which we would like to inline. How about moving it to the definition of state.outgoingData? That's probably the best place.

@mscdex
mscdex Dec 22, 2016 Contributor

Moved.

@mcollina
Member

However readable-stream ensure compatibility between the ecosystem and core. It runs from node 0.8 to 7, plus browsers (yes, even IE). So, we need to strike a trade-off. Let's not side-track the whole PR with this discussion, as it will be LONG :/.

Ok, but the streams changes aren't a compatibility issue, they're strictly performance-related changes.

I consider a compatibility issue something that could drop throughput by 10% or 20%.

@mcollina

LGTM minus nits and @calvinmetcalf checks on the readable-stream build scripts.

@mcollina
Member

@mscdex very solid work. I can confirm a rough 7% increase in hello-world scenarios.

@chyzwar
chyzwar commented Dec 27, 2016

Hi,

I know that it is probably not right place to ask but I will do it anyway.

@mscdex Do you know if it would be possible to extend ServerResponse ClientRequest classes?
Currently it is only possible by hackery on proto (express.js) or by wrapping in another object/proxy.
I am looking for clean way to extend these classes and then use it in request event

@mscdex
Contributor
mscdex commented Dec 27, 2016 edited

@Chyzwar Please open a separate issue in this repo or on the nodejs/help repo.

@mscdex
Contributor
mscdex commented Dec 27, 2016

/cc @nodejs/http Thoughts on this PR?

@indutny

LGTM if CI is green.

@mscdex mscdex referenced this pull request in nodejs/readable-stream Dec 28, 2016
Open

replace bind() #253

@benjamingr
Member

LGTM

@mscdex
Contributor
mscdex commented Dec 29, 2016

@mcollina With nodejs/readable-stream#253, are all of your nits addressed now?

@mcollina
Member

Yes it does. Go ahead and merge this.

mscdex added some commits Dec 18, 2016
@mscdex mscdex http: reuse existing headers array for raw values
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
175ed52
@mscdex mscdex http: misc cleanup and minor optimizations
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
14c76f8
@mscdex mscdex http: refactor server connection handling
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
832271c
@mscdex mscdex http: improve validation performance
The new table-based lookups perform significantly better for the
common cases (checking latin1 characters).

PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
a54972c
@mscdex mscdex lib: avoid recompilation of anonymous functions
Since at least V8 5.4, using function.bind() is now fast enough to
use to avoid recompiling/reoptimizing the same anonymous functions.
These changes especially impact http servers.

PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
b6ea857
@mscdex mscdex http: extract validation functions
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
e8b809a
@mscdex mscdex http: simplify boolean checks
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
af74e72
@mscdex mscdex http: optimize headers iteration
This commit uses instanceof instead of Array.isArray() for faster
type checking and avoids calling Object.keys() when the headers are
stored as a 2D array instead of a plain object.

PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
4d7531d
@mscdex mscdex merged commit 4d7531d into nodejs:master Dec 29, 2016
@mscdex mscdex deleted the mscdex:http-server-refactor branch Dec 29, 2016
@mscdex mscdex referenced this pull request Dec 31, 2016
Merged

http: various performance improvements #10558

3 of 3 tasks complete
@joyeecheung joyeecheung added a commit to joyeecheung/node that referenced this pull request Jan 2, 2017
@mscdex @joyeecheung mscdex + joyeecheung http: reuse existing headers array for raw values
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
6d4f1a2
@joyeecheung joyeecheung added a commit to joyeecheung/node that referenced this pull request Jan 2, 2017
@mscdex @joyeecheung mscdex + joyeecheung http: misc cleanup and minor optimizations
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
f57e4db
@joyeecheung joyeecheung added a commit to joyeecheung/node that referenced this pull request Jan 2, 2017
@mscdex @joyeecheung mscdex + joyeecheung http: refactor server connection handling
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
537991d
@joyeecheung joyeecheung added a commit to joyeecheung/node that referenced this pull request Jan 2, 2017
@mscdex @joyeecheung mscdex + joyeecheung http: improve validation performance
The new table-based lookups perform significantly better for the
common cases (checking latin1 characters).

PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
5145db5
@joyeecheung joyeecheung added a commit to joyeecheung/node that referenced this pull request Jan 2, 2017
@mscdex @joyeecheung mscdex + joyeecheung lib: avoid recompilation of anonymous functions
Since at least V8 5.4, using function.bind() is now fast enough to
use to avoid recompiling/reoptimizing the same anonymous functions.
These changes especially impact http servers.

PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
ed512e3
@joyeecheung joyeecheung added a commit to joyeecheung/node that referenced this pull request Jan 2, 2017
@mscdex @joyeecheung mscdex + joyeecheung http: extract validation functions
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
262cc88
@joyeecheung joyeecheung added a commit to joyeecheung/node that referenced this pull request Jan 2, 2017
@mscdex @joyeecheung mscdex + joyeecheung http: simplify boolean checks
PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
7a065df
@joyeecheung joyeecheung added a commit to joyeecheung/node that referenced this pull request Jan 2, 2017
@mscdex @joyeecheung mscdex + joyeecheung http: optimize headers iteration
This commit uses instanceof instead of Array.isArray() for faster
type checking and avoids calling Object.keys() when the headers are
stored as a 2D array instead of a plain object.

PR-URL: nodejs#6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
58fe774
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: reuse existing headers array for raw values
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1dd684a
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: misc cleanup and minor optimizations
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
50317b9
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: refactor server connection handling
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
5cfafc3
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: improve validation performance
The new table-based lookups perform significantly better for the
common cases (checking latin1 characters).

PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
b9a4bd0
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas lib: avoid recompilation of anonymous functions
Since at least V8 5.4, using function.bind() is now fast enough to
use to avoid recompiling/reoptimizing the same anonymous functions.
These changes especially impact http servers.

PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
6d2b1b3
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: extract validation functions
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
4b7e552
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: simplify boolean checks
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
792142c
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: optimize headers iteration
This commit uses instanceof instead of Array.isArray() for faster
type checking and avoids calling Object.keys() when the headers are
stored as a 2D array instead of a plain object.

PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
a711ee0
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@evanlucas evanlucas 2017-01-04, Version 7.4.0 (Current)
Notable changes:

* buffer:
  - Improve performance of Buffer allocation by ~11% (Brian White) #10443
  - Improve performance of Buffer.from() by ~50% (Brian White) #10443
* events: Improve performance of EventEmitter.once() by ~27% (Brian White) #10445
* http: Improve performance of http server by ~7% (Brian White) #6533
89fa67d
@evanlucas evanlucas referenced this pull request Jan 3, 2017
Merged

v7.4.0 release proposal #10589

@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: reuse existing headers array for raw values
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
42e01d6
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: misc cleanup and minor optimizations
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
8d7b241
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: refactor server connection handling
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1167389
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: improve validation performance
The new table-based lookups perform significantly better for the
common cases (checking latin1 characters).

PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
df41a74
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas lib: avoid recompilation of anonymous functions
Since at least V8 5.4, using function.bind() is now fast enough to
use to avoid recompiling/reoptimizing the same anonymous functions.
These changes especially impact http servers.

PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
a7fdfc0
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: extract validation functions
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
2ad046a
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: simplify boolean checks
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
2f702f2
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@mscdex @evanlucas mscdex + evanlucas http: optimize headers iteration
This commit uses instanceof instead of Array.isArray() for faster
type checking and avoids calling Object.keys() when the headers are
stored as a 2D array instead of a plain object.

PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
56686fb
@evanlucas evanlucas added a commit that referenced this pull request Jan 3, 2017
@evanlucas evanlucas 2017-01-04, Version 7.4.0 (Current)
Notable changes:

* buffer:
  - Improve performance of Buffer allocation by ~11% (Brian White) #10443
  - Improve performance of Buffer.from() by ~50% (Brian White) #10443
* events: Improve performance of EventEmitter.once() by ~27% (Brian White) #10445
* http: Improve performance of http server by ~7% (Brian White) #6533
22e9bbf
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@mscdex @evanlucas mscdex + evanlucas http: reuse existing headers array for raw values
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
b094b49
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@mscdex @evanlucas mscdex + evanlucas http: misc cleanup and minor optimizations
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
1f0fd7b
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@mscdex @evanlucas mscdex + evanlucas http: refactor server connection handling
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
df8b8b2
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@mscdex @evanlucas mscdex + evanlucas http: improve validation performance
The new table-based lookups perform significantly better for the
common cases (checking latin1 characters).

PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
8a2a763
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@mscdex @evanlucas mscdex + evanlucas lib: avoid recompilation of anonymous functions
Since at least V8 5.4, using function.bind() is now fast enough to
use to avoid recompiling/reoptimizing the same anonymous functions.
These changes especially impact http servers.

PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
aed5e27
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@mscdex @evanlucas mscdex + evanlucas http: extract validation functions
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
c8ad127
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@mscdex @evanlucas mscdex + evanlucas http: simplify boolean checks
PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
a760d70
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@mscdex @evanlucas mscdex + evanlucas http: optimize headers iteration
This commit uses instanceof instead of Array.isArray() for faster
type checking and avoids calling Object.keys() when the headers are
stored as a 2D array instead of a plain object.

PR-URL: #6533
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com>
Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com>
32b6bcd
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@evanlucas evanlucas 2017-01-04, Version 7.4.0 (Current)
Notable changes:

* buffer:
  - Improve performance of Buffer allocation by ~11% (Brian White) #10443
  - Improve performance of Buffer.from() by ~50% (Brian White) #10443
* events: Improve performance of EventEmitter.once() by ~27% (Brian White) #10445
* fs: Allow passing Uint8Array to fs methods where Buffers are supported. (Anna Henningsen) #10382
* http: Improve performance of http server by ~7% (Brian White) #6533
* npm: Upgrade to v4.0.5 (Kat Marchán) #10330
5d3dd96
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@evanlucas evanlucas 2017-01-04, Version 7.4.0 (Current)
Notable changes:

* buffer:
  - Improve performance of Buffer allocation by ~11% (Brian White) #10443
  - Improve performance of Buffer.from() by ~50% (Brian White) #10443
* events: Improve performance of EventEmitter.once() by ~27% (Brian White) #10445
* fs: Allow passing Uint8Array to fs methods where Buffers are supported. (Anna Henningsen) #10382
* http: Improve performance of http server by ~7% (Brian White) #6533
* npm: Upgrade to v4.0.5 (Kat Marchán) #10330

PR-URL: #10589
4760abc
@evanlucas evanlucas added a commit that referenced this pull request Jan 4, 2017
@evanlucas evanlucas 2017-01-04, Version 7.4.0 (Current)
Notable changes:

* buffer:
  - Improve performance of Buffer allocation by ~11% (Brian White) #10443
  - Improve performance of Buffer.from() by ~50% (Brian White) #10443
* events: Improve performance of EventEmitter.once() by ~27% (Brian White) #10445
* fs: Allow passing Uint8Array to fs methods where Buffers are supported. (Anna Henningsen) #10382
* http: Improve performance of http server by ~7% (Brian White) #6533
* npm: Upgrade to v4.0.5 (Kat Marchán) #10330

PR-URL: #10589
b8f6c1f
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // ... 255
+];
@cdaringe
cdaringe Jan 12, 2017

do you have any reference mat'l on the choice of int vs bool here? just interested.

@mscdex
mscdex Jan 12, 2017 Contributor

Performance-wise? Not really. At the very least it's more compact. I wouldn't be surprised though if V8 internally treated booleans as SMIs with values of 0 or 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment