目录
问题内容
解决方法
首页 后端开发 Golang 为什么 Go 中读写文件比 Perl 慢很多?

为什么 Go 中读写文件比 Perl 慢很多?

Feb 09, 2024 pm 09:30 PM
标准库

为什么 Go 中读写文件比 Perl 慢很多?

为什么 Go 中读写文件比 Perl 慢很多?这是很多开发者在使用这两种编程语言时经常遇到的问题。在这篇文章中,php小编草莓将为您解答这个问题。在比较 Go 和 Perl 读写文件的速度时,我们需要考虑到两个关键因素:语言特性和底层实现。Go 语言在文件读写方面的设计理念与 Perl 不同,这导致了它们在性能上的差异。同时,底层实现也是影响读写速度的重要因素。接下来,我们将详细分析这些因素,帮助您更好地理解为什么 Go 中读写文件比 Perl 慢很多。

问题内容

我使用go是为了提高代码效率,但是当我使用go读写文件时,发现它的读写效率没有perl高。是我代码的问题还是其他原因?

构建输入文件:

# input file:
for i in $(seq 1 600000) do     echo server$((random%800+100)),$random,$random,$random >> sample.csv done
登录后复制

用perl读写文件:

time cat sample.csv | perl -ne 'chomp;print"$_"' > out.txt
登录后复制
real    0m0.249s
user    0m0.083s
sys 0m0.049s
登录后复制

使用 go 读写文件:

package main

import (
    "bufio"
    "fmt"
    "io"
    "os"
    "strings"
)

func main() {

    filepath := "./sample.csv"
    file, err := os.openfile(filepath, os.o_rdwr, 0666)
    if err != nil {
        fmt.println("open file error!", err)
        return
    }
    defer file.close()
    buf := bufio.newreader(file)
    for {
        line, err := buf.readstring('\n')
        line = strings.trimspace(line)
        fmt.println(line)
        if err != nil {
            if err == io.eof {
                fmt.println("file read ok!")
                break
            } else {
                fmt.println("read file error!", err)
                return
            }
        }
    }
}
登录后复制

然后我运行:

time go run read.go > out.txt
登录后复制
real    0m2.332s
user    0m0.326s
sys 0m2.038s
登录后复制

为什么 go 的读写速度比 perl 慢近 10 倍?

解决方法

您正在将苹果与橙子进行比较。

至少有两个方法错误:

  1. 您的 perl 咒语测量 cat 如何读取文件并通过 pipe(2) 发送其内容,而 perl 从那里读取数据,对其进行处理并将结果写入其标准输出。

  2. 你的围棋咒语

    • 测量 go 工具链的完整构建过程(包括编译、链接和写出可执行映像文件)然后运行 已编译程序的组成部分,以及
    • 测量对标准输出的无缓冲写入(fmt.print* 调用),而在 perl 代码中写入标准输出 - 引用 文档 - “如果输出到终端,通常可以进行行缓冲,否则进行块缓冲。”

让我们尝试比较一下苹果。

首先,这是一个类似的 go 实现:

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "os"
)

func main() {
    in := bufio.newscanner(os.stdin)
    out := bufio.newwriter(os.stdout)

    for in.scan() {
        s := bytes.trimspace(in.bytes())

        if _, err := out.write(s); err != nil {
            fmt.fprint(os.stderr, "failed to write file:", err)
            os.exit(1)
        }
    }

    if err := out.flush(); err != nil {
        fmt.fprint(os.stderr, "failed to write file:", err)
        os.exit(1)
    }

    if err := in.err(); err != nil {
        fmt.fprint(os.stderr, "reading failed:", err)
        os.exit(1)
    }
}
登录后复制

让我们将其保存为 chomp.go 并进行测量:

  1. 构建代码:

    $ go build chomp.go

  2. 生成输入文件:

    $ for i in $(seq 1 600000);执行 echo server$((random%800+100)),$random,$random,$random;完成 >sample.csv

  3. 运行 perl 代码:

    $ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; }
    
    real    0m0.226s
    user    0m0.102s
    sys 0m0.048s
    登录后复制
  4. 再次运行它以确保它已从文件系统缓存中读取输入文件:

    $ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; }
    
    real   0m0.123s
    user   0m0.090s
    sys    0m0.033s
    登录后复制

    注意执行时间是如何减少的。

  5. 在缓存的输入上运行 go 代码:

    $ time { ./chomp <sample.csv >out2.txt; }
    
    real   0m0.063s
    user   0m0.032s
    sys    0m0.032s
    登录后复制
  6. 确保结果相同:

    $ cmp out1.txt out2.txt

  7. 如您所见,在我的带有 ssd 的 linux/amd64 系统上,结果大致相同。

    嗯,我还应该指出,为了获得合理的结果,您需要运行每个命令,例如 1000 次,并对每个批次中的结果进行平均,然后比较这些数字,但我认为这足以证明什么您的方法存在的问题是。

    还有一件事需要考虑:这两个程序的运行时间绝大多数由文件系统 i/o 主导,因此,如果您认为 go 会更快,那么您的期望是没有根据的:这两个程序大部分时间sleep 在内核的系统调用 read(2)read(2)write(2)write(2)。在某些涉及 cpu 运算的情况下,go 程序可能比 perl 程序更快(特别是如果它是为利用多核系统而编写的),但您的示例根本不是这种情况。

    哦,只是为了明确未说明的事实:虽然 go 语言规范没有说明 aot,而 go run 是一种针对一次性一次性演出的 hack,go run 是一种针对一次性一次性演出的 hack,严肃的工作,也不执行任何严重复杂程度的代码。简而言之,go-that-you-are-using 并不是一种解释性语言,尽管 go run 的可用性可能使它看起来如此。事实上,它执行正常 go build

    严肃的工作,也不执行任何严重复杂程度的代码。简而言之,go-that-you-are-using 并不是一种解释性语言,尽管 go run 的可用性可能使它看起来如此。事实上,它执行正常 go build 会执行的操作,然后运行生成的可执行文件,然后将其丢弃。🎜

    您可能会想说 perl 也处理“源代码”,但 perl 解释器针对处理脚本和 go 的构建工具链进行了高度优化——同时与大多数其他编译语言相比速度快得惊人——未针对此进行优化。
    可能更明显的区别是,perl 解释器实际上解释您的(非常简单的)脚本,而 chompprint 是所谓的“内置函数”,很容易提供给由解释器执行脚本。与构建 go 程序相比,编译器解析源代码文件并将其转换为机器代码,链接器实际上读取 go 标准库的编译包的文件 - 所有这些都是 imported, - 从它们,组合所有这些机器代码并写出一个可执行图像文件(这很像 perl 二进制文件本身!);当然,这是一个非常消耗资源的过程,与实际的程序执行无关。

    以上是为什么 Go 中读写文件比 Perl 慢很多?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
3 周前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您听不到任何人,如何修复音频
3 周前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

c++中绝对值怎么用 c++中绝对值怎么用 May 06, 2024 pm 06:15 PM

C++ 中获取绝对值的方法有两种:1. 使用内置函数 abs(),获取整型或浮点型的绝对值;2. 使用泛型函数 std::abs(),获取各类支持绝对值运算数据类型的绝对值。

c++中std::怎么用 c++中std::怎么用 May 09, 2024 am 03:45 AM

std 是 C++ 中包含标准库组件的命名空间。为了使用 std,需要使用 "using namespace std;" 语句。直接使用 std 命名空间中的符号可以简化代码,但建议仅在需要时使用,以避免命名空间污染。

python怎么弹出窗口 python怎么弹出窗口 May 05, 2024 pm 08:15 PM

在 Python 中弹出窗口可以使用两种方法:Tkinter:使用 Tkinter 库创建 Tk 或 TopLevel 窗口小部件。Pyglet:使用 Pyglet 库创建 Window 窗口。

c++中fabs是什么意思 c++中fabs是什么意思 May 08, 2024 am 01:15 AM

fabs() 函数是 C++ 中的一个数学函数,用于计算浮点数的绝对值,去除负号并返回正值。它接受一个浮点参数,并返回一个 double 类型的绝对值。例如,fabs(-5.5) 将返回 5.5。该函数适用于浮点数,其精度受底层硬件影响。

c++中prime什么意思 c++中prime什么意思 May 07, 2024 pm 11:33 PM

prime 是 C++ 中的关键字,表示质数类型,只能被 1 和本身整除,用作布尔类型指示给定值是否为质数,为质数则为 true,否则为 false。

_complex在c语言中的用法 _complex在c语言中的用法 May 08, 2024 pm 01:27 PM

complex 类型用于表示 C 语言中的复数,包含实部和虚部。其初始化形式为 complex_number = 3.14 + 2.71i,实部可通过 creal(complex_number) 访问,虚部可通过 cimag(complex_number) 访问。该类型支持常用的数学运算,如加、减、乘、除和取模。此外,还提供了一组用于处理复数的函数,如 cpow、csqrt、cexp 和 csin。

config在java中什么意思 config在java中什么意思 May 07, 2024 am 02:39 AM

Config 在 Java 中表示配置信息,用于调整应用程序行为,通常存储在外部文件中或数据库中,可通过 Java Properties、PropertyResourceBundle、Java Configuration Framework 或第三方库进行管理,其好处包括解耦、灵活性、环境意识、可管理性、可扩展性。

c++中min是什么意思 c++中min是什么意思 May 08, 2024 am 12:51 AM

C++ 中的 min 函数可返回多个值中的最小值。其语法为:min(a, b),其中 a 和 b 为要比较的值。还可以指定一个比较函数,以支持不支持 < 运算符的类型。C++20 引入了 std::clamp 函数,可处理三个或更多值的最小值。

See all articles