#go #profiling
#Вперед #профилирование
Вопрос:
Вопрос: Как определить время и профилировать раздел программы в golang с помощью go test
?
Пример использования: у меня есть алгоритм параллельной обработки массовых операций для дерева B . Я использую go test
для профилирования и сравнения с другими базовыми алгоритмами (сериализованная версия, пессимистическая блокировка и т.д.). Для настройки тестового примера я создам дерево B с 1 МЛН записей и создам список из 1 млн операций, затем я начну фактическое тестирование BulkProcess
этих операций.
func TestInputTreeM1e6N1e6(*testing.T) {
M := 1000000
//Test Preparation 1: Setup the tree
tree := NewTree(cmp)
file1name := "InitalTree_10000000.txt"
testF1, err := os.Open(file1name)
if err != nil {
panic(err)
}
defer testF1.Close()
nums, _ := ReadInts(testF1)
for i, num := range nums {
if i == M {
break
}
tree.Set(Int(num), Int(1))
}
fmt.Println("Tree initialized")
//Test Prepration 2: Initialize operations
N := 1000000
inputs := make([]SearchPair, N)
file2name := "Operations_10000000.txt"
testF2, err := os.Open(file2name)
if err != nil {
panic(err)
}
defer testF2.Close()
var opt string
var num int
var input SearchPair
for i:=0; i < N; i {
fmt.Fscanf(testF2, "%s %d", amp;opt, amp;num)
switch opt {
case "DEL":
input = SearchPair{
opt: DEL, //Operation to be applied
k: Int(num), //k to be operated upon
v: Int(0),
}
case "PUT":
input = SearchPair{
opt: PUT, //Operation to be applied
k: Int(num), //k to be operated upon
v: Int(-1),
}
case "SET":
input = SearchPair{
opt: SET, //Operation to be applied
k: Int(num), //k to be operated upon
v: Int(2),
}
}
inputs[i] = input
}
//Start actual testing
fmt.Println("Start processing...")
tree.BulkProcess(inputs)
fmt.Println("Done")
}
Проблема: я использую go test -v -cpuprofile cpu.out -memprofile mem.out
для профилирования BulkProcess
производительности, затем использую go tool pprof --pdf ConcurrentBPlusTree.test mem.out > mgraph.pdf
и go tool pprof --pdf ConcurrentBPlusTree.test cpu.out > cgraph.pdf
для визуализации результата.
Прямо сейчас go test
, похоже, выполняется профилирование всего тестового примера, включая построение дерева и построение операций. Файловый ввод-вывод во время настройки теста доминировал в производительности до такой степени, что я даже не мог видеть, что происходит в моем реальном тестировании.
Кроме того, go test имеет выходные строки, подобные этой
=== RUN TestInputTreeM1e6N1e6
--- PASS: TestInputTreeM1e6N1e6 (63.36s)
Возможно ли настроить таймер так, чтобы он показывал только время, затраченное на массовую обработку, а не на весь случай? Я знаю, что у b *testing.B
есть API, такие как b.ResetTimer()
и b.StopTimer()
. Существует ли аналогичный API для *testing.T
, чтобы я мог изменить поведение синхронизации?
Конкретный вопрос
- Как я могу использовать
go test
для профилирования только последних трех строк моего текущего тестового примера? - Как я могу использовать
go test
для определения времени только для последних трех строк моего текущего тестового примера?
Ответ №1:
Если вы не хотите профилировать всю программу, вы можете запускать и останавливать CPUProfile самостоятельно, используя runtime/pprof
пакет:
f, err := os.Create(profileFileName)
if err != nil {
log.Fatal("could not create CPU profile: ", err)
}
if err := pprof.StartCPUProfile(f); err != nil {
log.Fatal("could not start CPU profile: ", err)
}
defer pprof.StopCPUProfile()
Комментарии:
1. Возможно ли получить обработчик профиля процессора,
f
которыйgo test
был установлен для меня, чтобы мне нужно было только обернуть определенный раздел с помощьюStartCPUProfile(f)
иStopCPUProfile()
в моем тестовом примере, все еще используя тот жеgo test
CLI?2. @cookieisaac: нет, потому что
go test
уже будет запущен профиль процессора, и может быть запущен только один. Однако вы могли бы просто определить свой собственный флаг, т. Е.-testprofile