简单的数据流:与Java相比超级慢

As a Java dev, I'm currently looking at Go because I think it's an interesting language.

To start with it, I decided to take a simple Java project I wrote months ago, and re-write it in Go to compare performances and (mainly, actually) compare the code readability/complexity.

The Java code sample is the following:

public static void main(String[] args) {
    long start = System.currentTimeMillis();

    Stream<Container> s = Stream.from(new Iterator<Container>() {
        int i = 0;

        @Override
        public boolean hasNext() {
            return i < 10000000;
        }

        @Override
        public Container next() {
            return new Container(i++);
        }
    });

    s = s.map((Container _source) -> new Container(_source.value * 2));

    int j = 0;
    while (s.hasNext()) {
        s.next();
        j++;
    }

    System.out.println(System.currentTimeMillis() - start);

    System.out.println("j:" + j);
}

public static class Container {

    int value;

    public Container(int v) {
        value = v;
    }

}

Where the map function is:

return new Stream<R>() {
        @Override
        public boolean hasNext() {
            return Stream.this.hasNext();
        }

        @Override
        public R next() {
            return _f.apply(Stream.this.next());
        }
    };

And the Stream class is just an extension to java.util.Iterator to add custom methods to it. Other methods than map differs from standard Java Stream API.

Anyway, to reproduce this, I wrote the following Go code:

package main

import (
    "fmt"
)

type Iterator interface {
    HasNext() bool
    Next() interface{}
}

type Stream interface {
    HasNext() bool
    Next() interface{}
    Map(transformer func(interface{}) interface{}) Stream
}

///////////////////////////////////////

type incremetingIterator struct {
    i int
}

type SampleEntry struct {
    value int
}

func (s *SampleEntry) Value() int {
    return s.value
}

func (s *incremetingIterator) HasNext() bool {
    return s.i < 10000000
}

func (s *incremetingIterator) Next() interface{} {
    s.i = s.i + 1
    return &SampleEntry{
        value: s.i,
    }
}

func CreateIterator() Iterator {
    return &incremetingIterator{
        i: 0,
    }
}

///////////////////////////////////////
type stream struct {
    source Iterator
}

func (s *stream) HasNext() bool {
    return s.source.HasNext()
}

func (s *stream) Next() interface{} {
    return s.source.Next()
}

func (s *stream) Map(tr func(interface{}) interface{}) Stream {
    return &stream{
        source: &mapIterator{
            source:      s,
            transformer: tr,
        },
    }
}

func FromIterator(it Iterator) Stream {
    return &stream{
        source: it,
    }
}

///////////////////////////////////////
type mapIterator struct {
    source      Iterator
    transformer func(interface{}) interface{}
}

func (s *mapIterator) HasNext() bool {
    return s.source.HasNext()
}

func (s *mapIterator) Next() interface{} {
    return s.transformer(s.source.Next())
}

///////////////////////////////////////
func main() {

    it := CreateIterator()

    ss := FromIterator(it)

    ss = ss.Map(func(in interface{}) interface{} {
        return &SampleEntry{
            value: 2 * in.(*SampleEntry).value,
        }
    })

    fmt.Println("Start")
    for ss.HasNext() {
        ss.Next()
    }
    fmt.Println("Over")
}

Both producing the same result but when Java takes about 20ms, Go takes 1050ms (with 10M items, test ran several times).

I'm very new to Go (started couple of hours ago) so please be indulgent if I did something really bad :-)

Thank you!

查看全部
duanlijia5864
duanlijia5864
2017/03/16 17:54
  • iterator
  • java
  • performance
  • stream
  • 点赞
  • 收藏
  • 回答
    私信
满意答案
查看全部

3个回复