Scala和Go语言的TCP基准测试

我们写了一个简单的“ping-pong”客户端和服务器分别用go语言

//SERVER 


package main 


  


import ( 


    "net" 


    "runtime" 


) 


  


func handleClient(conn net.Conn) { 


    defer conn.Close() 


  


    var buf [4]byte 


    for { 


        n, err := conn.Read(buf[0:]) 


        if err!=nil {return} 


        if n>0 { 


            _, err = conn.Write([]byte("Pong")) 


            if err!=nil {return} 


        } 


    } 


} 


  


func main() { 


    runtime.GOMAXPROCS(4) 


  


    tcpAddr, _ := net.ResolveTCPAddr("tcp4", ":1201") 


    listener, _ := net.ListenTCP("tcp", tcpAddr) 


  


    for { 


        conn, _ := listener.Accept() 


        go handleClient(conn) 


    } 


} 
//CLIENT 


package main 


  


import ( 


    "net" 


    "fmt" 


    "time" 


    "runtime" 


) 


  


func ping(times int, lockChan chan bool) { 


    tcpAddr, _ := net.ResolveTCPAddr("tcp4", "localhost:1201") 


    conn, _ := net.DialTCP("tcp", nil, tcpAddr) 


  


    for i:=0; i<int(times); i++ { 


        _, _ = conn.Write([]byte("Ping")) 


        var buff [4]byte 


        _, _ = conn.Read(buff[0:]) 


    } 


    lockChan<-true 


    conn.Close()     


} 


  


func main() { 


    runtime.GOMAXPROCS(4) 


  


    var totalPings int = 1000000 


    var concurrentConnections int = 100 


    var pingsPerConnection int = totalPings/concurrentConnections 


    var actualTotalPings int = pingsPerConnection*concurrentConnections 


  


    lockChan := make(chan bool, concurrentConnections) 


  


    start := time.Now() 


    for i:=0; i<concurrentConnections; i++{ 


        go ping(pingsPerConnection, lockChan) 


    } 


    for i:=0; i<int(concurrentConnections); i++{ 


        <-lockChan  


    } 


    elapsed := 1000000*time.Since(start).Seconds() 


    fmt.Println(elapsed/float64(actualTotalPings)) 


} 

和Scala语言

//SERVER 


import java.net._ 


import scala.concurrent.ExecutionContext.Implicits.global 


import scala.concurrent._ 


  


object main{ 


  


    def handleClient(s: Socket) : Unit = { 


      val in = s.getInputStream 


      val out = s.getOutputStream 


      while(s.isConnected){ 


        val buffer = Array[Byte](4) 


        in.read(buffer) 


        out.write("Pong".getBytes) 


      } 


    } 


  


    def main(args: Array[String]){ 


      val server = new ServerSocket(1201) 


      while(true){ 


        val s: Socket = server.accept() 


        future { handleClient(s) } 


      } 


    } 


} 
//CLIENT 


import scala.concurrent._ 


import scala.concurrent.duration._ 


import scala.concurrent.ExecutionContext.Implicits.global 


import java.net._ 


  


object main{ 


  


    def ping(timesToPing: Int) : Unit = { 


        val socket = new Socket("localhost", 1201) 


        val out = socket.getOutputStream 


        val in = socket.getInputStream 


        for (i <- 0 until timesToPing) { 


            out.write("Ping".getBytes) 


            val buffer = Array[Byte](4) 


            in.read(buffer) 


        } 


        socket.close 


    } 


  


    def main(args: Array[String]){ 


        var totalPings = 1000000 


        var concurrentConnections = 100 


        var pingsPerConnection : Int = totalPings/concurrentConnections 


        var actualTotalPings : Int = pingsPerConnection*concurrentConnections 


  


        val t0 = (System.currentTimeMillis()).toDouble 


        var futures = (0 until concurrentConnections).map{_ =>  


            future(ping(pingsPerConnection)) 


        } 


  


        Await.result(Future.sequence(futures), 1 minutes) 


        val t1 = (System.currentTimeMillis()).toDouble 


        println(1000*(t1-t0)/actualTotalPings) 


    } 


} 

后者和   WebSockets vs. TCP benchmark一文中用到的完全一致。两者操作都很简单并有提升的空间。实际的测试代码中包括的功能性测试能处理一些连接错误,此处省略不作赘述。

客户端想服务器发出一系列持久并发的连接请求并且发送一定数量的ping(即字符串“Ping”)。服务器对每个“Ping”请求做出回应并回复“Pong”。

实验是在2.7G赫兹的四核苹果笔记本上演示的。客户端和服务器分别运行,以用来更好地测试程序运行的系统开销。

客户端能生成100个并发请求并发出100万次的ping到服务器端,并通过连接平均分布ping。我们测试了全程的“ping-pong”往返时间。

相关推荐