-
Notifications
You must be signed in to change notification settings - Fork 180
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
Conversation
…tions when using ruby >= 2.3 - SimpleDecoder::TimestampWithTimeZone::decode - SimpleDecoder::TimestampWithoutTimeZone::decode
…when the string can't be parsed.
- 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
There was a problem hiding this 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.
@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. |
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 |
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 providerb_time_timespec_new()
)timegm()
ormktime()
fails at runtime (happens on Android)I did some very simple benchmarks with the following results: