Erlang/Java/Go threadring benchmark

10217 단어 자바erlangGo
shootout 이란 일련의 알고리즘 을 통 해 language performance 를 비교 하 는 것 을 말한다. 구체 적 으로 볼 수 있다. http://shootout.alioth.debian.org/
안에 많은 알고리즘 이 포함 되 어 있다.
 
[root@localhost bench]# ls
ackermann       except          harmonic     knucleotide   message      nsievebits   raytracer   reversefile   tcpecho
ary             fannkuch        hash         LICENSE       messagering  objinst      README      robots.txt    tcprequest
binarytrees     fannkuchredux   hash2        license.txt   meteor       partialsums  recursive   sieve         tcpsocket
chameneos       fasta           health       lists         methcall     pidigits     regexdna    spectralnorm  tcpstream
chameneosredux  fastaredux      heapsort     magicsquares  moments      primes       regexmatch  spellcheck    threadring
discovery       fibo            hello        mandelbrot    nbody        process      regexsub    strcat        wc
dispatch        flyweightstate  implicitode  matrix        nestedloop   prodcons     regsub      sumcol        wordfreq
echo            gifdeanim       Include      matrixnorm    nsieve       random       revcomp     takfp

 기본적으로 통용 되 는 언어 는 모두 포함 되 어 있다.
shootout 공식 테스트 기 계 는 ubuntu 이 고 kernel 은 3.0 입 니 다. arch 는 x86 one - core / x86 quad - core / x86 - 64 one - core / x86 - 64 quad - core 를 포함 하고 있 습 니 다. 각 arch 의 테스트 결 과 는 순위 가 약간 다 르 지만 모든 테스트 결 과 를 보면 일부 특징 을 발견 할 수 있 습 니 다.
1) 컴 파일 형 언어 는 가상 컴퓨터 언어 보다 속도 가 빠 르 지만 꼭 그렇지 는 않다.예 를 들 어 자바 7 은 Go 보다 어떤 테스트 에서 속도 가 더 좋다 (자바 이 는 JIT 가 있다).
2) 함수 형 언어 종합 순 위 는 보통 중간 에 있 고 나 쁘 지도 않 고 좋 지도 않다.
3) Fortran Intel 이 가장 빠 르 고 C / C + + 보다 빠 릅 니 다. 이것 은 뒤에 있 는 Intel 때 문 이 라 고 생각 합 니 다. Intel 의 c 컴 파일 러 는 gcc 보다 빠 릅 니 다.
4) P 시리즈 언어 (Perl / python / Ruby) 가 가장 느리다.나 는 nbody 가 Go, JavaPython 에 걸 리 는 시간 을 테스트 했다. Go 는 1m, Python 은 46m, 자바 는 가장 짧 은 40sec 를 소모 했다.
 
이상 의 결론 은 종합 순위 로 실제 테스트 결과 에 영향 을 주 는 요소 가 매우 많 고 같은 언어의 서로 다른 알고리즘 실현 도 순위 에 영향 을 미친다.
threadring 테스트 에 서 는 Erlang Hipe 가 1 위, haskell 이 2 위, Go 가 3 위 를 차지 했다.threadring 알고리즘 은 사실 매우 간단 합 니 다. 여기 서 Go / Erlang / 자바 의 threadring 실현 을 살 펴 보 겠 습 니 다.
 
package main

import (
        "flag"
        "fmt"
        "os"
)

var n = flag.Int("n", 1000, "how many passes")

const Nthread = 503

func f(i int, in <-chan int, out chan<- int) {
        for {
                n := <-in
                if n == 0 {
                        fmt.Printf("%d
", i) os.Exit(0) } out <- n - 1 } } func main() { flag.Parse() one := make(chan int) // will be input to thread 1 var in, out chan int = nil, one for i := 1; i <= Nthread-1; i++ { in, out = out, make(chan int) go f(i, in, out) } go f(Nthread, out, one) one <- *n <-make(chan int) // hang until ring completes }

 Go 에서 thread 는 goroutine 으로 시 뮬 레이 션 하여 503 개의 thread 를 하나의 링 링 으로 구성 하여 첫 번 째 thread 에 하나의 숫자 1000 을 보 냅 니 다. 각 thread 는 숫자 를 받 은 후에 다음 thread 에 전달 합 니 다. 숫자 가 0 으로 줄 어 들 때 까지.
이 go 프로그램 은 28sec (time. / 8. out - n 50000000) 를 소모 합 니 다.
이곳 의 go 버 전 threadring 은 shootout 공식 버 전이 아 닙 니 다. 여 기 는 google 의 go 구현 버 전 입 니 다. shootout 버 전 은 여기, 이곳 에 있 습 니 다.
 
Erlang 의 threadring 다시 보기:
 
-module(threadring).
-export([main/1, roundtrip/2]).

-define(RING, 503).

start(Token) ->
   H = lists:foldl(
      fun(Id, Pid) -> spawn(threadring, roundtrip, [Id, Pid]) end,
      self(),
      lists:seq(?RING, 2, -1)),
   H ! Token,
   roundtrip(1, H).

roundtrip(Id, Pid) ->
   receive
      1 ->
         io:fwrite("~b~n", [Id]),
         erlang:halt();
      Token ->
         Pid ! Token - 1,
         roundtrip(Id, Pid)
   end.

main([Arg]) ->
   Token = list_to_integer(Arg),
   start(Token).

Erlang 버 전의 threadring plain 은 17sec 로 go 버 전보 다 적 습 니 다. erlang smp 는 1m 정도 걸 립 니 다. (threadring 알고리즘 디자인 으로 인해 runquue 에서 하나의 running process 만 있 기 때문에 이 장면 에서 smp 는 장점 을 발휘 하지 못 하고 오히려 lock contention 으로 인해 성능 이 떨 어 집 니 다)
 
 
[root@localhost threadring]# time erl -smp disable -noshell -run threadring main 50000000                                           
292

real    0m17.290s
user    0m0.517s
sys     0m16.768s
[root@localhost threadring]# time erl -noshell -run threadring main 50000000             
292

real    1m9.036s
user    0m4.266s
sys     1m4.759s
 
다음은 자바 의 threadring:
 
import java.util.LinkedList;
import java.util.Queue;


public class threadring {
    public static void main(String[] args) {
        Node[] ring = new Node[503];
        for (int i=0; i<ring.length; i++) {
            ring[i] = new Node(i+1);
        }
        for (int i=0; i<ring.length; i++) {
            int nextIndex = (ring[i].label % ring.length);
            ring[i].next = ring[nextIndex];
        }
        int nHops = Integer.parseInt(args[0]);
        new Thread(new Consumer()).start();
        ring[0].sendMessage(nHops);
    }

    private static Queue<Node> q = new LinkedList<Node>();

    static class Consumer implements Runnable {

        public void run() {
            while (true) {
                try {
                    Node node;
                    node = q.poll();
                    if (node == null) {
                        //ignore, wait for some element
                        Thread.sleep(100);
                    } else {
                        node.run();
                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    static class Node implements Runnable {
        private final int label;
        private Node next;
        private int message;

        public Node(int label) {
            this.label = label;
        }

        public void sendMessage(int message) {
            this.message=message;
            q.add(this);
        }

        public void run() {
            //                System.out.println("after lock");
            if (message == 0) {
                System.out.println(label);
                System.exit(0);
            } else {
                next.sendMessage(message - 1);
            }
        }
    }
}

 
이 자바 버 전의 threadring 은 너무 간단 합 니 다. 하나의 Consumer 스 레 드 는 모든 Node 를 실행 합 니 다. Actor 모드 와 유사 하기 때문에 이 자바 프로그램 은 시간 이 매우 짧 고 약 2cec 입 니 다.
자바 에는 coroutine 같은 디자인 이 없 기 때문에 자바 는 실제 thread 로 threadring 을 모 의 하 는 것 이 더욱 설득력 이 있 습 니 다.
 
/**
 * The Computer Language Benchmarks Game
 * http://shootout.alioth.debian.org/
 * contributed by Klaus Friedel
 */

import java.util.concurrent.locks.LockSupport;

public class threadring {
  static final int THREAD_COUNT = 503;

  public static class MessageThread extends Thread {
    MessageThread nextThread;
    volatile Integer message;

    public MessageThread(MessageThread nextThread, int name) {
      super(""+name);
      this.nextThread = nextThread;
    }

    public void run() {
      while(true) nextThread.enqueue(dequeue());
    }

    public void enqueue(Integer hopsRemaining) {
      if(hopsRemaining == 0){
        System.out.println(getName());
        System.exit(0);
      }
      // as only one message populates the ring, it's impossible
      // that queue is not empty
      message = hopsRemaining - 1;
      LockSupport.unpark(this); // work waiting...
    }

    private Integer dequeue(){
      while(message == null){
        LockSupport.park();
      }
      Integer msg = message;
      message = null;
      return msg;
    }
  }

  public static void main(String args[]) throws Exception{
    int hopCount = Integer.parseInt(args[0]);

    MessageThread first = null;
    MessageThread last = null;
    for (int i = THREAD_COUNT; i >= 1 ; i--) {
      first = new MessageThread(first, i);
      if(i == THREAD_COUNT) last = first;
    }
    // close the ring:
    last.nextThread = first;

    // start all Threads
    MessageThread t = first;
    do{
      t.start();
      t = t.nextThread;
    }while(t != first);
    // inject message
    first.enqueue(hopCount);
    first.join(); // wait for System.exit
  }
}

 이 자바 프로그램 은 매우 오래 걸 립 니 다 (time 자바 - server threadring 50000000 )。

좋은 웹페이지 즐겨찾기