brick / date-time

Date and time library for PHP
MIT License
321 stars 29 forks source link

[performance] Optimizing LocalDate::plusDays() method #78

Closed gnutix closed 9 months ago

gnutix commented 10 months ago

Hello @BenMorel,

As you've noticed, I'm focusing on some performance aspects of this library.

There's one operation we do very often in our codebase : LocalDate::plusDays(1). Mostly because we often need to convert "date and time" intervals (with an exclusive end) to "date only" intervals (with an inclusive end), and this is done by calling plusDays(1) on the end of the interval.

I have a Blackfire inspection that shows that for ~400'000 calls to plusDays() in a request, it takes 11.5 seconds, of which :

I don't think there's much that can be done regarding intdiv, as it's a native PHP function. And obviously, we can't use a cache to improve performances, as the LocalDate we call plusDays(1) from will widely vary (aka represent different dates).

So, I'm left wondering if there's maybe something there that could be done within toEpochDay and ofEpochDay themselves ? But looking at the code, I'm quite lost regarding what could actually be improved, except trying to reduce the number of mathematical operations that are done while keeping all the edge-cases they have to deal with...

Or could it be simplified by having a separate method that does specifically plusOneDay (and not "N" days) ?

I'm eager to read your thoughts and insights about this. Thanks ! gnutix

BenMorel commented 9 months ago

So, I'm left wondering if there's maybe something there that could be done within toEpochDay and ofEpochDay themselves ? But looking at the code, I'm quite lost regarding what could actually be improved, except trying to reduce the number of mathematical operations that are done while keeping all the edge-cases they have to deal with...

This code is a port from the Java version, and is a bit obscure I agree. I don't know if much can be done to improve it, but I think that the plusDays(1) optimization is a good compromise!