测量执行时间的常用技术提供了不同的值(java)

测量执行时间的常用技术提供了不同的值(java),java,time,set,execution,Java,Time,Set,Execution,我试图测量不同类型集合上不同操作的时间,并想对它们进行比较,但在同一类型集合上得到的值差别很大,比如因子1000。我使用我在这里读到的常用技巧: 我比较了Hashset、TreeSet和LinkedHashSet。 我用1000000个整数填充这些集合,使用methode contains()并遍历这些集合。我测量了每次手术的时间,数值差别很大。因此,我第二次使用相同类型的新集合执行此操作,而我得到的执行时间似乎不合法 同一类型的集合需要填充1400毫秒,然后填充300毫秒。为什么呢 下面是一个

我试图测量不同类型集合上不同操作的时间,并想对它们进行比较,但在同一类型集合上得到的值差别很大,比如因子1000。我使用我在这里读到的常用技巧:

我比较了Hashset、TreeSet和LinkedHashSet。 我用1000000个整数填充这些集合,使用methode contains()并遍历这些集合。我测量了每次手术的时间,数值差别很大。因此,我第二次使用相同类型的新集合执行此操作,而我得到的执行时间似乎不合法

同一类型的集合需要填充1400毫秒,然后填充300毫秒。为什么呢

下面是一个代码示例,它可以让我更清楚地理解我的意思:

    public static void main(String[] args){

    HashSet<Integer> firstHashSet = new HashSet<>(predefinedSize);
    HashSet<Integer> secondHashSet = new HashSet<>(predefinedSize);
    LinkedHashSet<Integer> firstLinkedHashSet = new LinkedHashSet<>(predefinedSize);
    LinkedHashSet<Integer> secondLinkedHashSet = new LinkedHashSet<>(predefinedSize);
    TreeSet<Integer> firstTreeSet = new TreeSet<>();
    TreeSet<Integer> secondTreeSet = new TreeSet<>();
    int x = 9432;
    System.out.println("filling hashSet:        <" + fillSet(firstHashSet) + "> milliSeconds");
    System.out.println("filling linkedSet:      <" + fillSet(firstLinkedHashSet) + "> milliSeconds");
    System.out.println("filling treeSet:        <" + fillSet(firstTreeSet) + "> milliSeconds");
    System.out.println("-------------------------------------------------------------");
    System.out.println("filling hashSet:        <" + fillSet(secondHashSet) + "> milliSeconds");
    System.out.println("filling linkedSet:      <" + fillSet(secondLinkedHashSet) + "> milliSeconds");
    System.out.println("filling treeSet:        <" + fillSet(secondTreeSet) + "> milliSeconds");
publicstaticvoidmain(字符串[]args){
HashSet firstHashSet=新的HashSet(预定义大小);
HashSet secondHashSet=新的HashSet(预定义大小);
LinkedHashSet firstLinkedHashSet=新LinkedHashSet(预定义大小);
LinkedHashSet secondLinkedHashSet=新LinkedHashSet(预定义大小);
TreeSet firstTreeSet=新树集();
TreeSet secondTreeSet=新树集();
int x=9432;
System.out.println(“填充哈希集:毫秒”);
System.out.println(“填充链接集:毫秒”);
System.out.println(“填充树集:毫秒”);
System.out.println(“------------------------------------------------------------------”;
System.out.println(“填充哈希集:毫秒”);
System.out.println(“填充链接集:毫秒”);
System.out.println(“填充树集:毫秒”);
这是我的一个填充集的外观:

private static int size = 1000000;
private static int predefinedSize = 2000000;

public static double fillSet(LinkedHashSet<Integer> myHashSet){
    double timeStart = System.nanoTime();
    for(int i=0; i<size; i++){
        myHashSet.add(i);
    }
    double time = (System.nanoTime() - timeStart)/ Math.pow(10, 6);
    return time;
}
private static int size=1000000;
私有静态int预定义大小=2000000;
公共静态双填充集(LinkedHashSet myHashSet){
double timeStart=System.nanoTime();

对于(int i=0;i,正如@kan的评论所提到的,使用系统计时器并执行一百万次将提供各种各样的结果。您正在寻找的是一个微基准:

至于你的时间安排到处都是的原因,你必须仔细阅读计算机体系结构和Java JVM。一些可能性:

  • 处理器中的动态时钟速度技术-您可以通过关闭CPU改变时钟速度的功能来消除这种可能性
  • 您的集合有100万个Int类型的元素,即4 MiB。鉴于非服务器CPU将有1到8 MiB的缓存,因此该大小大约是它是否适合处理器缓存的极限。如果在一次执行中,您的100万个元素在缓存中的停留时间比在另一次执行中的要长,您将得到一个非常好的结果不同的执行时间。您可以通过将集合设置为非常小,完全适合缓存(最多几十KB),或者设置为非常大,根本无法与缓存一起工作(可能是100 MB),来消除这种可能性
  • 您可能没有运行任何其他应用程序,但您的计算机上仍有其他东西在后台运行。(防病毒、更新服务、10-20个与操作系统内部工作相关的其他任务)
  • Java虚拟机的行为可能会有所不同(这一点我不能太确定,因为我不擅长JIT、GC和其他可能影响执行时间的东西的内部工作)。微基准库将在很大程度上消除这种可能的差异

可能垃圾收集器在填充数据时正在运行,因此时间不同。现在打开一些其他应用程序,如chrome、explorer、photoshop或任何游戏,然后检查基准测试,你就会知道有什么问题。确保打开繁重的任务,然后使用相同的应用程序对低处理器和高处理器执行相同的检查,然后你会得到太多的答案要创建错误的基准,请使用以下方法:
filling hashSet:        <52.14022> milliSeconds
filling linkedSet:      <95.599435> milliSeconds
filling treeSet:        <2172.773956> milliSeconds
-------------------------------------------------------------
filling hashSet:        <59.096929> milliSeconds
filling linkedSet:      <1006.638126> milliSeconds
filling treeSet:        <241.36395> milliSeconds