ruby: Improve performance of Google::Protobuf::Timestamp#to_time (#6360)
This changes to_time to use Ruby's built in Time.at with nanos support
rather than calculating a float and passing it to Time.at. The new
version runs about 3 times faster than the original version and
allocates fewer objects.
Warming up --------------------------------------
protobuf#to_time 57.296k i/100ms
faster#to_time 133.229k i/100ms
Calculating -------------------------------------
protobuf#to_time 635.361k (± 2.1%) i/s - 3.209M in 5.052169s
faster#to_time 1.873M (± 3.3%) i/s - 9.459M in 5.055169s
Comparison:
faster#to_time: 1873368.8 i/s
protobuf#to_time: 635361.4 i/s - 2.95x slower
Calculating -------------------------------------
protobuf#to_time 326.000 memsize ( 126.000 retained)
7.000 objects ( 2.000 retained)
0.000 strings ( 0.000 retained)
faster#to_time 86.000 memsize ( 0.000 retained)
1.000 objects ( 0.000 retained)
0.000 strings ( 0.000 retained)
Comparison:
faster#to_time: 86 allocated
protobuf#to_time: 326 allocated - 3.79x more
diff --git a/ruby/lib/google/protobuf/well_known_types.rb b/ruby/lib/google/protobuf/well_known_types.rb
index 2ee65bc..37f8d5b 100644
--- a/ruby/lib/google/protobuf/well_known_types.rb
+++ b/ruby/lib/google/protobuf/well_known_types.rb
@@ -72,8 +72,14 @@
end
Timestamp.class_eval do
- def to_time
- Time.at(self.to_f)
+ if RUBY_VERSION < "2.5"
+ def to_time
+ Time.at(self.to_f)
+ end
+ else
+ def to_time
+ Time.at(seconds, nanos, :nanosecond)
+ end
end
def from_time(time)