Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-8068803

Performance of LocalDate.plusDays could be better

    Details

    • Type: Bug
    • Status: Resolved
    • Priority: P4
    • Resolution: Fixed
    • Affects Version/s: 8
    • Fix Version/s: 9
    • Component/s: core-libs
    • Labels:
      None
    • Subcomponent:
    • Resolved In Build:
      b102

      Description

      LocalDate.plusDays() is relatively slow for the common case. As this method is widely used (by minusDays, plusWeeks, minusWeeks and matching methods on other classes such as LocalDateTime and ZonedDateTime) this change will have wide ripple through benefits.

      The common case for adding/subtracting days on a date is adding/subtracting 1 day. In the codebase I work on this accounts for about 70% of all uses of the method. Less than 3% was additions/subtractions of over 30 days. The current logic in plusDays() does not distinguish the common case.

      Benchmarking has been performed here:
      https://github.com/ThreeTen/threeten-bench/blob/master/src/main/java/org/threeten/LocalDateBenchmark.java (non-OpenJDK server but any necessary rights hereby granted to OpenJDK)

      Based on trying 5 different approaches, propose adding option 3 to LocalDate in OpenJDK. The existing implementation of LocalDate.plusDays() would be replaced as follows:

          public LocalDate plusDays(long daysToAdd) {
              if (daysToAdd == 0) {
                  return this;
              }
              long dom = day + daysToAdd;
              if (dom > 0 && dom <= 59) { // 59th Jan is 28th Feb, 59th Feb is 31st Mar
                  int monthLen = input.lengthOfMonth();
                  if (dom <= monthLen) {
                      return LocalDate.of(year, month, (int) dom);
                  } else if (month < 12) {
                      return LocalDate.of(year, month + 1, (int) (dom - monthLen));
                  } else {
                      return LocalDate.of(year + 1, 1, (int) (dom - monthLen));
                  }
              }
              long mjDay = Math.addExact(toEpochDay(), daysToAdd);
              return LocalDate.ofEpochDay(mjDay);
          }

      This option is a reasonable balance of higher performance and simplicity, handling where the date moves to later in the current month or most dates in the next month. This also handles subtraction within the current month.

      This code is roughly 3.7 times faster than the current code. In the non-optimized fallback case, there is very little negative impact (not measurable).

      Given how core the method is and the widespread impact of this one change, backporting to JDK 8 appears worthwhile.

      Existing test cases cover this method OK, however some additional testing would be worthwhile, particular to cover the additional edge cases.

        Activity

        Hide
        hgupdate HG Updates added a comment -
        URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/ad15d9eb8b41
        User: rriggs
        Date: 2016-01-11 16:50:43 +0000
        Show
        hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/dev/jdk/rev/ad15d9eb8b41 User: rriggs Date: 2016-01-11 16:50:43 +0000
        Hide
        hgupdate HG Updates added a comment -
        URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/ad15d9eb8b41
        User: lana
        Date: 2016-01-20 20:51:00 +0000
        Show
        hgupdate HG Updates added a comment - URL: http://hg.openjdk.java.net/jdk9/jdk9/jdk/rev/ad15d9eb8b41 User: lana Date: 2016-01-20 20:51:00 +0000

          People

          • Assignee:
            ntv Nadeesh Tv (Inactive)
            Reporter:
            scolebourne Stephen Colebourne
          • Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: