thoas / go-funk

A modern Go utility library which provides helpers (map, find, contains, filter, ...)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Let's discuss performance

christian-blades-cb opened this issue · comments

I was curious what the performance impact is of your functional implementation vs the classic implementations. I haven't gone in depth, but the results are interesting (in particular the memory allocations for Contains.)

➜  funk-bench git:(master) ✗ go test -benchmem -bench .
testing: warning: no tests to run
BenchmarkContains/Idiomatic-8               1000           1946239 ns/op               0 B/op          0 allocs/op
BenchmarkContains/funk-8                       2         645429814 ns/op        28916552 B/op    3614564 allocs/op
PASS
ok      github.com/christian-blades-cb/funk-bench       4.417s
commented

Hay :)

I haven't done the benchmark yet, but it doesn't surprise me since the reflect API relies on allocations, however it's in my TODO

commented

I have added a performance section in the README, you are totally right on this point we must bring this subject on the table and also provide typesafe solutions (less flexible).

commented

Typesafe implementations are on the way, I will add more benchmarks bit by bit.

Wow! You've been busy! Excellent work.

I'd love to explore why using reflection has so many more allocations, 10 minutes on google wasn't enlightening. Would make a good article.

@christian-blades-cb, would doing some memory profiling with the -runtime flag shed some light on the allocation churn?

@thoas I have implemented a way to avoid the cost of reflect.Value

https://github.com/json-iterator/go/blob/master/feature_reflect.go

The general idea only rely on reflect.Type to assemble your function logic through composition. Then working with raw unsafe.Pointer directly. Essentially, interface{} is a reflect.Type + raw pointer.