1

I have below code which is predominantly the most expensive in terms of time complexity in my application.

public class Test {

    private static final DateTimeFormatter SQL_FORMATTER = DateTimeFormatter.ofPattern("MM/dd/yy HH:mm:ss");

    public static void main(String[] args) {

        Instant start = Instant.now();
        try {
            String parsedDate = parseISO8601UtcDateToSqlDateFormat("2000-01-01T00:00:00Z");
            System.out.println(parsedDate);
        } finally {
            long timeTaken = Duration.between(start, Instant.now()).toMillis();
            System.out.println("\n\nFinished processing in: "+timeTaken+ " ms!\n"); 
        }
    }

    public static String parseISO8601UtcDateToSqlDateFormat(String param) {

        TemporalAccessor accessor = DateTimeFormatter.ISO_INSTANT.parse(param);
        LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.from(accessor), ZoneOffset.UTC);
        return dateTime.format(SQL_FORMATTER);

    }

}

Date time formatting is consuming 16ms at the minimum.

Whereas my complete application which does a lot of complex processing is done in less than 1ms.

P.S: Question is not related to benchmarking, I just want to understand whether date time parsing with java 8 is really this expensive or am I doing something wrong.

  • 1
    How are you benchmarking this? – Boris the Spider Mar 05 '18 at 18:34
  • Assuming you're correctly benchmarking this, is 16ms *really* a problem? – Jacob G. Mar 05 '18 at 18:36
  • *Whereas my complete application which does a lot of complex processing is done in less than 1ms.* So according to you, *lot of complex processing* done by your logic is faster than these four lines of code? Are we talking about the **for loops** and **if statements** as a complex process? –  Mar 05 '18 at 18:40
  • 1
    `DateTimeFormatter formatter = DateTimeFormatter.ofPattern(SQLFormatConstants.JAVA_DATE_FORMAT);` This can be `static final` I believe. The new java 8 datetime api compiles such pattern, and you're compiling one everytime you want to format a date. – Jazzwave06 Mar 05 '18 at 18:50
  • @sturcotte06 Joda caches patterns. Does Java Time not? – shmosel Mar 05 '18 at 19:01
  • @sturcotte06 That's very obvious.. which I already tried before posting the question. For me even a single ms is too much –  Mar 05 '18 at 19:04
  • 1
    Your benchmark is probably not giving the right result. In my own benchmark with JMH I get about 1ns (_not_ ms) on average per call, which is completely neglect-able. – Jorn Vernee Mar 05 '18 at 19:21
  • 1
    "_Question is not related to benchmarking, I just want to understand whether date time parsing with java 8 is really this expensive or am I doing something wrong._" -> you **are** doing something wrong, your measurement is wrong. I imagine you are measuring classloading. – Boris the Spider Mar 05 '18 at 19:21
  • Of your 16 ms, how many are spent doing the timing, mostly inside `Instant.now()`? – Ole V.V. Mar 06 '18 at 08:16
  • You shouldn’t need to format your date-time for SQL. Your JDBC driver will happily accept an `Instant` object (if version 4.2 compliant, which it probably is). – Ole V.V. Mar 06 '18 at 08:19
  • You're still missing a lot of class loading at that point, you can check by using `-XX:+TraceClassLoading`. You're also measuring the call to `System.out.println` which takes a long time. It's just a lot more reliable to use something like [JMH](http://openjdk.java.net/projects/code-tools/jmh/), which has most of the functionality built in. – Jorn Vernee Mar 06 '18 at 09:19
  • 1
    "_See where I'm noting the start time. I believe all class loading is done by that time._" - what makes you believe that? How about profiling/JIT? You are benchmarking the JVM not your code - listen to what literally _everyone_ is telling you. – Boris the Spider Mar 06 '18 at 19:35
  • 1
    Okay, you have now static formatters which is good practice for immutable objects. But you should really use `System.nanoTime()` instead of `Duration`-expression for minimizing the impact on benchmark results. JMH is usually better for this purpose. And if you still think after having done this that you have a performance problem then you might try my lib Time4J which contains a fast format and parse engine using [ChronoFormatter](http://time4j.net/javadoc-en/net/time4j/format/expert/ChronoFormatter.html). – Meno Hochschild Mar 07 '18 at 12:04

1 Answers1

1

Have you tried:

private static final DateTimeFormatter SQL_FORMATTER = DateTimeFormatter.ofPattern(SQLFormatConstants.JAVA_DATE_FORMAT);

private String parseISO8601UtcDateToSqlDateFormat(String param) {
    TemporalAccessor accessor = DateTimeFormatter.ISO_INSTANT.parse(param);
    LocalDateTime dateTime = LocalDateTime.ofInstant(Instant.from(accessor), ZoneOffset.UTC);
    return dateTime.format(SQL_FORMATTER);
}

New Java 8 Time API have stateless and immutable formatters. Custom formatters should be compiled once and stored in a constant (Like DateTimeFormatter.ISO_INSTANT).

Jazzwave06
  • 1,883
  • 1
  • 11
  • 19
  • 1
    Well the benchmark you're doing makes no sense. Have you considered that the formatter might have lazy initialization? Have you considered that a JVM needs to warmup? You need to do at least 10k iterations without recording any timestamps. Then do 10k iterations with a single timestamp. Split the time range on your 10k iterations. If it still gives you 16ms by iteration, then we'll keep searching for a solution. – Jazzwave06 Mar 05 '18 at 19:05
  • Also, use `System.nanoTime()` for benchmarking (or Guava's `Stopwatch`). – Jazzwave06 Mar 05 '18 at 19:08