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 time decoder #20

Merged
merged 11 commits into from
May 3, 2018
Merged

Faster time decoder #20

merged 11 commits into from
May 3, 2018

Conversation

larskanis
Copy link
Collaborator

This moves PG::SimpleDecoder::TimestampWithTimeZone and PG::SimpleDecoder::TimestampWithoutTimeZone to C. It is based on #19 with some tweaking by me.

I tested the implementation successfully on Windows-10 with MINGW (RubyInstaller), Ubuntu-18.04 with glibc, Alpine-Linux-3.7 with musl-libc and Android-7.0 with bionic-libc (termux).

The conversion is done by a fast path and as a fallback by a slower path. The slow path is used under these conditions:

  • timegm() is not available (on Windows)
  • RUBY_VERSION < 2.3.0 (it doesn't provide rb_time_timespec_new())
  • time conversion by timegm() or mktime() fails at runtime (happens on Android)

I did some very simple benchmarks with the following results:

ruby -Ilib -rpg -e "map=PG::TypeMapByColumn.new([PG::TextDecoder::TimestampWithTimeZone.new]); res=PG.connect.exec(\"SELECT '2016-01-02 22:23:59.3-04'::timestamptz\").map_types!(map); st=Time.now; 10000.times{ res.getvalue(0,0) }; p Time.now-st"
version time
master (RegExp) 0.71s
vhl-time-decoder slow path 0.41s
vhl-time-decoder fast path 0.022s

remy-cassia-tech and others added 11 commits April 30, 2018 15:21
…tions when using ruby >= 2.3

- SimpleDecoder::TimestampWithTimeZone::decode
- SimpleDecoder::TimestampWithoutTimeZone::decode
- Don't fail when the time is more precise than processed
- Shorten some expect-series.
- Change Spaces->Tabs.
- Add a test case for leap-seconds.
…c_new()

Both _mkgmtime() as well as mktime() return errors with certain dates.
This path is approx. 10 times slower, compared with
rb_time_timespec_new().
Its still 10 times faster than the previous RegExp way.
Also fall through to the slow path, because it fails on Android (using termux)
with certain time values otherwise:

Failures:

  1) PG::Type derivations PG::SimpleCoder#decode timestamps decodes timestamps with date before 1823
     Failure/Error:
       expect( textdec_timestamp.decode('1822-01-02 23:23:59.123456') ).
        to be_within(0.000001).of( Time.new(1822,01,02, 23, 23, 59.123456) )

       expected "1822-01-02 23:23:59.123456" to be within 1.0e-06 of 1822-01-02 23:23:59 +0100, but it could not be treated as a numeric value
     # ./spec/pg/type_spec.rb:125:in `block (5 levels) in <top (required)>'
     # ./spec/helpers.rb:31:in `block in included'

  2) PG::Type derivations PG::SimpleCoder#decode timestamps decodes timestamps with date after 2116
     Failure/Error:
       expect( textdec_timestamp.decode('2117-01-02 23:23:59.123456') ).
        to be_within(0.000001).of( Time.new(2117,01,02, 23, 23, 59.123456) )

       expected "2117-01-02 23:23:59.123456" to be within 1.0e-06 of 2117-01-02 23:23:59 +0100, but it could not be treated as a numeric value
     # ./spec/pg/type_spec.rb:129:in `block (5 levels) in <top (required)>'
     # ./spec/helpers.rb:31:in `block in included'

Finished in 1 minute 19.47 seconds (files took 1.27 seconds to load)
386 examples, 2 failures, 1 pending
Copy link
Owner

@ged ged left a comment

Choose a reason for hiding this comment

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

Looks good to me! I learned a few Ruby+C things too, so thanks for doing this.

@larskanis
Copy link
Collaborator Author

@ged Thank you very much for reviewing! I'll merge it when time permits.

Moreover I think it makes sense to add another de+encoder for timestamps without timezone, which are treated as UTC time instead of local time. This is how ActiveRecord handles timestamps without timezone per default.

@larskanis larskanis merged commit 241cd5e into ged:master May 3, 2018
@alboyadjian
Copy link

Thank you for merging this! It's a big speed boost for us as we're using the raw exec for a hefty query. Thank you for your cleanup @larskanis

@larskanis larskanis deleted the vhl-time-decoder branch August 17, 2021 09:12
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.

4 participants