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

querystring: reduce memory usage #34179

Closed
wants to merge 1 commit into from

Conversation

sapics
Copy link
Contributor

@sapics sapics commented Jul 3, 2020

This PR will reduce the memory usage when program loads querystring or internal/querystring. (reduce about 8 Byte * (256 - 103) count = 1,224 Byte, for each)
It is also possible to remove isHexTable by replacing if(isHexTable[code]) to if(unhexTable[code]>=0), which reduce 8 * 103 Byte. Currently, I did not replace that for simplicity. If you feel better to replace it, please notice me.

To avoid number->boolean casting, I did not do following replacement as #34179 (comment)
I also change the conditional expression as

- if (isHexTable[code] === 1) {
+ if (isHexTable[code]) {

because I feel that the name of variable isHexTable looks boolean name.

Checklist
  • make -j4 test (UNIX), or vcbuild test (Windows) passes
  • commit message follows commit guidelines

@nodejs-github-bot nodejs-github-bot added the querystring Issues and PRs related to the built-in querystring module. label Jul 3, 2020
@benjamingr
Copy link
Member

Hey, thanks for your contribution 🙏

What's the impact on performance?

(you can run the querystring benchmark :])

@sapics
Copy link
Contributor Author

sapics commented Jul 4, 2020

Hello, thanks for your suggestion 🙏

 querystring/querystring-parse.js n=1000000 type='altspaces'                                                                                   **     -5.77 %      ±4.13% ±5.55% ±7.36%
 querystring/querystring-parse.js n=1000000 type='encodefake'                                                                                 ***      7.28 %      ±1.14% ±1.52% ±1.98%
 querystring/querystring-parse.js n=1000000 type='encodelast'                                                                                          0.40 %      ±0.67% ±0.89% ±1.17%
 querystring/querystring-parse.js n=1000000 type='encodemany'                                                                                          0.56 %      ±0.57% ±0.76% ±0.99%
 querystring/querystring-parse.js n=1000000 type='manyblankpairs'                                                                                     -0.06 %      ±0.68% ±0.90% ±1.18%
 querystring/querystring-parse.js n=1000000 type='manypairs'                                                                                    *     -1.09 %      ±0.90% ±1.20% ±1.56%
 querystring/querystring-parse.js n=1000000 type='multicharsep'                                                                                        0.42 %      ±1.63% ±2.18% ±2.84%
 querystring/querystring-parse.js n=1000000 type='multivalue'                                                                                         -0.43 %      ±0.85% ±1.14% ±1.48%
 querystring/querystring-parse.js n=1000000 type='multivaluemany'                                                                                     -0.50 %      ±1.22% ±1.62% ±2.12%
 querystring/querystring-parse.js n=1000000 type='noencode'                                                                                            0.31 %      ±0.96% ±1.28% ±1.67%
 querystring/querystring-stringify.js n=1000000 type='array'                                                                                          -1.62 %      ±2.49% ±3.33% ±4.38%
 querystring/querystring-stringify.js n=1000000 type='encodelast'                                                                                     -0.17 %      ±0.68% ±0.90% ±1.17%
 querystring/querystring-stringify.js n=1000000 type='encodemany'                                                                                     -0.35 %      ±1.29% ±1.72% ±2.24%
 querystring/querystring-stringify.js n=1000000 type='multiprimitives'                                                                                -0.28 %      ±0.97% ±1.29% ±1.68%
 querystring/querystring-stringify.js n=1000000 type='noencode'                                                                                       -1.07 %      ±2.98% ±4.00% ±5.28%
 querystring/querystring-unescapebuffer.js n=10000000 input='%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%30%31%32%33%34%35%36%37'                 0.76 %      ±1.38% ±1.86% ±2.45%
 querystring/querystring-unescapebuffer.js n=10000000 input='there is nothing to unescape here'                                                        0.36 %      ±0.64% ±0.85% ±1.11%
 querystring/querystring-unescapebuffer.js n=10000000 input='there%20are%20several%20spaces%20that%20need%20to%20be%20unescaped'                       0.26 %      ±0.52% ±0.69% ±0.90%
 querystring/querystring-unescapebuffer.js n=10000000 input='there%2Qare%0-fake%escaped values in%%%%this%9Hstring'                           ***     -1.52 %      ±0.38% ±0.51% ±0.66%

From the benchmark in linux, it looks almost same performance 😄
This commit is intended to reduce some memory usage at initialization, thus, it might be small impact to performance ;)
Do you feel something that could have a negative impact on performance, in my commit?

@bnoordhuis
Copy link
Member

Do you feel something that could have a negative impact on performance, in my commit?

If I read your changes right, it's now doing out-of-bounds array element reads and V8 used to penalize those. Maybe it no longer does or maybe it's insignificant here.

@benjamingr
Copy link
Member

Maybe it no longer does or maybe it's insignificant here.

It looks pretty significant so I am -0 on landing this.

Interesting change + results :]

@sapics
Copy link
Contributor Author

sapics commented Jul 4, 2020

@bnoordhuis

If I read your changes right, it's now doing out-of-bounds array element reads

Yes, I did. And I used a lot in my personal coding :)

V8 used to penalize those.

Thanks for letting me know! I did not know that!

@benjamingr

It looks pretty significant so I am -0 on landing this.
Interesting change + results :]

I agree with you. I do not want to land unrecommended one, too :)
So, I close this pr.

Again, thank you both for advice!

@sapics sapics closed this Jul 4, 2020
@addaleax
Copy link
Member

addaleax commented Jul 4, 2020

@sapics One idea that might be worth exploring here is using an Int8Array for these tables instead. I would assume that should reduce memory overhead by a factor of 4 (32-bit integer → 8-bit integer), without affecting performance negatively.

@sapics
Copy link
Contributor Author

sapics commented Jul 5, 2020

Thanks @addaleax for your suggestion!

The suggestion looks much better! I fixed my commit, force-push it and reopen this PR.

Now, total memory usage would decrease (64 - 8) * (256 * 2 + 128 * 3) / 8 = 6272 Bytes (about 6KB!).
(I thought Number is 64 bits in js, 32 bits by V8 optimization? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)

Furthermore, we can get better benchmark ;)

                                                                                                                                        confidence improvement accuracy (*)    (**)   (***)
 querystring\\querystring-parse.js n=1000000 type='altspaces'                                                                                           0.22 %      ±1.64% ±2.19% ±2.86%
 querystring\\querystring-parse.js n=1000000 type='encodefake'                                                                                 ***      4.00 %      ±1.11% ±1.48% ±1.92%
 querystring\\querystring-parse.js n=1000000 type='encodelast'                                                                                 ***      2.22 %      ±1.14% ±1.52% ±1.99%
 querystring\\querystring-parse.js n=1000000 type='encodemany'                                                                                          0.27 %      ±0.94% ±1.25% ±1.63%
 querystring\\querystring-parse.js n=1000000 type='manyblankpairs'                                                                                     -0.08 %      ±0.30% ±0.40% ±0.52%
 querystring\\querystring-parse.js n=1000000 type='manypairs'                                                                                          -0.56 %      ±1.18% ±1.57% ±2.05%
 querystring\\querystring-parse.js n=1000000 type='multicharsep'                                                                                **     -2.18 %      ±1.33% ±1.78% ±2.33%
 querystring\\querystring-parse.js n=1000000 type='multivalue'                                                                                          0.22 %      ±1.17% ±1.55% ±2.03%
 querystring\\querystring-parse.js n=1000000 type='multivaluemany'                                                                              **      1.46 %      ±0.87% ±1.16% ±1.51%
 querystring\\querystring-parse.js n=1000000 type='noencode'                                                                                            0.39 %      ±1.03% ±1.37% ±1.78%
 querystring\\querystring-stringify.js n=1000000 type='array'                                                                                   **      3.65 %      ±2.69% ±3.59% ±4.70%
 querystring\\querystring-stringify.js n=1000000 type='encodelast'                                                                               *      1.51 %      ±1.47% ±1.97% ±2.59%
 querystring\\querystring-stringify.js n=1000000 type='encodemany'                                                                                      0.68 %      ±0.99% ±1.32% ±1.72%
 querystring\\querystring-stringify.js n=1000000 type='multiprimitives'                                                                                -2.49 %      ±4.81% ±6.47% ±8.57%
 querystring\\querystring-stringify.js n=1000000 type='noencode'                                                                                        0.69 %      ±1.79% ±2.38% ±3.11%
 querystring\\querystring-unescapebuffer.js n=10000000 input='%20%21%22%23%24%25%26%27%28%29%2A%2B%2C%2D%2E%2F%30%31%32%33%34%35%36%37'        ***      4.58 %      ±0.79% ±1.06% ±1.40%
 querystring\\querystring-unescapebuffer.js n=10000000 input='there is nothing to unescape here'                                               ***     -1.35 %      ±0.75% ±1.00% ±1.31%
 querystring\\querystring-unescapebuffer.js n=10000000 input='there%20are%20several%20spaces%20that%20need%20to%20be%20unescaped'              ***      5.65 %      ±0.65% ±0.86% ±1.12%
 querystring\\querystring-unescapebuffer.js n=10000000 input='there%2Qare%0-fake%escaped values in%%%%this%9Hstring'                             *      0.33 %      ±0.33% ±0.44% ±0.58%

@sapics sapics reopened this Jul 5, 2020
@sapics sapics force-pushed the querystring/reduce-memory-usage branch from fa58d14 to 5bd319e Compare July 5, 2020 02:57
@addaleax
Copy link
Member

addaleax commented Jul 5, 2020

(I thought Number is 64 bits in js, 32 bits by V8 optimization? https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number)

Yes, “small integers” (signed integers up to 31 bits in length, aka “smi”s) take up only a single 32-bit value, and V8 does have a special array representation for smi arrays, as far as I remember.

lib/querystring.js Outdated Show resolved Hide resolved
@nodejs-github-bot
Copy link
Collaborator

nodejs-github-bot commented Jul 5, 2020

@sapics sapics force-pushed the querystring/reduce-memory-usage branch from 5bd319e to 689a4cd Compare July 5, 2020 14:24
@aduh95 aduh95 added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. commit-queue Add this label to land a pull request using GitHub Actions. request-ci Add this label to start a Jenkins CI on a PR. labels Nov 8, 2020
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Nov 8, 2020
@nodejs-github-bot
Copy link
Collaborator

@github-actions github-actions bot added commit-queue-failed An error occurred while landing this pull request using GitHub Actions. and removed commit-queue Add this label to land a pull request using GitHub Actions. labels Nov 8, 2020
@github-actions
Copy link
Contributor

github-actions bot commented Nov 8, 2020

Commit Queue failed
- Loading data for nodejs/node/pull/34179
✔  Done loading data for nodejs/node/pull/34179
----------------------------------- PR info ------------------------------------
Title      querystring: reduce memory usage (#34179)
   ⚠  Could not retrieve the email or name of the PR author's from user's GitHub profile!
Branch     sapics:querystring/reduce-memory-usage -> nodejs:master
Labels     author ready, querystring
Commits    1
 - querystring: reduce memory usage by Int8Array
Committers 1
 - sapics 
PR-URL: https://github.com/nodejs/node/pull/34179
Reviewed-By: Anna Henningsen 
Reviewed-By: Denys Otrishko 
------------------------------ Generated metadata ------------------------------
PR-URL: https://github.com/nodejs/node/pull/34179
Reviewed-By: Anna Henningsen 
Reviewed-By: Denys Otrishko 
--------------------------------------------------------------------------------
   ✖  Last GitHub CI failed
   ℹ  Last Full PR CI on 2020-11-08T12:24:00Z: https://ci.nodejs.org/job/node-test-pull-request/34198/
   ℹ  Last Benchmark CI on 2020-07-05T13:02:13Z: https://ci.nodejs.org/view/Node.js%20benchmark/job/benchmark-node-micro-benchmarks/638/
- Querying data for job/node-test-pull-request/34198/
✔  Build data downloaded
- Querying failures of job/node-test-commit/42045/
✔  Data downloaded
   ✖  4 failure(s) on the last Jenkins CI run
   ℹ  This PR was created on Fri, 03 Jul 2020 06:36:29 GMT
   ✔  Approvals: 2
   ✔  - Anna Henningsen (@addaleax): https://github.com/nodejs/node/pull/34179#pullrequestreview-442670690
   ✔  - Denys Otrishko (@lundibundi): https://github.com/nodejs/node/pull/34179#pullrequestreview-442675347
--------------------------------------------------------------------------------
   ✔  Aborted `git node land` session in /home/runner/work/node/node/.ncu

Commit Queue action: https://github.com/nodejs/node/actions/runs/352514303

@nodejs-github-bot
Copy link
Collaborator

@aduh95
Copy link
Contributor

aduh95 commented Nov 9, 2020

@sapics Can you fix the linter issue please? You need to declare const { Int8Array } = primordials;.

@aduh95 aduh95 added stalled Issues and PRs that are stalled. and removed author ready PRs that have at least one approval, no pending requests for changes, and a CI started. labels Nov 9, 2020
@github-actions
Copy link
Contributor

github-actions bot commented Nov 9, 2020

This issue/PR was marked as stalled, it will be automatically closed in 30 days. If it should remain open, please leave a comment explaining why it should remain open.

@sapics sapics force-pushed the querystring/reduce-memory-usage branch from 689a4cd to c1bc95b Compare November 10, 2020 05:15
@sapics
Copy link
Contributor Author

sapics commented Nov 10, 2020

@aduh95 Thank you for noticing linter issue! I fix it and push the commit.

@aduh95 aduh95 added author ready PRs that have at least one approval, no pending requests for changes, and a CI started. request-ci Add this label to start a Jenkins CI on a PR. and removed commit-queue-failed An error occurred while landing this pull request using GitHub Actions. stalled Issues and PRs that are stalled. labels Nov 10, 2020
@github-actions github-actions bot removed the request-ci Add this label to start a Jenkins CI on a PR. label Nov 10, 2020
@nodejs-github-bot

This comment has been minimized.

@nodejs-github-bot
Copy link
Collaborator

@aduh95 aduh95 added the commit-queue Add this label to land a pull request using GitHub Actions. label Nov 10, 2020
@github-actions github-actions bot removed the commit-queue Add this label to land a pull request using GitHub Actions. label Nov 10, 2020
@github-actions
Copy link
Contributor

Landed in 0dee498...00b5ee6

@github-actions github-actions bot closed this Nov 10, 2020
nodejs-github-bot pushed a commit that referenced this pull request Nov 10, 2020
PR-URL: #34179
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
@sapics sapics deleted the querystring/reduce-memory-usage branch November 11, 2020 12:18
codebytere pushed a commit that referenced this pull request Nov 22, 2020
PR-URL: #34179
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
@codebytere codebytere mentioned this pull request Nov 22, 2020
BethGriggs pushed a commit that referenced this pull request Dec 9, 2020
PR-URL: #34179
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
BethGriggs pushed a commit that referenced this pull request Dec 10, 2020
PR-URL: #34179
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
@BethGriggs BethGriggs mentioned this pull request Dec 10, 2020
BethGriggs pushed a commit that referenced this pull request Dec 15, 2020
PR-URL: #34179
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Denys Otrishko <shishugi@gmail.com>
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author ready PRs that have at least one approval, no pending requests for changes, and a CI started. querystring Issues and PRs related to the built-in querystring module.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants