为什么 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 倍?
解决方法
您正在将苹果与橙子进行比较。
至少有两个方法错误:
您的 perl 咒语测量
cat
如何读取文件并通过pipe(2) 发送其内容
,而perl
从那里读取数据,对其进行处理并将结果写入其标准输出。你的围棋咒语
- 测量 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
并进行测量:
构建代码:
$ go build chomp.go
生成输入文件:
$ for i in $(seq 1 600000);执行 echo server$((random%800+100)),$random,$random,$random;完成 >sample.csv
运行 perl 代码:
$ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; } real 0m0.226s user 0m0.102s sys 0m0.048s
登录后复制再次运行它以确保它已从文件系统缓存中读取输入文件:
$ time { perl -ne 'chomp; print "$_";' <sample.csv >out1.txt; } real 0m0.123s user 0m0.090s sys 0m0.033s
登录后复制注意执行时间是如何减少的。
在缓存的输入上运行 go 代码:
$ time { ./chomp <sample.csv >out2.txt; } real 0m0.063s user 0m0.032s sys 0m0.032s
登录后复制-
确保结果相同:
$ cmp out1.txt out2.txt
如您所见,在我的带有 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 run
的可用性可能使它看起来如此。事实上,它执行正常 go build
会执行的操作,然后运行生成的可执行文件,然后将其丢弃。🎜您可能会想说 perl 也处理“源代码”,但 perl 解释器针对处理脚本和 go 的构建工具链进行了高度优化——同时与大多数其他编译语言相比速度快得惊人——未针对此进行优化。
可能更明显的区别是,perl 解释器实际上解释您的(非常简单的)脚本,而 chomp
和 print
是所谓的“内置函数”,很容易提供给由解释器执行脚本。与构建 go 程序相比,编译器解析源代码文件并将其转换为机器代码,链接器实际上读取 go 标准库的编译包的文件 - 所有这些都是 import
ed, - 从它们,组合所有这些机器代码并写出一个可执行图像文件(这很像 perl
二进制文件本身!);当然,这是一个非常消耗资源的过程,与实际的程序执行无关。
以上是为什么 Go 中读写文件比 Perl 慢很多?的详细内容。更多信息请关注PHP中文网其他相关文章!

热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

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

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

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

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

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

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

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

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