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

Faster string generator #213

Merged
merged 7 commits into from
Jul 17, 2022
Merged

Faster string generator #213

merged 7 commits into from
Jul 17, 2022

Conversation

kachick
Copy link
Owner

@kachick kachick commented Jul 17, 2022

ref: #102, https://github.com/kachick/ruby-ulid/wiki/Benchmark, https://github.com/rbspy/rbspy, https://github.com/tmm1/stackprof

Just use cache does not make much faster.

Before

#### kachick - ruby-ulid(This one)
cd ./benchmark/compare_with_othergems/kachick
bundle install --quiet
bundle exec ruby -v ./generate.rb
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
Warming up --------------------------------------
  ULID.generate.to_s     6.555k i/100ms
Calculating -------------------------------------
  ULID.generate.to_s     62.171k (±10.6%) i/s -    308.085k in   5.015662s
"`ruby-ulid gem (this one) - 0.5.0` generated products: 439170 - sample: [\"01G86P982YH0Z09JQ3VD1K6SSD\", \"01G86P96SMW2CSG0379AGMQ1XC\", \"01G86P9AYMMBHXEM4G70EF47BB\", \"01G86P9BC89AZGPXVT7N6PRT58\", \"01G86P99KFFRSJAY10TBJ4BS67\"]"
cd -

After

❯ rake benchmark_with_other_gems
#### kachick - ruby-ulid(This one)
cd ./benchmark/compare_with_othergems/kachick
bundle install --quiet
bundle exec ruby -v ./generate.rb
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
Warming up --------------------------------------
         ULID.encode     7.080k i/100ms
Calculating -------------------------------------
         ULID.encode     64.003k (±10.0%) i/s -    318.600k in   5.031231s
"`ruby-ulid gem (this one) - 0.6.0.pre` generated products: 454935 - sample: [\"01G86NV9B5ZMRH7SZK0BZYJT48\", \"01G86NV76W39M9YY9X93E2X4JV\", \"01G86NVB235XFQ09MKH3626AB2\", \"01G86NVCXDFX6SRE6148XVFN9X\", \"01G86NVAY1GWNWE4VMRY2497ZT\"]"

Do stackprof

❯ rake stackprof
bundle exec ruby ./scripts/prof.rb
bundle exec stackprof tmp/stackprof-wall-*.dump --text --limit 1
==================================
  Mode: wall(1000)
  Samples: 1301 (0.00% miss rate)
  GC: 225 (17.29%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
       481  (37.0%)         481  (37.0%)     String#gsub
bundle exec stackprof tmp/stackprof-cpu-*.dump --text --limit 1
==================================
  Mode: cpu(1000)
  Samples: 131 (0.00% miss rate)
  GC: 24 (18.32%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
        54  (41.2%)          54  (41.2%)     String#gsub

Replacing String#gsub with String#tr makes almost 2x faster. And now bottleneck is mandatory random generator.

❯ rake stackprof
bundle exec ruby ./scripts/prof.rb
bundle exec stackprof tmp/stackprof-wall-*.dump --text --limit 1
==================================
  Mode: wall(1000)
  Samples: 695 (0.00% miss rate)
  GC: 66 (9.50%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
       280  (40.3%)         280  (40.3%)     Random.urandom
bundle exec stackprof tmp/stackprof-cpu-*.dump --text --limit 1
==================================
  Mode: cpu(1000)
  Samples: 68 (0.00% miss rate)
  GC: 11 (16.18%)
==================================
     TOTAL    (pct)     SAMPLES    (pct)     FRAME
        29  (42.6%)          29  (42.6%)     Random.urandom
❯ rake benchmark/generate_vs_encode.rb
/home/kachick/.rubies/ruby-3.1.2/bin/ruby benchmark/generate_vs_encode.rb
Warming up --------------------------------------
  ULID.generate.to_s    12.980k i/100ms
         ULID.encode    14.573k i/100ms
Calculating -------------------------------------
  ULID.generate.to_s    131.198k (± 5.7%) i/s -    661.980k in   5.066869s
         ULID.encode    147.106k (± 3.7%) i/s -    743.223k in   5.059546s

Comparison:
         ULID.encode:   147105.5 i/s
  ULID.generate.to_s:   131197.8 i/s - 1.12x  (± 0.00) slower

Now this gem is almost 1.5x faster than other major gems (As far as I know in pure ruby)

❯ rake benchmark_with_other_gems
------------------------------------------------------------------------
#### kachick - ruby-ulid(This one)
cd ./benchmark/compare_with_othergems/kachick
bundle install --quiet
bundle exec ruby -v ./generate.rb
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
Warming up --------------------------------------
         ULID.encode    12.363k i/100ms
Calculating -------------------------------------
         ULID.encode    119.758k (±14.3%) i/s -    593.424k in   5.071896s
"`ruby-ulid gem (this one) - 0.6.0.pre` generated products: 832041 - sample: [\"01G86TFTMSMAYPX24J3NWBYB3N\", \"01G86TFW3TS0YSNR3RY6E5SRDF\", \"01G86TFSH3YM4FCQB5W4VARCZV\", \"01G86TFX92QKAJXC3ADCA1J662\", \"01G86TFV0QYWNKD2NHH88YW57H\"]"
cd -
------------------------------------------------------------------------
#### rafaelsales - ulid
cd ./benchmark/compare_with_othergems/rafaelsales
bundle install --quiet
bundle exec ruby -v ./generate.rb
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
Warming up --------------------------------------
       ULID.generate     9.128k i/100ms
Calculating -------------------------------------
       ULID.generate     82.906k (±11.0%) i/s -    410.760k in   5.026247s
"`ulid gem - 1.3.0` generated products: 585831 - sample: [\"01G86TG68FGBY0VCGENC9YC3NT\", \"01G86TG6A788TJQ8BB29MQYS2Q\", \"01G86TG7JNWXWP5G1NDSS8K00J\", \"01G86TG54JVTPN4ZNNWQYCVVEE\", \"01G86TG3S0RPSMRM1EYGPDJX9D\"]"
cd -
------------------------------------------------------------------------
#### abachman - ulid-ruby
cd ./benchmark/compare_with_othergems/abachman
bundle install --quiet
bundle exec ruby -v ./generate.rb
ruby 3.1.2p20 (2022-04-12 revision 4491bb740a) [x86_64-linux]
Warming up --------------------------------------
       ULID.generate     7.454k i/100ms
Calculating -------------------------------------
       ULID.generate     67.697k (±10.4%) i/s -    335.430k in   5.011842s
"`ulid-ruby gem - 1.0.2` generated products: 475505 - sample: [\"01G86TGA3T4HWA3MR4YDQSS4NV\", \"01G86TGE7BZJMDKPDMJCH9F00X\", \"01G86TGAA4414FF9GG1AV2M8HX\", \"01G86TGFKZXWFP06XAMW5V57Q5\", \"01G86TGAFER6BH0Q3DVJW5EAWD\"]"
cd -
irb(main):002:0> Rational(119.758, 82.906).to_f
=> 1.4445034135044508
irb(main):003:0> Rational(119.758, 67.697).to_f
=> 1.7690296468085733

🎉 ⚡

* Implement `ULID.gen` for String optimized generator
* Removed lazy calculation for `ULID#to_s`
* Prefer `ULID#encode` rather than `to_s` in implementation
@kachick kachick added enhancement New feature or request performance Optimized for performance labels Jul 17, 2022
kachick added a commit that referenced this pull request Jul 17, 2022
@kachick kachick marked this pull request as ready for review July 17, 2022 19:40
@kachick kachick merged commit 993d903 into main Jul 17, 2022
@kachick kachick deleted the faster-string-generator branch July 17, 2022 19:41
@kachick
Copy link
Owner Author

kachick commented Jul 17, 2022

no confidence for the namings…

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request performance Optimized for performance
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant