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

perf: reduce if statement for NaN (micro-optimization) #697

Merged
merged 6 commits into from
Mar 18, 2024

Conversation

cesco69
Copy link
Contributor

@cesco69 cesco69 commented Mar 13, 2024

reduce if statement for NaN

Checklist

Signed-off-by: francesco <francesco.bagnoli.69@gmail.com>
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

Copy link
Member

@ivan-tymoshenko ivan-tymoshenko left a comment

Choose a reason for hiding this comment

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

This was probably done for the performance reasone. I would like to see the benchmarks first.

@cesco69
Copy link
Contributor Author

cesco69 commented Mar 13, 2024

@ivan-tymoshenko the difference is very small (is a micro-optimization)

before (master)

short string............................................. x 21,651,330 ops/sec ±1.82% (185 runs sampled)
unsafe short string...................................... x 890,279,050 ops/sec ±1.42% (181 runs sampled)
short string with double quote........................... x 12,229,862 ops/sec ±2.59% (190 runs sampled)
long string without double quotes........................ x 15,138 ops/sec ±0.37% (190 runs sampled)
unsafe long string without double quotes................. x 1,022,578,589 ops/sec ±0.39% (186 runs sampled)
long string.............................................. x 15,864 ops/sec ±0.47% (189 runs sampled)
unsafe long string....................................... x 1,054,094,454 ops/sec ±0.47% (190 runs sampled)
number................................................... x 1,060,238,499 ops/sec ±0.43% (190 runs sampled)
integer.................................................. x 219,863,056 ops/sec ±0.41% (189 runs sampled)
formatted date-time...................................... x 1,708,781 ops/sec ±0.39% (191 runs sampled)
formatted date........................................... x 1,140,619 ops/sec ±0.41% (191 runs sampled)
formatted time........................................... x 1,139,486 ops/sec ±0.38% (191 runs sampled)
short array of numbers................................... x 74,560 ops/sec ±0.47% (189 runs sampled)
short array of integers.................................. x 62,719 ops/sec ±0.45% (189 runs sampled)
short array of short strings............................. x 20,168 ops/sec ±0.41% (191 runs sampled)
short array of long strings.............................. x 19,610 ops/sec ±0.64% (191 runs sampled)
short array of objects with properties of different types x 9,593 ops/sec ±0.48% (190 runs sampled)
object with number property.............................. x 1,039,195,747 ops/sec ±0.38% (190 runs sampled)
object with integer property............................. x 221,921,570 ops/sec ±0.42% (187 runs sampled)
object with short string property........................ x 22,879,162 ops/sec ±0.62% (191 runs sampled)
object with long string property......................... x 16,001 ops/sec ±0.34% (191 runs sampled)
object with properties of different types................ x 1,928,181 ops/sec ±0.84% (185 runs sampled)
simple object............................................ x 9,957,657 ops/sec ±0.41% (192 runs sampled)
simple object with required fields....................... x 9,954,660 ops/sec ±0.41% (191 runs sampled)
object with const string property........................ x 1,065,629,415 ops/sec ±0.40% (191 runs sampled)
object with const number property........................ x 1,050,253,605 ops/sec ±0.45% (188 runs sampled)
object with const bool property.......................... x 1,065,744,689 ops/sec ±0.42% (190 runs sampled)
object with const object property........................ x 1,060,911,654 ops/sec ±0.48% (189 runs sampled)
object with const null property.......................... x 1,048,597,601 ops/sec ±0.36% (191 runs sampled)

after (PR)

short string............................................. x 23,704,625 ops/sec ±0.43% (192 runs sampled)
unsafe short string...................................... x 1,052,116,318 ops/sec ±0.45% (187 runs sampled)
short string with double quote........................... x 13,418,664 ops/sec ±0.41% (191 runs sampled)
long string without double quotes........................ x 15,433 ops/sec ±0.41% (190 runs sampled)
unsafe long string without double quotes................. x 1,046,654,174 ops/sec ±0.37% (191 runs sampled)
long string.............................................. x 16,078 ops/sec ±0.41% (191 runs sampled)
unsafe long string....................................... x 1,045,056,985 ops/sec ±0.34% (190 runs sampled)
number................................................... x 1,059,855,559 ops/sec ±0.41% (192 runs sampled)
integer.................................................. x 219,744,959 ops/sec ±0.41% (191 runs sampled)
formatted date-time...................................... x 1,702,920 ops/sec ±0.34% (192 runs sampled)
formatted date........................................... x 1,145,765 ops/sec ±0.42% (191 runs sampled)
formatted time........................................... x 1,146,381 ops/sec ±0.37% (191 runs sampled)
short array of numbers................................... x 73,906 ops/sec ±0.45% (190 runs sampled)
short array of integers.................................. x 58,721 ops/sec ±0.37% (190 runs sampled)
short array of short strings............................. x 19,936 ops/sec ±0.48% (189 runs sampled)
short array of long strings.............................. x 20,276 ops/sec ±0.45% (189 runs sampled)
short array of objects with properties of different types x 9,629 ops/sec ±0.48% (191 runs sampled)
object with number property.............................. x 1,050,962,467 ops/sec ±0.49% (189 runs sampled)
object with integer property............................. x 222,334,876 ops/sec ±0.32% (191 runs sampled)
object with short string property........................ x 22,828,654 ops/sec ±0.68% (190 runs sampled)
object with long string property......................... x 16,029 ops/sec ±0.32% (192 runs sampled)
object with properties of different types................ x 1,918,710 ops/sec ±0.89% (185 runs sampled)
simple object............................................ x 9,822,513 ops/sec ±0.46% (188 runs sampled)
simple object with required fields....................... x 9,778,720 ops/sec ±0.55% (191 runs sampled)
object with const string property........................ x 1,052,599,498 ops/sec ±0.38% (191 runs sampled)
object with const number property........................ x 1,068,877,579 ops/sec ±0.44% (192 runs sampled)
object with const bool property.......................... x 1,053,391,814 ops/sec ±0.41% (190 runs sampled)
object with const object property........................ x 1,049,257,020 ops/sec ±0.39% (189 runs sampled)
object with const null property.......................... x 1,069,585,019 ops/sec ±0.42% (190 runs sampled)

@cesco69 cesco69 changed the title chore(perf): reduce if statement for NaN chore(perf): reduce if statement for NaN (micro-optimization) Mar 13, 2024
@Fdawgs Fdawgs changed the title chore(perf): reduce if statement for NaN (micro-optimization) perf: reduce if statement for NaN (micro-optimization) Mar 13, 2024
@Uzlopak
Copy link
Contributor

Uzlopak commented Mar 13, 2024

why are strings effected in the benchmark but integer and number not?

@cesco69
Copy link
Contributor Author

cesco69 commented Mar 14, 2024

why are strings effected in the benchmark but integer and number not?

@Uzlopak I think the reason is because string serialization is CPU intensive (more complex) and instable (maybe times change on each benchmark run). Integers and Numbers are super simple block of code.

My PR can't influence strings and is a too little optimization for see big changes into "number" and "integer" benchmark time.
it is still a small optimization even if the times do not change.

If we want talk about a huge optimization, this is a good PR #696

@Uzlopak
Copy link
Contributor

Uzlopak commented Mar 14, 2024

I dont see the performance gain? Which of these benchmarks is for you significant?

@Uzlopak
Copy link
Contributor

Uzlopak commented Mar 14, 2024

Maybe it is better to optimize for the valid case and check first if is an integer and if not, just throw that error.

@cesco69
Copy link
Contributor Author

cesco69 commented Mar 14, 2024

@Uzlopak

Maybe it is better to optimize for the valid case and check first if is an integer and if not, just throw that error.

mhh, good point! yep! you says this, right?

3bea520

Signed-off-by: francesco <francesco.bagnoli.69@gmail.com>
@cesco69
Copy link
Contributor Author

cesco69 commented Mar 14, 2024

I dont see the performance gain? Which of these benchmarks is for you significant?

is too small optimization to see changes into the benchmark... but this is the significant part

before (master)

number................................................... x 1,060,238,499 ops/sec ±0.43% (190 runs sampled)
integer.................................................. x 219,863,056 ops/sec ±0.41% (189 runs sampled)

after (PR)

number................................................... x 1,059,855,559 ops/sec ±0.41% (192 runs sampled)
integer.................................................. x 219,744,959 ops/sec ±0.41% (191 runs sampled)

lib/serializer.js Outdated Show resolved Hide resolved
Signed-off-by: francesco <francesco.bagnoli.69@gmail.com>
Copy link
Member

@gurgunday gurgunday left a comment

Choose a reason for hiding this comment

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

the last change is good, if we want the most performance, lgtm

Signed-off-by: francesco <francesco.bagnoli.69@gmail.com>
lib/serializer.js Outdated Show resolved Hide resolved
Co-authored-by: Aras Abbasi <aras.abbasi@googlemail.com>
Signed-off-by: francesco <francesco.bagnoli.69@gmail.com>
@Uzlopak
Copy link
Contributor

Uzlopak commented Mar 14, 2024

can i have some more benchmarks, please?

@cesco69
Copy link
Contributor Author

cesco69 commented Mar 14, 2024

can i have some more benchmarks, please?

@Uzlopak
master

integer.................................................. x 218,730,757 ops/sec ±0.40% (190 runs sampled)

PR

integer.................................................. x 219,974,956 ops/sec ±0.43% (188 runs sampled)

I have also update this check https://github.com/fastify/fast-json-stringify/blob/master/lib/serializer.js#L55 for "number" type
master

number................................................... x 1,040,965,666 ops/sec ±0.49% (188 runs sampled)

PR

number................................................... x 1,048,533,445 ops/sec ±0.48% (189 runs sampled)

Signed-off-by: francesco <francesco.bagnoli.69@gmail.com>
@cesco69 cesco69 requested a review from Uzlopak March 14, 2024 13:50
Copy link
Member

@mcollina mcollina left a comment

Choose a reason for hiding this comment

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

lgtm

awesome finding

@mcollina mcollina merged commit 7051fe6 into fastify:master Mar 18, 2024
19 checks passed
@cesco69 cesco69 deleted the patch-4 branch March 19, 2024 07:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants