Scala vs. Go TCP Benchmark | 42 Engineering这篇文章对Scala和Go语言在Socket的TCP网络方面进行了一个比较测试。
GO语言代码:
//服务器端 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) } }
|
测试结果令人惊讶:Scala竟然好于Go语言:
Scala的平均往返时间1.6 microseconds (0.0016 milliseconds) 而 Go语言是 ~11 microseconds (0.011 milliseconds).
文章的意思:GO语言固然很快,但是如果你的软件是类似传递TCP包,那么在吞吐量上面这是就有区别出来了,作者言下之意好像是性能快是一个方面,吞吐量大也很重要,所谓吞吐量:是否能够一口吃个大胖子,还是一口只能吃个小鸡块。
Scala也为吞吐量付出代价,内存占用200MB,而GO只有10MB。
作者最后总结:GO语言还很新,有很多性能提升的地方,它的稳定且简单的并发原始模型可以弥补使上述一些缺陷。