Почему чтение и запись среза в многогорке стоят дорого? - PullRequest
0 голосов
/ 24 апреля 2019

Я написал 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-го цикла.И вот, наконец, я полностью запутался!

...