Skip to content

Commit a9255c0

Browse files
committed
Replace Rational() method calls with rational literals for performance
Replace Rational(1, 2) with 0.5r and Rational(0) with 0r across core.rb, datetime.rb, and strftime.rb. Rational literals are resolved at compile time, avoiding method dispatch overhead on every call. Note: Rational(4800001, 2) in amjd is intentionally kept as-is because 4800001/2r is parsed as Integer#/(Rational) division at runtime, which is 2x slower than the direct Rational() constructor. Benchmark (Ruby 4.0.1 +YJIT, benchmark-ips): Date.new!: Before (Rational(1,2)): 2.812M i/s (355.58 ns/i) After (0.5r): 3.596M i/s (278.11 ns/i) Improvement: +27.9% Date#day_fraction: Before (Rational(0)): 11.230M i/s (89.05 ns/i) After (0r): 29.947M i/s (33.39 ns/i) Improvement: +166.7% Micro-benchmark (literal vs method call): 0r vs Rational(0): 34.5M vs 11.3M i/s (+3.05x) 0.5r vs Rational(1,2): 34.2M vs 8.8M i/s (+3.90x)
1 parent 7e80db9 commit a9255c0

File tree

3 files changed

+10
-10
lines changed

3 files changed

+10
-10
lines changed

lib/date/core.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ def _load(s)
328328
def new!(ajd = 0, of = 0, sg = DEFAULT_SG)
329329
# ajd is Astronomical Julian Day (may be Rational)
330330
# Convert to integer JD and day fraction (same as C's old_to_new)
331-
raw_jd = ajd + Rational(1, 2)
331+
raw_jd = ajd + 0.5r
332332
jd = raw_jd.floor
333333
df = raw_jd - jd
334334
obj = allocate
@@ -875,7 +875,7 @@ def cwyear
875875
# DateTime.new(2001,2,3,12).day_fraction # => (1/2)
876876
#
877877
def day_fraction
878-
@df || Rational(0)
878+
@df || 0r
879879
end
880880

881881
# call-seq:
@@ -1585,7 +1585,7 @@ def marshal_load(array)
15851585
when 3
15861586
# Format 1.8: [ajd, of, sg]
15871587
ajd, _of, sg = array
1588-
raw_jd = ajd + Rational(1, 2)
1588+
raw_jd = ajd + 0.5r
15891589
jd = raw_jd.floor
15901590
df = raw_jd - jd
15911591
init_from_jd(jd, sg, df == 0 ? nil : df)

lib/date/datetime.rb

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ def ajd
140140
time_r = Rational(@hour * 3600 + @min * 60 + @sec_i, 86400) +
141141
Rational(@sec_frac.numerator, @sec_frac.denominator * 86400)
142142
of_r = Rational(@of, 86400)
143-
jd_r + time_r - of_r - Rational(1, 2)
143+
jd_r + time_r - of_r - 0.5r
144144
end
145145

146146
# ---------------------------------------------------------------------------
@@ -440,12 +440,12 @@ def marshal_load(array)
440440
when 2
441441
jd_like, sg_or_bool = array
442442
sg = sg_or_bool == true ? ITALY : (sg_or_bool == false ? JULIAN : sg_or_bool.to_f)
443-
_init_datetime(jd_like.to_i, 0, 0, 0, Rational(0), 0, sg)
443+
_init_datetime(jd_like.to_i, 0, 0, 0, 0r, 0, sg)
444444
when 3
445445
ajd, of_r, sg = array
446446
of_sec = (of_r * 86400).to_i
447447
# Reconstruct local JD and time from AJD
448-
local_r = ajd + Rational(1, 2) + of_r
448+
local_r = ajd + 0.5r + of_r
449449
jd = local_r.floor
450450
rem_r = (local_r - jd) * 86400
451451
h = rem_r.to_i / 3600
@@ -857,7 +857,7 @@ def _dt_new_by_frags(hash, sg)
857857
warn("invalid offset is ignored: #{of}", uplevel: 0)
858858
of = 0
859859
end
860-
sf = hash[:sec_fraction] || Rational(0)
860+
sf = hash[:sec_fraction] || 0r
861861
_new_dt_from_jd_time(jd, h, m, s, sf, of, sg)
862862
end
863863

@@ -880,7 +880,7 @@ def _split_sec(second)
880880
s_i = s_r.floor
881881
[s_i, s_r - s_i]
882882
else
883-
[Integer(second), Rational(0)]
883+
[Integer(second), 0r]
884884
end
885885
end
886886

@@ -932,7 +932,7 @@ def _split_second(second)
932932
s_i = s_r.floor
933933
[s_i, s_r - s_i]
934934
else
935-
[Integer(second), Rational(0)]
935+
[Integer(second), 0r]
936936
end
937937
end
938938

lib/date/strftime.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ def internal_sec
523523
end
524524

525525
def sec_frac
526-
Rational(0)
526+
0r
527527
end
528528

529529
def of_seconds

0 commit comments

Comments
 (0)