Re: DateTime Performance
On 8/4/03 12:26 AM, Dave Rolsky wrote: # ... includes args: year, month, day, hour, minute, second DateTime-new(...): 16 wallclock secs @ 687.29/s (14.48 usr + 0.07 sys = 14.55 CPU) This does a lot of work, including calculating both UTC local times, which involves calculating leap seconds, etc. Does it need to do that? I mean, sure, eventually it might have to do that if I want to do some sort of date manipulation, or even just fetch or print the date. But does it have to really do anything at all during object construction other than stash the args somewhere? DateTime-now(): 21 wallclock secs @ 547.95/s (18.13 usr + 0.12 sys = 18.25 CPU) Ditto. I'm assuming now() is slower than new() due to the system call overhead of getting the current time...? Total Elapsed Time = 19.91729 Seconds User+System Time = 14.60729 Seconds Exclusive Times %Time ExclSec CumulS #Calls sec/call Csec/c Name 27.6 4.035 4.685 20274 0.0002 0.0002 Params::Validate::_validate 24.0 3.510 17.549 1 0.0004 0.0018 DateTime::new 18.9 2.770 3.809 10001 0.0003 0.0004 DateTime::Locale::_load_class_from_id This seems quite odd. It really doesn't do much. 8.96 1.309 2.647 10020 0.0001 0.0003 DateTime::TimeZone::BEGIN And this is completely mystifying. Can you show us your code? Sure, here it is: for(1 .. 1) { my $d = DateTime-new(year = 200, month = 1, day = 1, hour = 2, minute = 3, second = 4); } Those stats were produced on a G3/400 running a development release of OS X that uses some build of Perl 5.8.1, which could explain some oddness. Here is the same code run on a G4/800 using Perl 5.8.0 on the latest released version of OS X 10.2: Total Elapsed Time = 8.817281 Seconds User+System Time = 5.352659 Seconds Exclusive Times %Time ExclSec CumulS #Calls sec/call Csec/c Name 60.4 3.236 10.844 1 0.0003 0.0011 DateTime::new 44.7 2.395 3.305 10001 0.0002 0.0003 DateTime::Locale::_load_class_from_id 43.3 2.318 2.127 20274 0.0001 0.0001 Params::Validate::_validate 22.5 1.207 1.095 10001 0.0001 0.0001 DateTime::Locale::Base::new 18.4 0.987 1.223 10020 0.0001 0.0001 DateTime::TimeZone::BEGIN 17.5 0.939 0.465 5 0. 0. DateTime::__ANON__ 15.2 0.818 0.645 10002 0.0001 0.0001 DateTime::_calc_local_components 12.8 0.687 1.025 10002 0.0001 0.0001 DateTime::_calc_local_rd 10.6 0.568 0.525 10002 0.0001 0.0001 DateTime::_calc_utc_rd 8.20 0.439 0.225 10002 0. 0. DateTime::_normalize_seconds 7.83 0.419 0.275 1 0. 0. DateTime::_last_day_of_month 7.47 0.400 0.115 30006 0. 0. DateTime::TimeZone::Floating::is_floating 7.27 0.389 3.505 10001 0. 0.0004 DateTime::Locale::load 5.79 0.310 0.214 10006 0. 0. DateTime::TimeZone::Floating::BEGIN 4.86 0.260 0.070 20004 0. 0. DateTime::TimeZone::OffsetOnly::is_utc Maybe that looks more sane to you? So, what does everyone else think of the object creation performance situation? Is it simply good enough to be 3x faster that Date::Manip::ParseDate()? Are there any obvious areas that I should consider before I start mucking around with DateTime::new()? Considering that up til now my concern has been primarily on getting things correct, I wouldn't worry about it. There are definitely some big performance improvements possible. One possibility is to move the leap second bits into the DateTime XS code, which should help a lot. The timezone stuff can also benefit from being rewritten as XS, but that won't help the particular cases you benchmarked, since the UTC and floating time zones are quite fast already. What about what I mentioned earlier: lazy (or lazier) evaluation in the constructor? Basically, I want construction with known values to be as fast as possible since there's a chance I may not even look at the date fields of my objects. But it's a hassle to have special-case code that either doesn't fetch or doesn't set the date fields of my objects, just so I can avoid the relatively expansive calls to DateTime-new() -John
Re: DateTime Performance
On 8/4/03 10:10 AM, John Siracusa wrote: On 8/4/03 12:26 AM, Dave Rolsky wrote: # ... includes args: year, month, day, hour, minute, second DateTime-new(...): 16 wallclock secs @ 687.29/s (14.48 usr + 0.07 sys = 14.55 CPU) This does a lot of work, including calculating both UTC local times, which involves calculating leap seconds, etc. Does it need to do that? I mean, sure, eventually it might have to do that if I want to do some sort of date manipulation, or even just fetch or print the date. But does it have to really do anything at all during object construction other than stash the args somewhere? I played around with DateTime::new() and found that the biggest culprit is this line: $self-{locale} = DateTime::Locale-load( $p{locale} ); The removal of which more than doubles the performance of calling DateTime::new(...) with ymdhms args. The only way to get a comparable speedup is to remove every line below that one except for these two: bless $self, $class; return $self; And even that only gives a ~90% speedup vs. the 100%+ gained by ditching DateTime::Locale-load(). (Obviously all of this will hose DateTime's actual functionality, but bear with me :) Profiling showed that DateTime::Locale::_load_class_from_id() was being called N+1 times during N calls to DateTime-new(...), and that it was #3 in the dprofpp list (2000 iterations shown): %Time ExclSec CumulS #Calls sec/call Csec/c Name 47.8 0.663 2.135 2000 0.0003 0.0011 DateTime::new 35.2 0.488 0.399 4274 0.0001 0.0001 Params::Validate::_validate 31.6 0.439 0.517 2001 0.0002 0.0003 DateTime::Locale::_load_class_from_id 15.8 0.219 0.313 2020 0.0001 0.0002 DateTime::TimeZone::BEGIN I found that _load_class_from_id() unconditionally executes this code: eval require $real_class; Skipping that line was good for a 30%+ speed boost, but that got me thinking...aren't the Locale objects loaded/created by _load_class_from_id() singletons? Replacing calls to _load_class_from_id() within DateTime::Locale::load() with some dumb caching like this: $Cache_By_Id{$id} ||= $class-_load_from_id($id) Resulted in an easy 50% speed-up for DateTime-new(...), and _load_class_from_id() dropped completely off the dprofpp output: Total Elapsed Time = 0.841889 Seconds User+System Time = 0.501889 Seconds Exclusive Times %Time ExclSec CumulS #Calls sec/call Csec/c Name 116. 0.584 1.290 2000 0.0003 0.0006 DateTime::new 79.3 0.398 0.287 4274 0.0001 0.0001 Params::Validate::_validate 41.6 0.209 0.220 2002 0.0001 0.0001 DateTime::_calc_local_rd 37.6 0.189 0.238 2020 0.0001 0.0001 DateTime::TimeZone::BEGIN 31.6 0.159 0.150 2002 0.0001 0.0001 DateTime::_calc_utc_rd 27.8 0.140 0.070 2002 0.0001 0. DateTime::_calc_local_components 25.9 0.130 0.030 1 0. 0. DateTime::__ANON__ 17.9 0.090 0.070 2001 0. 0. DateTime::DefaultLocale 15.9 0.080 0.040 4004 0. 0. DateTime::TimeZone::OffsetOnly::is_utc 15.9 0.080 0.030 2000 0. 0. DateTime::_last_day_of_month 15.9 0.080 0.040 2002 0. 0. DateTime::_normalize_seconds 13.9 0.070 0.010 6006 0. 0. DateTime::TimeZone::Floating::is_floating 13.9 0.070 0.069 2006 0. 0. DateTime::TimeZone::Floating::BEGIN 11.3 0.057 0.115 1 0.0573 0.1145 DateTime::Locale::register 7.97 0.040 0.154 6 0.0067 0.0257 DateTime::Locale::BEGIN (An aside: why is DateTime::DefaultLocale on this list at all?) To test my theory that this kind of dumb caching is valid, I ran all of DateTime::Locale's tests, and then ran DateTime's tests while using the modified DateTime::Locale. Everything passed. So, assuming I'm not missing a finer point here, I'm thinking that one easy speed-up for DateTime object creation would be to make the various DateTime::Locale::* classes into singletons (using whatever the proper method is for this in the DT project) and avoid repeated string evals and repeated calls to _load_class_from_id(). Going further, if calls to DateTime::Locale-load(...) could be memoized safely, that'd be great too :) -John
Re: DateTime Performance
On 8/4/03 1:25 PM, Ben Bennett wrote: Why not make your module be lazy about whether or not it creates a DateTime? I thought of that, but I also use the act of creating a DateTime object to check the validity of date attributes. Anyway, I think there's room for DateTime-new() optimization even without adding lazy evaluation (see earlier posts). -John
Is anyone working on the Hebrew Calendar?
Is anyone working on a DateTime::Calendar::Hebrew implemetation? I did the pre-requisite search with Google, but I couldn't find any mention of someone working on it. I've been working with the Hebrew calendar for years, and I have loads of code (non object oriented), all based on Dershowitz-Reingold. I also have code that might be classified as DateTime::Calendar::Jewish or DateTime::Calendar::Hebrew::Religious, but we'll save that for later. Just need to get my head around the API requirements, and I should be able to put some code out there. Steve