Aproveitando o post do Elton Minetto (Testando o generics do Go), onde ele fez um benchmark comparando uma função escrita sem generics e uma com, nesse post vamos dar continuidade na análise que ele fez fazendo um profile de memória e passando a flag -benchmem.
O código utilizado foi exatamente o mesmo que o Elton utilizou em seus testes.
Se você não viu o post dele, deixo abaixo as duas funções utilizadas. A primeira foi copiada do package samber/lo utilizando generics, enquanto a segunda foi implementada pelo próprio Elton.
package main
import (
"fmt"
)
func main() {
s := []string{"Samuel", "Marc", "Samuel"}
names := Uniq(s)
fmt.Println(names)
names = UniqGenerics(s)
fmt.Println(names)
i := []int{1, 20, 20, 10, 1}
ids := UniqGenerics(i)
fmt.Println(ids)
}
//from https://github.com/samber/lo/blob/master/slice.go
func UniqGenerics[T comparable](collection []T) []T {
result := make([]T, 0, len(collection))
seen := make(map[T]struct{}, len(collection))
for _, item := range collection {
if _, ok := seen[item]; ok {
continue
}
seen[item] = struct{}{}
result = append(result, item)
}
return result
}
func Uniq(collection []string) []string {
result := make([]string, 0, len(collection))
seen := make(map[string]struct{}, len(collection))
for _, item := range collection {
if _, ok := seen[item]; ok {
continue
}
seen[item] = struct{}{}
result = append(result, item)
}
return result
}
E para o benchmark, foram feitas 3 funções bem simples.
package main
import (
"testing"
"github.com/bxcodec/faker/v3"
)
var names []string
func BenchmarkMain(m *testing.B) {
for i := 0; i < 1000; i++ {
names = append(names, faker.FirstName())
}
}
func BenchmarkNormalUniq(b *testing.B) {
_ = Uniq(names)
}
func BenchmarkGenericsUniq(b *testing.B) {
_ = UniqGenerics(names)
}
Ao executar o go test -bench=. -cpu 8 -benchtime 100x -memprofile mem.prof -benchmem podemos ver que tive um resultado muito similar ao dele.

Três coisas me agradaram muito nesse benchmark. Em primeiro lugar, a diferença de nano segundos por operação (ns/op) não é muito grande. Já em segundo e terceiro lugar, ambas funções consumiram a mesma quantidade de bytes por operação (B/op) e fizeram a mesma quantidade de alocações por operação (allocs/op).
Isso mostra que em tempo de execução, quando falamos de consumo de recurso, uma função com generics consome exatamente a mesma coisa que qualquer função “comum”.
Para fechar, vamos dar uma conferida em como ficou o profile de memória.

E vejam só que coisa mais linda! Ao serem executadas, ambas funções consumiram exatamente a mesma quantidade de memória, ou seja… VEM GENERICS!!!!!!
Deixem suas dúvidas nos comentário.
Até a próxima!
Faça parte da comunidade!
Receba os melhores conteúdos sobre Go, Kubernetes, arquitetura de software, Cloud e esteja sempre atualizado com as tendências e práticas do mercado.
Livros Recomendados
Abaixo listei alguns dos melhores livros que já li sobre GO.





[…] Benchmark: Generics unique vs Unique […]
[…] Benchmark: Generics unique vs Unique […]