Skip to content

Latest commit

 

History

History
121 lines (89 loc) · 3.56 KB

File metadata and controls

121 lines (89 loc) · 3.56 KB

Отчет по оптимизации

Начальные показатели

go test -bench=BenchmarkSlow -benchmem

Итераций Времени, ns/op Памяти, B/op Аллокаций ,allocs/op
88 13 505 000 18 393 863 182 838

Запустим BenchmarkSlow с профилированием по cpu и mem

GOGC=off go test -bench=BenchmarkSlow -cpuprofile cpu.out -memprofile mem.out

cpu

go tool pprof hw3.test cpu.out

(pprof) list SlowSearch

Нагрузку создают операции со строками:

  • 60ms json.Unmarshal
  • 40ms, 30ms regexp.MatchString
  • 20ms ioutil.ReadAll
  • 10ms regexp.MustCompile
  • 10ms foundUsers += fmt.Sprintf
  • 10ms strings.Split

(pprof) web

  • Судя по графу горячие места связаны с регулярными выражениями.

mem

space

go tool pprof hw3.test mem.out

(pprof) alloc_space

(pprof) list SlowSearch

Замечаем:

  • 839.78MB, 538.58MB regexp.MatchString
  • 125.35MB ioutil.ReadAll
  • 63.32MB strings.Split
  • 52.03MB json.Unmarshal
  • 21.06MB fmt.Sprintf

(pprof) web

  • regexp
  • MatchString
  • Compile
  • syntax Parse
  • json Unmarshal
  • ioutil ReadAll

objects

(pprof) alloc_objects (pprof) list SlowSearch

  • 7 115 884, 6 435 062 regexp.MatchString("Android", browser)
  • 4 090 149 json.Unmarshal
  • 196 614 user := make(map[string]interface{})
  • 114 688 email := r.ReplaceAllString(user["email"].(string), " [at] ")
  • 78 501 foundUsers += fmt.Sprintf("[%d] %s <%s>\n", i, user["name"], email)
  • 3 277 r := regexp.MustCompile("@")
  • 1 714 ioutil.ReadAll(file)

(pprof) web

  • regexp
  • MatchString
  • Compile
  • syntax Parse
  • json Unmarshal

Оптимизация

Циклично пользуемся:

GOGC=off go test -bench . -benchmem -cpuprofile cpu.out -memprofile mem.out

go tool pprof -http=:8083 hw3.test cpu.out go tool pprof hw3.test cpu.out

последовательно исправляя горячие места:

json.Unmarshal

Заменим на easyjson

regexp.MatchString

  • Заменим на strings.Contains
  • Объединим 2 цикла for по browsers в 1

ioutil.ReadAll

ioutil.ReadAll и lines заменим на bufio.NewScanner и построчный Scan()

foundUsers +=

  • заменим на strings.Builder.WriteString()
  • пишем сразу в вывод

seenBrowsers := []string{}

т.к нам нужно только число уникальных браузеров используем set map[string]struct{}

избавляемся от преобразования []byte в []string т.к оно избыточно для easyjson

regexp.MustCompile("@")

замена на email = [2]string(strings.Split(user.Email, "@"))

не парсим ненужные поля в json

Результат

Поправив горячие места получаем:

Итераций Времени, ns/op Памяти, B/op Аллокаций ,allocs/op
BenchmarkSlow-10 86 12 431 961 18 042 795 182 723
BenchmarkFast-10 1208 910 658 543 401 7083