我写了一个小类,该类基本上从CSV文件中检索数据并将其加载到POJO对象中。由于我需要经常访问这些数据,因此我编写了一个singleton类,该类检查数据是否已存在于对象中,如果是,则直接从对象直接返回数据(而无需再次从文件中获取)。否则,它将从文件中检索数据并将数据存储在对象中以供将来查询。
在测试时,我注意到访问数据10,000次(大约是第一次从文件中加载数据)大约需要175毫秒。
让我吃惊的是,当我循环20,000次时,它只花了177毫秒(比10,000次多了2毫秒),而50,000次只花了197毫秒。
为什么要比50K更快地完成50K,这是为什么?为什么时间没有按比例增加?
为什么直接从对象访问数据要比从磁盘访问数据快得多(当我通过文件访问数据时,一次大约需要160毫秒)
谢谢
更新:
也许更令人困惑的是,当我尝试使用两个不同的键(需要从文件读取两次)访问对象时,与访问一次相比,它花费的时间大致相同(变化时间为1毫秒)。关于对象访问比文件访问快20万倍的所有解释仅解释了我的第一次观察,但是现在我实际上是从两个不同的文件中读取数据,但是我看不到花费的时间成比例地增加。>
换句话说,这样做:
for (int counter = 0; counter < 1; counter++) {
POJOObj.getInstance().getKey("Key1", "Val1");
}
花费的时间与此相同:
for (int counter = 0; counter < 1; counter++) {
POJOObj.getInstance().getKey("Key1", "Val1");
POJOObj.getInstance().getKey("Key1", "Val2"); // this requires new read from file
}
为什么时间没有成比例增加?
答案 0 :(得分:2)
与从内存中读取数据相比,从磁盘中读取文件要慢得多。有一个很好的资源叫做“ Latency Numbers Every Developer Should Know”,它解释了部分原因。从本质上讲,从磁盘读取1MB的速度比从主内存中读取相同的速度慢200,000倍。
关于为什么看到方法响应时间更快的原因-Hotspot(JVM的内部编译器)可能已启动。当您在Java中频繁执行方法时,JVM会在某个阈值后检测到它(我想说是大约1万次调用,但对此不信任我)并优化方法。它通过将您已执行的解释后的字节码转换为嵌入式程序集来实现。这要快得多,并且在后台进行。编写像您这样的微基准测试非常困难,并且有很多方法可以解决这个问题。如果您有兴趣进一步探索这些数字,请从Oracle上查看this resource的一些陷阱以及如何使用名为JMH的工具避免这些陷阱。