Java - 循环性能下降

标签 java performance loops

场景是这样的......

我有两个函数 Function A() 和 Function B()。函数 A() 有一个 for 循环,在每次迭代中调用函数 B()。函数 B() 有一个 for 循环,迭代大约 1000 万次。

Function A()
{
    for (i = 0; i < 10; i++)
        Function B();
}

Function B()
{
    for (i = 0; i < 10000000; i++)
        certain_operations()
}

现在,我面临的问题是,A()的for循环的第一次迭代需要1分钟执行,第二次迭代需要2分钟,第三次迭代需要4分钟等等......即使数字迭代次数相同,A() 中的后续循环执行会增加。我生成了以下日志。

Cluster :  1
 INFO 2014-09-17 16:36:20,496 [pool-1-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-17 16:37:11,762 [pool-1-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-17 16:37:11,762 [pool-1-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 1 - Critical Operations : 160000

Cluster :  2
 INFO 2014-09-17 16:37:11,767 [pool-2-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-17 16:38:02,365 [pool-2-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-17 16:38:02,365 [pool-2-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 2 - Critical Operations : 40000

Cluster :  3
 INFO 2014-09-17 16:38:02,366 [pool-3-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-17 16:41:35,675 [pool-3-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-17 16:41:35,675 [pool-3-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 3 - Critical Operations : 80000

Cluster :  4
 INFO 2014-09-17 16:41:35,676 [pool-4-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-17 16:50:17,875 [pool-4-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-17 16:50:17,875 [pool-4-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 4 - Critical Operations : 120000

Cluster :  5
 INFO 2014-09-17 16:50:17,886 [pool-5-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-17 17:02:42,819 [pool-5-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-17 17:02:42,819 [pool-5-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 5 - Critical Operations : 160000

Cluster :  6
 INFO 2014-09-17 17:02:42,820 [pool-6-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-17 17:07:01,916 [pool-6-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-17 17:07:01,916 [pool-6-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 6 - Critical Operations : 40000

Cluster :  7
 INFO 2014-09-17 17:07:01,917 [pool-7-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-17 17:16:21,122 [pool-7-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-17 17:16:21,122 [pool-7-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 7 - Critical Operations : 100000

Cluster :  8
 INFO 2014-09-17 17:16:21,123 [pool-8-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-17 17:22:40,371 [pool-8-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-17 17:22:40,371 [pool-8-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 8 - Critical Operations : 60000

此处,Print 1 和 Print 2 之间的时间是函数 A() 的一次迭代的执行时间。

知道为什么会出现这个问题吗?关于如何解决此问题的建议将不胜感激。非常感谢。

这是我的代码,以防出现异常情况...

Function A()
{
    for(Data d : packList)              
            List<Data> region  = getRegionData(d, dataList, axisEN, eN, cluster++);         

            //dataList -> 10 million records
            //d -> single instance of dataList
}

public List<Data> getRegionData(Data data, List<Data> listData, int axisEN, int eN, int cluster)    //Function B()
    {   
        List<Data> region = new ArrayList<Data>();
        Data temp = new Data();
        int distance;

        Logger.sysLog(LogValues.info, this.getClass().getName(), "Print 1");
        for(Data d : listData)
        {
            temp.setOffnet(java.lang.Math.abs(data.getOffnet() - d.getOffnet()));
            temp.setOnnet(java.lang.Math.abs(data.getOnnet() - d.getOnnet()));
            temp.setInet(java.lang.Math.abs(data.getInet() - d.getInet()));

            distance = temp.getOffnet() + temp.getOnnet() + temp.getInet();

            if(distance <= eN)
                if(temp.getOffnet() <= axisEN && temp.getOnnet() <= axisEN && temp.getInet() <= axisEN)
                {                   
                    d.setId(listData.indexOf(d));
                    d.setCluster(cluster);
                    d.setDistance(distance);
                    d.setCount(d.getCount() + 1);
                    region.add(d);  
                }
        }



        Logger.sysLog(LogValues.info, this.getClass().getName(), "Print 2");
        Logger.sysLog(LogValues.info, this.getClass().getName(), "Cluster " + cluster + " : " + region.size());
        return region;
    }
}

。 .


编辑1:删除listData.indexOf(d)


 Cluster :  1
 INFO 2014-09-18 14:58:28,306 [pool-1-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-18 14:59:04,233 [pool-1-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-18 14:59:04,233 [pool-1-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 1  - Critical Operations : 120000
 Cluster :  2
 INFO 2014-09-18 14:59:04,236 [pool-2-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-18 15:01:32,566 [pool-2-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-18 15:01:32,566 [pool-2-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 2  - Critical Operations : 120000
 Cluster :  3
 INFO 2014-09-18 15:01:32,567 [pool-3-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-18 15:09:15,873 [pool-3-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-18 15:09:15,873 [pool-3-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 3  - Critical Operations : 200000
 Cluster :  4
 INFO 2014-09-18 15:09:15,874 [pool-4-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-18 15:13:30,019 [pool-4-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-18 15:13:30,019 [pool-4-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 4  - Critical Operations : 80000
 Cluster :  5
 INFO 2014-09-18 15:13:30,019 [pool-5-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-18 15:24:10,602 [pool-5-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-18 15:24:10,602 [pool-5-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 5  - Critical Operations : 160000
 Cluster :  6
 INFO 2014-09-18 15:24:10,603 [pool-6-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-18 15:29:47,132 [pool-6-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-18 15:29:47,132 [pool-6-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 6  - Critical Operations : 60000
 Cluster :  7
 INFO 2014-09-18 15:29:47,133 [pool-7-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 1
 INFO 2014-09-18 15:38:49,182 [pool-7-thread-1][] com.bng.dbscan.util.GenerateCluster - Print 2
 INFO 2014-09-18 15:38:49,182 [pool-7-thread-1][] com.bng.dbscan.util.GenerateCluster - Cluster 6  - Critical Operations : 60000

打印三次迭代的GC详细信息

After Iter1
Heap
 PSYoungGen      total 18432K, used 952K [0x9ee80000, 0xa0300000, 0xb3540000)
  eden space 15872K, 6% used [0x9ee80000,0x9ef6e248,0x9fe00000)
  from space 2560K, 0% used [0xa0080000,0xa0080000,0xa0300000)
  to   space 2560K, 0% used [0x9fe00000,0x9fe00000,0xa0080000)
 ParOldGen       total 41728K, used 0K [0x76140000, 0x78a00000, 0x9ee80000)
  object space 41728K, 0% used [0x76140000,0x76140000,0x78a00000)
 PSPermGen       total 16384K, used 1771K [0x72140000, 0x73140000, 0x76140000)
  object space 16384K, 10% used [0x72140000,0x722faf00,0x73140000)


After Iter2
Heap
 PSYoungGen      total 18432K, used 952K [0x9ef00000, 0xa0380000, 0xb35c0000)
  eden space 15872K, 6% used [0x9ef00000,0x9efee260,0x9fe80000)
  from space 2560K, 0% used [0xa0100000,0xa0100000,0xa0380000)
  to   space 2560K, 0% used [0x9fe80000,0x9fe80000,0xa0100000)
 ParOldGen       total 41728K, used 0K [0x761c0000, 0x78a80000, 0x9ef00000)
  object space 41728K, 0% used [0x761c0000,0x761c0000,0x78a80000)
 PSPermGen       total 16384K, used 1771K [0x721c0000, 0x731c0000, 0x761c0000)
  object space 16384K, 10% used [0x721c0000,0x7237af00,0x731c0000)


After Iter3
Heap
 PSYoungGen      total 18432K, used 952K [0x9ee80000, 0xa0300000, 0xb3540000)
  eden space 15872K, 6% used [0x9ee80000,0x9ef6e248,0x9fe00000)
  from space 2560K, 0% used [0xa0080000,0xa0080000,0xa0300000)
  to   space 2560K, 0% used [0x9fe00000,0x9fe00000,0xa0080000)
 ParOldGen       total 41728K, used 0K [0x76140000, 0x78a00000, 0x9ee80000)
  object space 41728K, 0% used [0x76140000,0x76140000,0x78a00000)
 PSPermGen       total 16384K, used 1771K [0x72140000, 0x73140000, 0x76140000)
  object space 16384K, 10% used [0x72140000,0x722faf00,0x73140000)

最佳答案

线索是listData.indexOf(d),它使算法复杂度呈二次方。
用简单的循环计数器替换 indexOf 并享受性能差异。

关于Java - 循环性能下降,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25904970/

相关文章:

java - 如何使用 Stream.flatmap 将被展平的对象与展平的对象组合起来

php - PHP Globals 的安全替代品(良好编码实践)

java - 5+5+5+5+5 和 5*5 哪个更快?

r - 在 R 中创建函数时循环将不起作用

javascript - 循环运行时浏览器卡住 (JavaScript)

c++ - 如何在C++中以交替顺序添加和减去用户输入

java - Kafka 9 KafkaConsumer multiple 似乎没有并行处理消息

java - 无法使用 Http put 方法将数据发送到 URL

java - JPA 2 + Criteria API - 定义子查询

performance - 提高标准矩阵乘法算法的效率?