Я написал mergeSort для многогранной версии go, а также написал тест производительности.Теперь я хочу использовать "go tool pprof" для анализа узкого места в моем коде.
Когда я получил профиль процессора, я использую "top10" в pprof, чтобы получить следующий вывод:
Showing nodes accounting for 4.73s, 98.54% of 4.80s total
Dropped 21 nodes (cum <= 0.02s)
Showing top 10 nodes out of 30
flat flat% sum% cum cum%
3.66s 76.25% 76.25% 3.66s 76.25% pingcap/talentplan/tidb/common/alg/sort.Merge
0.62s 12.92% 89.17% 0.64s 13.33% pingcap/talentplan/tidb/mergesort.prepare
0.17s 3.54% 92.71% 0.17s 3.54% runtime.freedefer
0.12s 2.50% 95.21% 0.14s 2.92% pingcap/talentplan/tidb/common/alg/sort.quickSort
0.10s 2.08% 97.29% 0.10s 2.08% runtime.memmove
0.03s 0.62% 97.92% 0.03s 0.62% runtime.memclrNoHeapPointers
0.03s 0.62% 98.54% 0.04s 0.83% runtime.stackpoolalloc
0 0% 98.54% 0.11s 2.29% pingcap/talentplan/tidb/common/alg/sort.MergeSortByMultiGoroutine
0 0% 98.54% 0.14s 2.92% pingcap/talentplan/tidb/common/alg/sort.QuickSort
0 0% 98.54% 4.04s 84.17% pingcap/talentplan/tidb/common/alg/sort.mergeSortByMultiGoroutine
Исходя из вышесказанного, я думаю, что любопытное узкое место находится в sort.Merge, поэтому я использую «list Merge», чтобы погрузиться в метод, и нахожу следующую информацию:
. . 50:func Merge(arr []int64, start int, mid int, end int, tmp []int64) {
. . 51: index, i, j := start, start, mid + 1
80ms 80ms 52: for ; i <= mid && j <= end; index++ {
180ms 180ms 53: if arr[i] <= arr[j] {
1.58s 1.58s 54: tmp[index] = arr[i]
50ms 50ms 55: i++
. . 56: } else {
1.52s 1.52s 57: tmp[index] = arr[j]
20ms 20ms 58: j++
. . 59: }
. . 60: }
. . 61: for ; i <= mid; index++ {
. . 62: tmp[index] = arr[i]
. . 63: i++
. . 64: }
. . 65: for ; j <= end; index++ {
. . 66: tmp[index] = arr[j]
. . 67: j++
. . 68: }
. . 69:
60ms 60ms 70: for i := start; i <= end; i++ {
170ms 170ms 71: arr[i] = tmp[i]
. . 72: }
. . 73:}
Что смущаетя здесь!В методе Merge есть 4 цикла for.Масштаб 1-го цикла for и 4-го цикла for примерно одинаков, и их задачей является перемещение элементов из одного слайса в другой.И проблема в том, почему 1-й цикл for стоит столько (1,58 с плюс 1,52 с), а 4-й цикл так мало (всего 170 мс)?Это нелогично!
Адрес этого проекта на github: https://github.com/Duncan15/talent-plan/tree/master/tidb/mergesort. Вы можете использовать "make pprof" для запуска теста производительности и получения профиля процессора и памяти.
IХотите знать, почему это происходит, если у вас есть время, пожалуйста, прочитайте мой код и дайте мне несколько советов.
спасибо, что сказали мне !!!
Я написал некоторый код, чтобы убедиться, чтокогда метод Merge выполняется в среде с одним рабочим циклом, стоимость 1-го цикла примерно одинакова с 4-м циклом, это кажется интуитивно понятным.Поэтому я думаю, может ли мультигорутинная среда вызывать вышеуказанное явление.Но в многогранной среде метод Merge запускается одновременно.Другими словами, 1-й цикл for и 4-й цикл for выполняются одновременно, если срез чтения и записи одновременно увеличит стоимость, стоимость 4-го цикла for также должна увеличиться, но из вывода pprof мы можем обнаружить, что только 1-й циклувеличение стоимости цикла for!
И я также пишу еще один тест, чтобы проверить мои мысли.Вы можете использовать «сделать ветеринар», чтобы запустить его.этот тест запускает метод Merge одновременно.Разница с mergeSort в мульти-версии программы заключается в том, что в этом тесте нет кода для сортировки, а просто код для слияния.И я неожиданно обнаружил, что в этом тесте стоимость 1-го цикла примерно такая же, как и у 4-го цикла.И вот, наконец, я полностью запутался!