Вот это нижнее меню с кодом мне отчего-то не доступно. Только верхний пример. Вместо большого Вашего списка вижу выбор из двух элементов "изображение" и "формула". Ничего больше в меню по "/" не появляется. :(
С этим как раз разобрался. fmt.Sprintf() делает 1 аллокацию в стандартном логере. Ещё 2 аллокации "прошиты" в runtime.Caller() который дергают все логеры, если хотят сообщать имя файла, функции и/или номер строчки. Вывод стек трейса потребует ещё нескольких усилий..
Это к вопросу является ли zap зеро аллокейт логером? :)
Я отлаживал иной код, но поскольку он очень похож на стандартный логгер в этой части, то обнаружив, что "пример адекватен" привел его. Забавно тут то, что буфер, прошитый внутри структуры логера, делает его не реентерабельным и требует блокировку мьютексом от начала формирования сообщения до самого конца, так ещё и то, что поверхностный прогон бенчмарков (для того, кто не в теме) покажет что все крайне кучеряво!
Попробовал выбросить буфер из структуры, делая выделение памяти явно .. получил не менее интересные результаты! Всего выделено памяти: 1160байт (буфер 1024, Sprintf берет 16) .. кому остальное? И, кстати, без походов в runtime.Caller() имею ... 3 аллокации "лишних"! .. это простите "кому"? ;)
Можете попробовать самостоятельно: копируете код логера к себе, убираете из него поле buf, и выделяете буфер явно, типа make([]byte, 0, 1024) .. скажем там, где buf = buf[:0] -- "очистка слайса". Можно в иных местах, результат тот же. :(
Возможно. Но тогда аллокация есть, но в бенчмарке ее нет .. проверка:
go test -bench=. -benchtime=1x -count=1 -benchmem
результат:
Benchmark_Stdlog-4 1 48051 ns/op 616 B/op 8 allocs/op
Собственно похоже, что бенчмарк выдает усредненное количество по прогонам, но раз буфер не растет (сообщение одно), то и среднее кол-во аллокаций стремится к нулю. Вывод: доверять бенчмаркам в этой части нельзя, если используется переиспользование чего-либо. Не влезая внутрь кода - никак. :(
Но, спасибо. Этот вопрос понятен.
Появился новый: откуда из 8 штук? append растит буфер 4 раза: 8,16,32,64 .. длина сообщения 41 символ. Sprintf() делает 1 аллокацию в 16 байт.. :)
Откуда ещё 3 аллокации?
Хотите сказать, что он настолько умен, что сам способен посчитать сколько байт надо под буфер динамически формируемого сообщения? Не, такое возможно, допускаю.Т.к. настройка логгера задается в тесте константно, какие поля он будет выводить - статически определимо, выводимое сообщение тоже константа .. но я сильно сомневаюсь, что компилятор Go настолько умен. ;)
Тут больше похоже на кривизну бенчмаркинга в Go, что сразу множит на ноль все бенчмарки разного рода замеров, типа "во, наш логер зеро-аллокатор".. ;)
Там ещё одна проблема, но задам ее отдельно. Решил протестить escape-алгоритм Go и .. тоже получил весьма странный результат. Но это позже. Может сам разберусь.