Thanks for reply Marko,

Sure!  I think the approach of making validation smarter and generating 
code for primitive types was the key. 

Actually when you ask me for benchmark the first time, the performance was 
terrible! 

If we have a look at how operation Filter is implemented:

*Filter operation*
https://github.com/wesovilabs/koazee/tree/master/internal/filter
We find 3 files (this is basically the same for all the operations)

In the filter.go, my input is a reflection type and obviously I am required 
to do a validation in order to avoid an uncontrolled *panic*

I guess my validation function is smarter than other libraries, Why? 
Because of I cache some info


func (op *Filter) validate() (*filterInfo, *errors.Error) {
   item := &filterInfo{}
   fnType := reflect.TypeOf(op.Func)
   if val := cache.get(op.ItemsType, fnType); val != nil {
      return val, nil
   //...... Validations for input
   item.fnInputType = fnIn.Type()
   cache.add(op.ItemsType, fnType, item)
   return item, nil
}


By this "smart cache" I avoid to evaluate eternally the same things. I mean,

If my stream contains string's and the filter func looks like func(string)bool 
I only evaluate once 

because the output will be always the same


The dispatcher.go has been generated. This has been generated from 
repository koazee-gen <https://github.com/wesovilabs/koazee-gen>

What do I achieve with this generated code? That my operation are applied 
over a function that will work with primitive values instead of doing it 
with reflection
For example,

func filterString(itemsValue reflect.Value, function interface{}) interface{} {
   input := itemsValue.Interface().([]string)
   output := make([]string, 0)
   fn := function.(func(string) bool)
   for i := 0; i < len(input); i++ {
      if fn(input[i]) {
         output = append(output, input[i])
      }
   }
   return output
}


Since I have a function for any primitive type (or pointers too) the 
performance doesn't suffer the reflection cost


I've also put a lot of effort to find the best way to do any operation with 
the best performance. 

For example, for reverse operation  I could do

func reverseInt16Ptr(itemsValue reflect.Value) interface{}{
   input := itemsValue.Interface().([]*int16)
   len := len(input)
   output := make([]*int16, len)
   for index := 0; index < len(input); index++ {
      output[index]= input[len-1-index]
   }
   return output
}



but my generated function looks like below

func reverseInt16Ptr(itemsValue reflect.Value) interface{}{
   input := itemsValue.Interface().([]*int16)
   len := len(input)
   output := make([]*int16, len)
   for index := 0; index < (len/2)+1; index++ {
      output[index], output[len-1-index] = input[len-1-index], input[index]
   }
   return output
}



I think is the best approach. I reduce a half the time of elements to be 
evaluated

I am learning a lot of Go (and enjoying too)  with all your requests and 
suggestions and to be honest is so valuable when you achieve good results.


On roadmap , I would like to publish a richer set of operations for v0.0.3 
(I know my provided set of operations is poor)  and for v0.0.4  find a way 
to improve the performance for complex structs (I got a idea..)





On Tuesday, December 4, 2018 at 9:05:52 AM UTC+1, Marko Ristin wrote:
>
> Thanks, Ivan! These numbers are very helpful! Could you at least give us a 
> hint why your library is faster than the other two? As far as I can see, 
> all three libraries in the benchmark use reflection.
>
> On Tue, 4 Dec 2018 at 08:49, Iván Corrales Solera <ivan.corra...@gmail.com 
> <javascript:>> wrote:
>
>> Hey all,
>>
>> I am working on Koazee, a library to deal with slices in a functional 
>> way. Since I published the very first release I was asked me for publishing 
>> a benchmark comparison with other existing and matured frameworks. that 
>> provide similar functionality. 
>>
>> I hope you find useful this article:  Koazee vs Go-Linq vs Go-Funk  
>> <https://medium.com/@ivan.corrales.solera/koazee-vs-go-funk-vs-go-linq-caf8ef18584e>
>>
>> -- 
>> You received this message because you are subscribed to the Google Groups 
>> "golang-nuts" group.
>> To unsubscribe from this group and stop receiving emails from it, send an 
>> email to golang-nuts...@googlegroups.com <javascript:>.
>> For more options, visit https://groups.google.com/d/optout.
>>
>

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to