Time::Moment vs DateTime
In December last year released the first version of Time::Moment. I don't foresee any major changes in Time::Moment 0.16 API, so in next release I'll remove the "early preview release" notice in the description. I have been using 0.16 in production two different deployments with great success, by removing DateTime from the ORM we have seen significantly reduced the memory usage and CPU usage and increased the throughput when inflating timestamps from a RDBM, previously DateTime was a one of our bottleneck in our profiling.
A couple of years ago I was faced with a ultimatum, either you make this code (a perl code base) faster and use less CPU and memory or we will have to move to another language or implementation. The code base in question processed logs and inflated a DateTime.pm for every timestamp. At that time i looked at DateTime source and decided that I would be better of with a more efficient implantation in C which I could glue to Perl/XS. Well, I couldn't find a codebase, so I had to develop one from scratch (the birth of c-dt), and so I did and solved the clients need.
The core for Time::Moment base is based on c-dt which has been in usage for several years.
iMac-27:p5-time-moment chansen$ perl dev/bench.pl Benchmarking constructor: ->new() Rate DateTime Time::Moment DateTime 25259/s -- -99% Time::Moment 2041902/s 7984% --Benchmarking constructor: ->now()
Rate DateTime Time::Piece localtime() Time::Moment
DateTime 13865/s -- -94% -99% -99%
Time::Piece 223194/s 1510% -- -80% -87%
localtime() 1097543/s 7816% 392% -- -34%
Time::Moment 1657189/s 11853% 642% 51% --Benchmarking constructor: ->now_utc()
Rate DateTime Time::Piece gmtime() Time::Moment
DateTime 29008/s -- -87% -98% -99%
Time::Piece 230440/s 694% -- -83% -92%
gmtime() 1361443/s 4593% 491% -- -52%
Time::Moment 2829107/s 9653% 1128% 108% --Benchmarking constructor: ->from_epoch()
Rate DateTime Time::Piece Time::Moment
DateTime 29896/s -- -88% -99%
Time::Piece 242526/s 711% -- -92%
Time::Moment 3104830/s 10286% 1180% --Benchmarking accessor: ->year()
Rate DateTime Time::Piece Time::Moment
DateTime 3194172/s -- -14% -59%
Time::Piece 3709584/s 16% -- -52%
Time::Moment 7796400/s 144% 110% --Benchmarking arithmetic: +10 days -10 days
Rate DateTime Time::Piece Time::Moment
DateTime 3532/s -- -98% -100%
Time::Piece 157780/s 4367% -- -94%
Time::Moment 2667260/s 75417% 1590% --Benchmarking: at end of current month
Rate DateTime Time::Moment
DateTime 2767/s -- -100%
Time::Moment 1460621/s 52690% --Benchmarking strftime: ->strftime('%FT%T')
Rate DateTime POSIX::strftime Time::Piece Time::Moment
DateTime 91116/s -- -65% -82% -94%
POSIX::strftime 263224/s 189% -- -49% -83%
Time::Piece 515384/s 466% 96% -- -67%
Time::Moment 1579032/s 1633% 500% 206% --Benchmarking sort: 1000 instants
Rate DateTime Time::Piece Time::Moment
DateTime 22.7/s -- -70% -98%
Time::Piece 77.0/s 239% -- -93%
Time::Moment 1135/s 4894% 1374% --
iMac-27:p5-time-moment chansen$ perl dev/sizeof.pl Comparing instance size: Time::Moment ............... : 104 B Time::Piece ................ : 456 B localtime() ................ : 296 B DateTime ................... : 4019 B DateTime w/o zone and locale : 2545 BComparing Storable::nfreeze() size:
Time::Moment ............... : 34 B
DateTime ................... : 156 B
This looks amazingly cool with a slightly friendlier interface!
What are the functional differences to DateTime? Are there any incompatibilities? That's the first section I looked for in the docs.
I'm seriously considering switching to Time::Moment. While DateTime is great functionality-wise, it's really slow, bloated, and unfit for some use-cases.
I have been watching this for a while. Amazing work, it even beats Time::Piece in terms of speed and memory used. I don't like DateTime, it has way too many dependencies and it'slow. You should have probably included Class::Date and even the lesser known Class::Date compatible Panda::Date.
Time::Moment represents an unambiguous point in time, but it's not fully time zone aware. If you have a local time (a point in time with an offset) you may need to use a time zone if you intend to perform arithmetic on the local date/time or altering the components of the local date/time. It's documented in TIME ZONES.
Time::Moment isn't feature complete, I intend to add a Duration object which models time only. David Golden has requested support for RFC timestamps in ->from_string which I intend to add at a later point.
Thanks, I'll consider adding Class::Date and Panda::Date to the benchmark.
This looks interesting, especially https://github.com/chansen/c-dt.
And for anyone who goes to that github page and wonders what a "proleptic Gregorian calendar" is, here's a link:
https://en.wikipedia.org/wiki/Proleptic_Gregorian_calendar
Thank you very much.
Jim Keenan
I'm glad you like c-dt, Time::Moment only uses a fraction of the API povided by c-dt. As you might have seen c-dt provides calculation of easter (western/orthodox), efficient business day calculations and weekday calculations and a bit more.
c-dt is a workhorse in some of our internal financial applications.
Perl badly needs a standard or at least a "de facto" standard for date time handling. DateTime has seemed to be emerging as that standard for some years. Unfortunately this is the third or so article in the last twelve months criticising it and promoting something else.
Wouldn't it have been great to read that two clever programmers had collaborated and that DateTime version ??? was backward compatable and really flew.
Then the benefits would have gradually crept into our codebase without me getting into another argument about standard modules.
The stats quoted for Time::Moment are impressive.
At a glance, the basic constructor arguments and basic attributes are compatible with DateTime making it a drop-in replacement in some cases.
However, the basic arithmetic operations are different. These are fairly common operations such as adding hours or days. This will make it very limited as a drop-in replacement.
Is there a case for some sort of DateTime::Facade namespace to hold modules which put DateTime compatible wrappers around other date/time modules? There would be an overhead in the extra layer of abstraction, but this might not be large.
"without me getting into another argument about standard modules"
Slightly worried about what I've written there. I'm writing about an argument at $work, not with anyone on this list.
I'm not sure what you are asking, if you think I didn't try to improve the performance of DateTime.pm, you think wrong (look at the changelog or ask Dave Rolsky).
Time::Moment can never be "backwards" comparability with DateTime.pm due to DateTime.pm's design.
Panda::Date is the fastest available framework. It doesn't use OS's time functions, instead it implements its own which are much faster. And with all these speeds, it is full-featured like datetime
moreover it has C++ interface with speeds of dozens millions/s. which you can use from your xs modules diretcly without slow perl layers.
Time::Moment only use gettimeofday(2) and localtime(3) to compute the difference.
I did consider to add Panda::Date until I reviewed the source code. Your code isn't thread safe and you require 5.18 to compile it, and your naïve implementation of a date with a time representation due to the broken down representation is just a wasteful! An instance of Time::Moment requires 16 bytes plus the overhead of a scalar allocation and is mostly faster than your implementation that doesn't even support a fractional representation!
And the benchmark:
Gonna migrate our PERL5 applications from DateTime => Time::Moment. Thanks for all the efforts.