快排和堆排性能對比


之前經(jīng)常使用golang測試框架中的單元測試拴泌,一直沒用性能測試足绅,今天想熟悉一下golang的Benchmark順便給堆排和快排做個性能測試间聊,測試非常簡單,源代碼如下:

//sort.go
package mysort

import (
    "math/rand"
    "time"
)

func swap(nums []int, i, j int) {
    nums[i], nums[j] = nums[j], nums[i]
}

func parition(nums []int, start, end int) int {
    idx := rand.Int()%(end-start) + 1 + start
    swap(nums, idx, end)
    idx = end
    for start < end {
        for nums[start] <= nums[idx] && start < end {
            start++
        }
        for nums[end] >= nums[idx] && start < end {
            end--
        }
        swap(nums, start, end)
    }
    swap(nums, start, idx)
    return start
}

//quick sort
func QSort(nums []int, start, end int) {
    rand.Seed(time.Now().UnixNano())
    if start < end {
        p := parition(nums, start, end)
        QSort(nums, start, p-1)
        QSort(nums, p+1, end)
    }
}

//生成一個隨機的數(shù)組旁瘫,長度為len, 元素最大值不超過max
func GenRandSlice(len, max int) []int {
    rand.Seed(time.Now().UnixNano())
    a := make([]int, 0)
    for i := 0; i < len; i++ {
        a = append(a, rand.Int()%max)
    }
    return a
}

//堆排序
func left(i int) int {
    return i << 1
}

func right(i int) int {
    return i<<1 + 1
}

func maxHeapify(a []int, i int) {
    l := left(i)
    r := right(i)
    max := i
    aLen := len(a)
    if l < aLen && a[l] > a[max] {
        max = l
    }
    if r < aLen && a[r] > a[max] {
        max = r
    }
    if max != i {
        swap(a, i, max)
        maxHeapify(a, max)
    }
}

func BuildMaxHeap(a []int) {
    aLen := len(a)
    if aLen == 0 {
        return
    }
    for i := aLen/2 - 1; i >= 0; i-- {
        maxHeapify(a, i)
    }
}

func HeapSort(a []int) {
    BuildMaxHeap(a)
    aLen := len(a)
    tmp := a[:]
    for i := aLen - 1; i >= 1; i-- {
        swap(tmp, 0, i)
        tmp = tmp[:len(tmp)-1]
        maxHeapify(tmp, 0)
    }
}

測試文件為:

//sort_test.go
import (
    "testing"
)

func BenchmarkHeapSort(b *testing.B) {
    a := GenRandSlice(10000, 10000)
    for i := 0; i < b.N; i++ {
        HeapSort(a)
    }
}

func BenchmarkQSort(b *testing.B) {
    a := GenRandSlice(10000, 10000)
    for i := 0; i < b.N; i++ {
        QSort(a, 0, len(a)-1)
    }
}

測試命令:

go test -bench=.

goos: darwin
goarch: amd64
pkg: go_practice/algorithm/mysort
BenchmarkHeapSort-4         2000        914686 ns/op
BenchmarkQSort-4              10     120658646 ns/op
PASS
ok      go_practice/algorithm/mysort    3.269s

每ns快速排序執(zhí)行的操作遠(yuǎn)遠(yuǎn)高于堆排祖凫,相比較來說,快排確實高效酬凳。另外惠况,goalng的testing真是好用,各種想要的功能都有粱年。性能測試了售滤,還可以對cpu和mem做進(jìn)一步分析,詳細(xì)的指令可查看:

go test -h

這里只截取一部分


    -cpuprofile cpu.out
        Write a CPU profile to the specified file before exiting.
        Writes test binary as -c would.

    -memprofile mem.out
        Write an allocation profile to the file after all tests have passed.
        Writes test binary as -c would.

    -memprofilerate n
        Enable more precise (and expensive) memory allocation profiles by
        setting runtime.MemProfileRate. See 'go doc runtime.MemProfileRate'.
        To profile all memory allocations, use -test.memprofilerate=1.

    -mutexprofile mutex.out
        Write a mutex contention profile to the specified file
        when all tests are complete.
        Writes test binary as -c would.

    -mutexprofilefraction n
        Sample 1 in n stack traces of goroutines holding a
        contended mutex.

    -outputdir directory
        Place output files from profiling in the specified directory,
        by default the directory in which "go test" is running.

    -trace trace.out
        Write an execution trace to the specified file before exiting.

如執(zhí)行命令 go test -test.bench="BenchmarkHeapSort" -cpuprofile cpu.out,會得到兩個文件:
cpu.out mysort.test cpu.out是cpu采樣結(jié)果台诗,mysort.test是測試的二進(jìn)制文件完箩,使用命令go tool pprof mysort.test cpu.out可得到如下結(jié)果:

File: mysort.test
Type: cpu
Time: Feb 17, 2019 at 12:55pm (CST)
Duration: 2.06s, Total samples = 1.67s (80.90%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top10
Showing nodes accounting for 1.67s, 100% of 1.67s total
Showing top 10 nodes out of 16
      flat  flat%   sum%        cum   cum%
     1.06s 63.47% 63.47%      1.38s 82.63%  go_practice/algorithm/mysort.maxHeapify
     0.30s 17.96% 81.44%      0.30s 17.96%  go_practice/algorithm/mysort.swap (inline)
     0.12s  7.19% 88.62%      0.12s  7.19%  runtime.newstack
     0.08s  4.79% 93.41%      0.08s  4.79%  go_practice/algorithm/mysort.left (inline)
     0.05s  2.99% 96.41%      1.50s 89.82%  go_practice/algorithm/mysort.HeapSort
     0.04s  2.40% 98.80%      0.04s  2.40%  runtime.nanotime
     0.01s   0.6% 99.40%      0.14s  8.38%  go_practice/algorithm/mysort.BuildMaxHeap
     0.01s   0.6%   100%      0.01s   0.6%  runtime.kevent
         0     0%   100%      1.50s 89.82%  go_practice/algorithm/mysort.BenchmarkHeapSort
         0     0%   100%      0.12s  7.19%  runtime.morestack

再對QSort做測試:

go test -test.bench="BenchmarkQSort" -cpuprofile cpu.out

go tool pprof mysort.test cpu.out

File: mysort.test
Type: cpu
Time: Feb 17, 2019 at 12:58pm (CST)
Duration: 1.45s, Total samples = 1.16s (79.90%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top10
Showing nodes accounting for 1.16s, 100% of 1.16s total
Showing top 10 nodes out of 20
      flat  flat%   sum%        cum   cum%
     0.80s 68.97% 68.97%      0.80s 68.97%  math/rand.seedrand (inline)
     0.25s 21.55% 90.52%      1.05s 90.52%  math/rand.(*rngSource).Seed
     0.05s  4.31% 94.83%      0.05s  4.31%  runtime.nanotime
     0.03s  2.59% 97.41%      0.03s  2.59%  runtime.walltime
     0.02s  1.72% 99.14%      0.02s  1.72%  runtime.usleep
     0.01s  0.86%   100%      0.01s  0.86%  runtime.kevent
         0     0%   100%      1.08s 93.10%  go_practice/algorithm/mysort.BenchmarkQSort
         0     0%   100%      1.08s 93.10%  go_practice/algorithm/mysort.QSort
         0     0%   100%      1.05s 90.52%  math/rand.(*Rand).Seed
         0     0%   100%      1.05s 90.52%  math/rand.(*lockedSource).seedPos

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市拉队,隨后出現(xiàn)的幾起案子弊知,更是在濱河造成了極大的恐慌,老刑警劉巖粱快,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秩彤,死亡現(xiàn)場離奇詭異,居然都是意外死亡事哭,警方通過查閱死者的電腦和手機漫雷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來鳍咱,“玉大人降盹,你說我怎么就攤上這事“迹” “怎么了蓄坏?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長丑念。 經(jīng)常有香客問我涡戳,道長,這世上最難降的妖魔是什么脯倚? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任渔彰,我火速辦了婚禮,結(jié)果婚禮上挠将,老公的妹妹穿的比我還像新娘胳岂。我一直安慰自己,他們只是感情好舔稀,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布乳丰。 她就那樣靜靜地躺著,像睡著了一般内贮。 火紅的嫁衣襯著肌膚如雪产园。 梳的紋絲不亂的頭發(fā)上汞斧,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天,我揣著相機與錄音什燕,去河邊找鬼粘勒。 笑死,一個胖子當(dāng)著我的面吹牛屎即,可吹牛的內(nèi)容都是我干的庙睡。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼技俐,長吁一口氣:“原來是場噩夢啊……” “哼乘陪!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起雕擂,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤啡邑,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后井赌,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體谤逼,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年仇穗,在試婚紗的時候發(fā)現(xiàn)自己被綠了流部。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡纹坐,死狀恐怖贵涵,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情恰画,我是刑警寧澤,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布瓷马,位于F島的核電站拴还,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏欧聘。R本人自食惡果不足惜片林,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望怀骤。 院中可真熱鬧费封,春花似錦、人聲如沸蒋伦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽痕届。三九已至韧献,卻和暖如春末患,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背锤窑。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工璧针, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人渊啰。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓探橱,卻偏偏與公主長得像,于是被迫代替她去往敵國和親绘证。 傳聞我的和親對象是個殘疾皇子隧膏,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345