一次快速排序引發的jvm調優

閒來無事,順便寫一個快排的代碼。結果卻引發了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);
    }

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章