资讯专栏INFORMATION COLUMN

一次快速排序引发的jvm调优

DobbyKim / 3240人阅读

摘要:因为它是快速排序,所以我想小数据量并不能体现它的快速。正当我要运行程序并且统计其运行时间时,悲剧发生了这是一个堆内存溢出错误。

闲来无事,顺便写一个快排的代码。结果却引发了java.OutOfMemoryError:Java heap space。
首先谈谈快速排序,这是一种在统计上很快的排序,他的核心思想是,在一个数组中随便取一个数作为基准(通常取最后一个),然后把整个数组划分,把比基准小或等于的数放在基准之前,把大于基准的数放在基准之后。然后再分别对基准之前的数组和基准之后的数组进行快速排序。
java 代码:

void quicksort(int[] nums,int begin,int end)
    {
        if(end <= begin)return;
        int p = begin-1;
        for(int i = begin;i <= end;i++)
            if(nums[i] <= nums[end])
            {
                p++;
                int temp = nums[i];
                nums[i] = nums[p];
                nums[p] = temp;
            }
        quicksort(nums,begin,p-1);
        quicksort(nums,p+1,end);
    }

这里唯一难理解的就是这个p,这里的思想是,p及其左侧都是小于等于基准的数,而p的右侧都是大于基准的数。因此,遍历这个数组的时候,若数大于基准,则访问下一个,否则把p+1,然后交换p和这个位置上的数,这样就能成功划分。

因为它是快速排序,所以我想小数据量并不能体现它的快速。因此,我使用了一个很大的数组,并且使用随机数填充它。

Random random = new Random();
int[] nums = new int[ (1024*1024*1024) ];
for(int i = 0;i < nums.length;i++)
    nums[i] = random.nextInt(500000);

这个数组的大小是4个GB,因为一个int是4B,而1024*1024是1M,而1024M是1G。
正当我要运行程序并且统计其运行时间时,悲剧发生了!!!
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
这是一个堆内存溢出错误。
于是我立马想到一个解决方法,那就是扩大堆内存
数组大小只有4GB,我现在给JVM进程5000MB大小的堆内存,也就是大约4.8GB的内存,程序一定是没问题的了。于是我添加了参数-Xms5000m。这个参数的意义是,最小堆内存为5000MB。
然鹅,结果是
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
why???
要说明这个必须先知道java内存结构。
理解了java内存结构之后,才能明白。堆内存又分为,新生代(Young)和老年代(Old),而数组这种大对象一般是直接分配在老年代中。虽然我设置了5000MB的堆内存,但是这5000MB的内存并不都是给老年代的,老年代和新生代内存的默认比例是2,也就是说5000MB里只有2/3是老年代的,也就是3333MB≈3.25GB,这个大小仍然小于数组的4GB,因此现在我设置老-新比例为9,也就是老年代拥有5000MB*0.9=4500MB≈4.39GB,此时已经大于数组所需要的内存大小!
添加完参数-Xms5000m -XX:NewRatio=9后,我再次运行程序,运行成功!!!经过漫长的等待,输出了排序的时间为1443.11s,也就是大约24分钟!!!

最后,java 核心代码:

public static void main(String[] args) {
        Random random = new Random();

        int[] nums = new int[ (1024*1024*1024) ];
        for(int i = 0;i < nums.length;i++)
            nums[i] = random.nextInt(500000);
        long being = System.currentTimeMillis();
        quicksort(nums,0,nums.length-1);

        long end = System.currentTimeMillis();
        System.out.println(((double) (end-being))/1000+"s");



    }


   static void quicksort(int[] nums,int begin,int end)
    {
        if(end <= begin)return;
        int p = begin-1;
        for(int i = begin;i <= end;i++)
            if(nums[i] <= nums[end])
            {
                p++;
                int temp = nums[i];
                nums[i] = nums[p];
                nums[p] = temp;
            }
        quicksort(nums,begin,p-1);
        quicksort(nums,p+1,end);
    }

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/73299.html

相关文章

  • ​深度分析 | MyCat与DBLE对比性能调优

    作者简介 蓝寅,开源分布式中间件DBLE项目负责人;持续专注于数据库方面的技术, 始终在一线从事开发;对数据复制,读写分离,分库分表的有深入的理解与实践。 问题起因: 用benchmarksql_for_mysql对原生MyCat-1.6.1和DBLE-2.17.07版做性能测试对比,发现DBLE性能只到原生版MyCat的70%左右。 问题分析过程: 分析过程主要有以下内容:包括现象,收集数据,分...

    Mike617 评论0 收藏0
  • 【译】深入理解G1GC日志(一)

    摘要:表示允许垃圾收集线程处理本次垃圾收集开始前没有处理好的日志缓冲区,这可以确保当前分区的是最新的。垃圾收集线程在完成其他任务的时间展示每个垃圾收集线程的最小最大平均差值和总共时间。 本文翻译自:https://www.redhat.com/en/blog/collecting-and-reading-g1-garbage-collector-logs-part-2?source=auth...

    spacewander 评论0 收藏0
  • Java服务GC参数调优案例

    摘要:服务是通过进行反向代理的,设置的超时时间是,所以如果卡顿在以内就不会对成功率造成太大的影响。 本文介绍了一次生产环境的JVM GC相关参数的调优过程,通过参数的调整避免了GC卡顿对JAVA服务成功率的影响 背景以及遇到的问题 我们的Java HTTP服务属于OLTP类型,对成功率和响应时间的要求比较高,在生产环境中出现偶现的成功率突然下降然后又自动恢复的情况,如图所示: showImg...

    msup 评论0 收藏0

发表评论

0条评论

DobbyKim

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<