草庐IT

go - binary.Read 慢吗?

coder 2023-06-29 原文

我正在将一个旧的小型 C 项目重写成 Go(以学习 Go)。

该项目基本上从文件中读取一些二进制数据,对所述数据进行一些过滤,然后将其打印到标准输出中。

代码的主要部分如下所示(省略错误处理):

type netFlowRow struct {
    Timestamp uint32
    Srcip     [4]byte
    Dstip     [4]byte
    Proto     uint16
    Srcport   uint16
    Dstport   uint16
    Pkt       uint32
    Size      uint64
}

func main() {
    // ...
    file, _ := os.Open(path)
    for j := 0; j < infoRow.Count; j++ {
        netRow := netFlowRow{}
        binary.Read(file, binary.BigEndian, &netRow)

        // ...
        fmt.Printf("%v", netRow)
    }
}

在进行了天真的重写之后,go 版本的运行速度比 C 版本慢 10 倍(~40 秒对 2-3 秒)。我用 pprof 做了分析,它向我展示了这个:

(pprof) top10
39.96s of 40.39s total (98.94%)
Dropped 71 nodes (cum <= 0.20s)
Showing top 10 nodes out of 11 (cum >= 39.87s)
      flat  flat%   sum%        cum   cum%
    39.87s 98.71% 98.71%     39.87s 98.71%  syscall.Syscall
     0.09s  0.22% 98.94%     40.03s 99.11%  encoding/binary.Read
         0     0% 98.94%     39.87s 98.71%  io.ReadAtLeast
         0     0% 98.94%     39.87s 98.71%  io.ReadFull
         0     0% 98.94%     40.03s 99.11%  main.main
         0     0% 98.94%     39.87s 98.71%  os.(*File).Read
         0     0% 98.94%     39.87s 98.71%  os.(*File).read
         0     0% 98.94%     40.21s 99.55%  runtime.goexit
         0     0% 98.94%     40.03s 99.11%  runtime.main
         0     0% 98.94%     39.87s 98.71%  syscall.Read

我没看错吗? syscall.Syscall 基本上是主要的时间消费者吗?它是从文件中读取的地方吗?

更新。 我使用了 bufio.Reader 并获得了这个配置文件:

(pprof) top10
34.16s of 36s total (94.89%)
Dropped 99 nodes (cum <= 0.18s)
Showing top 10 nodes out of 33 (cum >= 0.56s)
      flat  flat%   sum%        cum   cum%
    31.99s 88.86% 88.86%        32s 88.89%  syscall.Syscall
     0.43s  1.19% 90.06%      0.64s  1.78%  runtime.mallocgc
     0.39s  1.08% 91.14%      1.06s  2.94%  encoding/binary.(*decoder).value
     0.28s  0.78% 91.92%      0.99s  2.75%  reflect.(*structType).Field
     0.28s  0.78% 92.69%      0.28s  0.78%  runtime.duffcopy
     0.24s  0.67% 93.36%      1.64s  4.56%  encoding/binary.sizeof
     0.22s  0.61% 93.97%     34.51s 95.86%  encoding/binary.Read
     0.22s  0.61% 94.58%      0.22s  0.61%  runtime.mach_semaphore_signal
     0.07s  0.19% 94.78%      1.28s  3.56%  reflect.(*rtype).Field
     0.04s  0.11% 94.89%      0.56s  1.56%  runtime.newobject

最佳答案

binary.Read 会比较慢,因为它使用了 reflection .我建议使用 bufio.Reader 进行基准测试并手动调用 binary.BigEndian 方法来读取您的结构:

type netFlowRow struct {
    Timestamp uint32   // 0
    Srcip     [4]byte  // 4
    Dstip     [4]byte  // 8
    Proto     uint16   // 12
    Srcport   uint16   // 14
    Dstport   uint16   // 16
    Pkt       uint32   // 18
    Size      uint64   // 22
}

func main() {
    // ...
    file, _ := os.Open(path)
    r := bufio.NewReader(file)
    for j := 0; j < infoRow.Count; j++ {
        var buff [4 + 4 + 4 + 2 + 2 + 2 + 4 + 8]byte
        if _, err := io.ReadFull(r, buff[:]); err != nil {
            panic(err)
        }
        netRow := netFlowRow{
            Timestamp: binary.BigEndian.Uint32(buff[:4]),
            // Srcip
            // Dstip
            Proto: binary.BigEndian.Uint16(buff[12:14]),
            Srcport: binary.BigEndian.Uint16(buff[14:16]),
            Dstport: binary.BigEndian.Uint16(buff[16:18]),
            Pkt: binary.BigEndian.Uint32(buff[18:22]),
            Size: binary.BigEndian.Uint64(buff[22:30]),
        }
        copy(netRow.Srcip[:], buff[4:8])
        copy(netRow.Dstip[:], buff[8:12])

        // ...
        fmt.Printf("%v", netRow)
    }
}

关于go - binary.Read 慢吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41400639/

有关go - binary.Read 慢吗?的更多相关文章

  1. ruby CSV : How can I read a tab-delimited file? - 2

    CSV.open(name,"r").eachdo|row|putsrowend我得到以下错误:CSV::MalformedCSVErrorUnquotedfieldsdonotallow\ror\n文件名是一个.txt制表符分隔文件。我是专门做的。我有一个.csv文件,我转到excel,并将文件保存为.txt制表符分隔的文件。所以它是制表符分隔的。CSV.open不应该能够读取制表符分隔的文件吗? 最佳答案 尝试像这样指定字段分隔符:CSV.open("name","r",{:col_sep=>"\t"}).eachdo|row|

  2. ruby - File.read ("| echo mystring") 是如何工作的? - 2

    我在我正在处理的一些代码中发现了这一点。它旨在解决从磁盘读取key文件的要求。在生产环境中,key文件的内容位于环境变量中。旧代码:key=File.read('path/to/key.pem')新代码:key=File.read('|echo$KEY_VARIABLE')这是如何工作的? 最佳答案 来自IOdocs:Astringstartingwith“|”indicatesasubprocess.Theremainderofthestringfollowingthe“|”isinvokedasaprocesswithappro

  3. ruby - 如何通过 Rubocop 指示打开 & :read as argument to File. - 2

    我有这个代码File.open(file_name,'r'){|file|file.read}但是Rubocop发出警告:Offenses:Style/SymbolProc:Pass&:readasargumenttoopeninsteadofablock.你是怎么做到的? 最佳答案 我刚刚创建了一个名为“t.txt”的文件,其中包含“Hello,World\n”。我们可以按如下方式阅读。File.open('t.txt','r',&:read)#=>"Hello,World\n"顺便说一下,由于第二个参数的默认值是'r',所以这样

  4. ruby - Chef : Read variable from file and use it in one converge - 2

    我有以下代码,它下载一个文件,然后将文件的内容读入一个变量。使用该变量,它执行一个命令。这个配方不会收敛,因为/root/foo在编译阶段不存在。我可以通过多个聚合和一个来解决这个问题ifFile.exist但我想用一个收敛来完成它。关于如何做到这一点有什么想法吗?execute'download_joiner'docommand"awss3cps3://bucket/foo/root/foo"not_if{::File.exist?('/root/foo')}endpassword=::File.read('/root/foo').chompexecute'join_domain'd

  5. Ruby:read_timeout 和 open_timeout 之间的区别 - 2

    标题本身就说明了......read_timeout和open_timeout之间有什么区别? 最佳答案 open_timeout是您愿意等待“打开连接”的时间。在TCP上下文中,在放弃尝试并引发超时错误之前等待握手完成的时间量。read_timeout您可能会猜到,是您愿意等待从连接方接收到某些数据的时间。一个例子可能会清楚地说明这一点:在SOAPoverHTTPoverTCP上下文中(简化):您尝试与服务器建立TCP连接。如果建立连接的时间比open_timeout长,则放弃连接尝试并引发/发出/返回超时错误。如果连接成功,您发

  6. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

  7. ruby - 如何强制 Rack :session + sinatra to read "rack.session" from params instead of cookies - 2

    我正在处理oauth1.0(twitter和flickr)。网站工作在80端口,oauth服务器工作在8080端口算法:向oauth服务器发送ajax请求以检查用户是否有有效的access_token如果用户没有access_token或access_token已过期,则打开授权窗口在oauth服务器的用户session中保存access_token发送分享数据到oauth服务器它使用sinatra+rack:session+rack::session::sequel+sqlite来存储session。它在每个响应中发送Set-Cookie:rack.session=id我正在使用2种

  8. ruby-on-rails - Rails 3 Cli 执行命令真的很慢吗? - 2

    有人知道为什么我的rails3.0.7cli这么慢吗?当我运行railss或railsg时,他大约需要5秒才能真正执行命令...有什么建议吗?谢谢 最佳答案 更新:我正在将我的建议从rrails切换到rails-sh,因为前者支持REPL,而rrails不是用例。此外,当与ruby​​环境结合使用时,修补似乎确实可以提高性能变量,现在反射(reflect)在答案中。一个可能的原因可能是这个performancebuginruby每当在ruby​​代码中使用“require”时,它就会调用一些代码(更多详细信息here)。在使用Rai

  9. ruby-on-rails - Rails 调试方法只输出 !binary 值 - 2

    我已尽我所能搜索互联网以解决此问题,但我完全被关键字!binary所吸引,因为搜索引擎(包括stackoverflow的内部搜索!)去掉了感叹号。我正在http://ruby.railstutorial.org学习Rails教程-这在很大程度上是一个很好的资源。我的application.html.erb页面底部有一个有用的东西:我被告知特定场景应该输出以下内容:---!map:ActiveSupport::HashWithIndifferentAccesscommit:Signinsession:!ActiveSupport::HashWithIndifferentAccesspas

  10. ruby - 简单的问题 : Read file, 在 Ruby 中反转它并写入另一个文件 - 2

    我有:o=File.new("ouput.txt","rw+")File.new("my_file.txt").lines.reverse_each{|line|?????line}o.close不知道用什么方法写入文件输出o 最佳答案 puts理解数组,因此您可以将其简化为:File.open("f2.txt","w"){|o|o.putsFile.readlines("f1.txt").reverse} 关于ruby-简单的问题:Readfile,在Ruby中反转它并写入另一个文件,

随机推荐