Skip to content
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

freelist: Performance, replace shift() with pop() #2174

Closed
wants to merge 1 commit into from
Closed

freelist: Performance, replace shift() with pop() #2174

wants to merge 1 commit into from

Conversation

subzey
Copy link
Contributor

@subzey subzey commented Jul 14, 2015

Array#pop() is known to be faster than Array#shift().
In this case there's no difference from which side of the "pool" array
the object is retrieved.

@thefourtheye
Copy link
Contributor

Normally when we talk about performance, we create a benchmark suite to demonstrate the gain. Read more about it here https://github.com/nodejs/io.js/tree/master/benchmark

@mscdex
Copy link
Contributor

mscdex commented Jul 14, 2015

I agree with @thefourtheye, it would also be good to see numbers from said benchmark, especially on the master and next branches (and maybe even next+1 if it's working yet).

@Trott
Copy link
Member

Trott commented Jul 14, 2015

ref: #569

@trevnorris
Copy link
Contributor

It will be difficult to test this directly since it's an internal, and a micro benchmark between the two operations would be bogus. How could it be exposed for testing?

@thefourtheye
Copy link
Contributor

@trevnorris We can use --expose-internals flag introduced in #848, right?

@trevnorris
Copy link
Contributor

@thefourtheye Ah yes. Completely forgot about that one. Thanks for the reminder.

@subzey
Copy link
Contributor Author

subzey commented Jul 14, 2015

Thanks for your patience. Here's a benchmark commit (I hope, I did it right).
Before was about 1 200 000 to 1 500 000, after is about 3 400 000 on my win7 machine.

@trevnorris
Copy link
Contributor

@subzey If you can post the code in a gist I can help you write up a benchmark if you need it.

@subzey
Copy link
Contributor Author

subzey commented Jul 14, 2015

@trevnorris Does 3531e82 look good?

@trevnorris
Copy link
Contributor

@subzey Other than some style nits (spacing 'n stuff) it looks good.

@thefourtheye
Copy link
Contributor

@subzey The commit log should follow the guidelines listed here. Please check and update the commits.

@trevnorris
Copy link
Contributor

if it's an issue can be easily enough taken care of before we land it. just keep the reference for future contributions. ;)

@mscdex
Copy link
Contributor

mscdex commented Jul 14, 2015

@subzey Which branch did you test on to get those numbers?

@subzey
Copy link
Contributor Author

subzey commented Jul 14, 2015

@mscdex, Latest release.
First I ran the code requiring freelist builtin into the executable, then ../../lib/internal/freelist from this pr branch.

@subzey
Copy link
Contributor Author

subzey commented Jul 14, 2015

Looks like this microoptimization is useless now (#2176), feel free to reject this PR.

@thefourtheye
Copy link
Contributor

@subzey Don't worry about it. Its deprecated for the users. It is still used internally by http module.

@brendanashworth
Copy link
Contributor

@subzey could you update your PR with test modifications cause of fef87fe?

@subzey
Copy link
Contributor Author

subzey commented Jul 28, 2015

@brendanashworth I'm sorry, should I just merge master to this PR and run tests before pushing, or something else?

@Fishrock123
Copy link
Contributor

@subzey He's asking if you could rebase against master and force-push your changes up here. :)

@Fishrock123 Fishrock123 added the benchmark Issues and PRs related to the benchmark subsystem. label Jul 28, 2015
@subzey
Copy link
Contributor Author

subzey commented Aug 3, 2015

Force-pushed a rebased commit into this PR; fixed eslint whitespace errors

@thefourtheye
Copy link
Contributor

@subzey Can you share some performance numbers, with master and with this change, if you don't mind?

@subzey
Copy link
Contributor Author

subzey commented Aug 3, 2015

@thefourtheye, Sure.
Master: 1718948 (avg of 3 runs)
Branch: 3518114 (avg of 3 runs)

@thefourtheye
Copy link
Contributor

@subzey You might want to change the corresponding test as well, test/parallel/test-freelist.js. This change will break the test.

@subzey
Copy link
Contributor Author

subzey commented Aug 4, 2015

@thefourtheye, you're right. I'm terribly sorry for breaking the test, I'll fix it asap



// First, alloc N items
for (i = 0; i < n; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This benchmark doesn't really handle the common case (and exits way too fast). Do you think you could change it so it allocates / frees / allocates in blocks of say 500, all the way up to n? We try to have benchmarks take about 5-10 seconds to execute so numbers don't jump around as much.

@jasnell
Copy link
Member

jasnell commented Nov 16, 2015

@subzey ... is this still something you'd like to pursue?

@subzey
Copy link
Contributor Author

subzey commented Jan 25, 2016

Is there any info I can provide?

@ofrobots
Copy link
Contributor

@subzey Thanks for your patience. The proposed change LGTM. I left some comments with minor nits.

The commit log messages should to follow these guidelines here. We can take care of those when landing if you're unsure.

'use strict';

var common = require('../common.js');
var FreeList = require('../../lib/internal/freelist').FreeList;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be require('internal/freelist') with a note at the top that --expose-internals is needed to run the benchmark. Until benchmarks get special "Flags" code comments that get parsed like tests have, flags will need to be explicitly specified on the command-line.

@mscdex
Copy link
Contributor

mscdex commented Jan 25, 2016

A few nits but otherwise LGTM

for (i = 0; i < n; i++){
// Return all the N to the pool
for (j = 0; j < poolSize; j++) {
list.free(used[i]);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/used[i]/used[j]/

@subzey
Copy link
Contributor Author

subzey commented Jan 26, 2016

@ofrobots, @mscdex. The nits were fixed, I've squashed all the changes into 1 commit and rebased it on top of master (as I was asked previously). And also tried to make a perfect commit message.

Please take a look.

This can also be changed to simply this.constructor(); for an additional speed increase since http is the only module that uses FreeList and http just passes in a factory function with no parameters as its "constructor."

A...actually, I'd prefer to do it in a separate branch. :)

@ofrobots
Copy link
Contributor

bench.start();

for (i = 0; i < n; i++){
// Return all the N to the pool
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/N/items/

Array#pop() is known to be faster than Array#shift().
To be exact, it's O(1) vs. O(n). In this case there's no difference
from which side of the "pool" array the object is retrieved,
so .pop() should be preferred.
@subzey
Copy link
Contributor Author

subzey commented Jan 27, 2016

// Return all the N to the pool
s/N/items/

Fixed

@jasnell jasnell added lts-watch-v4.x and removed stalled Issues and PRs that are stalled. labels Jan 27, 2016
@ChALkeR ChALkeR added the performance Issues and PRs related to the performance of Node.js. label Feb 16, 2016
@ofrobots
Copy link
Contributor

@jasnell
Copy link
Member

jasnell commented Mar 2, 2016

LGTM

@ofrobots
Copy link
Contributor

ofrobots commented Mar 2, 2016

LGTM. Landed as c647e87.

ofrobots pushed a commit that referenced this pull request Mar 2, 2016
Array#pop() is known to be faster than Array#shift().
To be exact, it's O(1) vs. O(n). In this case there's no difference
from which side of the "pool" array the object is retrieved,
so .pop() should be preferred.

PR-URL: #2174
Reviewed-By: mscdex - Brian White <mscdex@mscdex.net>
Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
Reviewed-By: ofrobots - Ali Ijaz Sheikh <ofrobots@google.com>
@ofrobots ofrobots closed this Mar 2, 2016
Fishrock123 pushed a commit that referenced this pull request Mar 2, 2016
Array#pop() is known to be faster than Array#shift().
To be exact, it's O(1) vs. O(n). In this case there's no difference
from which side of the "pool" array the object is retrieved,
so .pop() should be preferred.

PR-URL: #2174
Reviewed-By: mscdex - Brian White <mscdex@mscdex.net>
Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
Reviewed-By: ofrobots - Ali Ijaz Sheikh <ofrobots@google.com>
MylesBorins pushed a commit that referenced this pull request Mar 17, 2016
Array#pop() is known to be faster than Array#shift().
To be exact, it's O(1) vs. O(n). In this case there's no difference
from which side of the "pool" array the object is retrieved,
so .pop() should be preferred.

PR-URL: #2174
Reviewed-By: mscdex - Brian White <mscdex@mscdex.net>
Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
Reviewed-By: ofrobots - Ali Ijaz Sheikh <ofrobots@google.com>
MylesBorins pushed a commit that referenced this pull request Mar 21, 2016
Array#pop() is known to be faster than Array#shift().
To be exact, it's O(1) vs. O(n). In this case there's no difference
from which side of the "pool" array the object is retrieved,
so .pop() should be preferred.

PR-URL: #2174
Reviewed-By: mscdex - Brian White <mscdex@mscdex.net>
Reviewed-By: jasnell - James M Snell <jasnell@gmail.com>
Reviewed-By: ofrobots - Ali Ijaz Sheikh <ofrobots@google.com>
@subzey subzey deleted the feature/freelist-performance branch July 21, 2016 15:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
benchmark Issues and PRs related to the benchmark subsystem. performance Issues and PRs related to the performance of Node.js.
Projects
None yet
Development

Successfully merging this pull request may close these issues.