2KB项目,专业的源码交易网站 帮助 收藏 每日签到

Scala 和 Go 语言的 TCP 基准测试

  • 时间:2019-01-23 18:40 编辑:2KB 来源:2KB.COM 阅读:379
  • 扫一扫,手机访问
  • 分享
摘要:
Scala Go 英文原文:Scala vs. Go TCP Benchmark

最近我们需要一些带有些特殊特征的负载平衡器。现成可取并不是我们想要的获取此类特征的途径。

因此我们着手调研怎样才能写出我们自己的软件负载平衡器。由于我们的大部分代码库和专业知识都基于Scala,所以基于java虚拟机来创建此平衡器是个自然之选。

另一方面,很多人,也包括在 Fortytwo的我们自己——经常但不总是——会做一些毫无根据的假设,即JAVA虚拟机比本地编译语言要慢。

由于负载平衡器常是性能极其关键的组件,因此可能一个其他的编程语言/环境会比较好些?

我们不是很乐意走入奇特的世界写C/C++,所以我们开始找寻一种折中的方法,既可以给我们带来传说中的本地代码的性能优势,同时也具有一些高级的特性,如垃圾回收以及内置的并发原语。一个立即浮现出来的这样的语言是Google的相对较新的Go语言。本机编译而且完美内置了并发构造。是不是很完美?

Go vs Scala

我们决定与最近的WebSockets和TCP发送 相似的时髦方法,在Go 和 Scala基础之上,对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”往返时间。

令我们吃惊的是, Scala比Go好的不止一点,平均往返时间约1.6微秒 (0.0016毫秒)对比于Go的 约11微妙 (0.011毫秒). Go的数字当然仍然是相当的快,但如果所有软件在做的都是接收一个tcp包,再传递给另一个终点,这样就会在最大吞吐量方面带来很大的差异。

相反的需要注意的是,Go服务器具有的内存封装仅仅是10MB,而Scala将近200MB。

Go仍然很新,随着它的成熟可能会有性能的改进,而且它的简单的并发原语可能使付出这些性能的损失是值得的。
尽管如此,这个结果实在有点令人惊讶,至少对我们是如此。我们想在评论中听到一些关于此的想法。

本文中的所有译文仅用于学习和交流目的,转载请务必注明文章译者、出处、和本文链接。 2KB翻译工作遵照 CC 协议,如果我们的工作有侵犯到您的权益,请及时联系我们。


2KB项目(www.2kb.com,源码交易平台),提供担保交易、源码交易、虚拟商品、在家创业、在线创业、任务交易、网站设计、软件设计、网络兼职、站长交易、域名交易、链接买卖、网站交易、广告买卖、站长培训、建站美工等服务

  • 全部评论(0)
资讯详情页最新发布上方横幅
最新发布的资讯信息
【计算机/互联网|】Nginx出现502错误(2020-01-20 21:02)
【计算机/互联网|】网站运营全智能软手V0.1版发布(2020-01-20 12:16)
【计算机/互联网|】淘宝这是怎么了?(2020-01-19 19:15)
【行业动态|】谷歌关闭小米智能摄像头,因为窃听器显示了陌生人家中的照片(2020-01-15 09:42)
【行业动态|】据报道谷歌新闻终止了数字杂志,退还主动订阅(2020-01-15 09:39)
【行业动态|】康佳将OLED电视带到美国与LG和索尼竞争(2020-01-15 09:38)
【行业动态|】2020年最佳AV接收机(2020-01-15 09:35)
【行业动态|】2020年最佳流媒体设备:Roku,Apple TV,Firebar,Chromecast等(2020-01-15 09:31)
【行业动态|】CES 2020预览:更多的流媒体服务和订阅即将到来(2020-01-08 21:41)
【行业动态|】从埃隆·马斯克到杰夫·贝佐斯,这30位人物定义了2010年代(2020-01-01 15:14)
联系我们

Q Q: 7090832

电话:400-0011-990

邮箱:7090832@qq.com

时间:9:00-23:00

联系客服
商家入住 服务咨询 投拆建议 联系客服
0577-67068160
手机版

扫一扫进手机版
返回顶部