Java 8 DateTimeFormatter performance
我有下面的代码,它在我的应用程序中主要是时间复杂度方面最昂贵的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| 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("
Finished processing in:"+timeTaken +" ms!
");
}
}
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 );
}
} |
日期时间格式至少需要16毫秒。
而我的完整应用程序,它可以在不到1毫秒的时间内完成许多复杂的处理。
P.S:问题与基准测试无关,我只是想了解JAVA 8的日期时间解析是否真的这么贵,还是我做错了什么。
- 你如何标杆这一点?
- 假设你是正确的基准测试,16毫秒真的是个问题吗?
- 通过测量自我的程序启动以来的持续时间以及所有处理完成后的持续时间duration.between(start,instant.now()).tomillis();
- 而我的整个应用程序做了很多复杂的处理,在不到1毫秒的时间里就完成了,所以根据你的说法,你的逻辑做了很多复杂的处理,比这四行代码快?我们说的for循环和if语句是一个复杂的过程吗?
- 不,我的应用程序包含50个其他文件,大约有3K行代码。所有的处理都比这4行代码快得多。
- 实际上,我正在为我的需求编写一个编译器和运行时引擎,其中包括处理大量数据。16毫秒不是问题,但事实上,目前这个方法在我的流程中只被调用了两次。如果通信量出现这样的情况,则必须进行1000次或更多次的日期分析。那肯定是个问题。
- 我相信这可能是static final。新的Java 8 DeaTimeAPI编译了这样的模式,并且每次编译日期时都要编译一个模式。
- @Sturcette06 Joda缓存模式。Java时间不是吗?
- @环行交叉口我用一个样本测试程序编辑了我的问题。自己跑看看
- @很明显。在发布问题之前我已经尝试过了。对我来说,即使是一个女士也太多了
- 你的基准可能没有给出正确的结果。在我自己的JMH基准测试中,每次调用平均可以得到1ns(而不是ms),这是完全可以忽略的。
- "问题与标杆无关,我只是想了解,用Java 8解析日期时间是否真的很贵,还是我做错了什么?"-->你做错了什么,你的测量是错误的。我想你是在衡量课堂负荷。
- 看看我在哪里记下开始时间。我相信到那时所有的课程都完成了。谢谢@jornverne的评论,如果至少在某个地方平均执行时间为~1ns,那么我的疑问就很清楚了。
- 在你的16个毫秒中,有多少是花在计时上的,主要是在Instant.now()内部?
- 您不需要为SQL设置日期时间格式。您的JDBC驱动程序会很高兴地接受一个Instant对象(如果版本4.2兼容,可能就是这样)。
- 在这一点上,您仍然缺少很多类加载,您可以使用-XX:+TraceClassLoading进行检查。你也在测量对System.out.println的呼叫,这需要很长时间。使用像JMH这样的内置大部分功能的东西,会更加可靠。
- "看看我在哪里记下了开始时间。我相信所有的课堂加载都是在那个时候完成的。"—你凭什么相信?分析/jit怎么样?你在标杆的是JVM,而不是你的代码——听每个人都在告诉你什么。
- 好了,现在有了静态格式化程序,这对于不可变的对象是很好的实践。但是您应该真正使用System.nanoTime()而不是Duration表达式来最小化对基准结果的影响。为此,JMH通常更好。如果你在做了这些之后仍然认为你有一个性能问题,那么你可以试试我的lib time4j,它包含一个快速的格式,并使用chronoformatter分析引擎。
您是否尝试过:
1 2 3 4 5 6 7
| 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 );
} |
新的Java 8时间API具有无状态和不变的格式化程序。自定义格式化程序应该编译一次并存储在常量中(如DateTimeFormatter.ISO_INSTANT)。
- 请回顾一下我在底部已经提到过的我试图移动格式化程序成为一个班级成员的问题,它仍然至少需要16毫秒。
- 好吧,你所做的基准毫无意义。您是否认为格式化程序可能具有延迟初始化?你认为JVM需要预热吗?你需要做至少10公里的迭代而不记录任何时间戳。然后用一个时间戳进行10次迭代。在10公里的迭代中拆分时间范围。如果它仍然通过迭代为您提供16毫秒,那么我们将继续寻找解决方案。
- 另外,使用System.nanoTime()作为基准(或guava的Stopwatch)。
- 我不是那个标杆专家。我只知道包括jvm init等。每次运行程序时,我在Conosle的时间都是0-1毫秒。但就在我添加这3行代码时,执行时间跳到了16-18ms,这是非常确定的。