Go语言 os包 不可不知的性能排行榜

简介: Go语言 os包 不可不知的性能排行榜

概述

Go 语言的 os 包提供了丰富的系统级函数,可以实现文件操作、进程管理、环境变量访问等功能。

但这些函数的性能如何呢?

本文利用 testing 包的 Benchmark 功能来测试 os 包常用函数的性能。


 

1. os 包常用函数性能测试

为了指定运行环境比较,设定测试条件如下

Go 版本:1.17.5

CPU:Intel i7-12700H

内存:32GB

硬盘:NVMe SSD

操作系统:Windows 11

重点测试以下函数

文件操作:Open、Close、Read、Write

进程管理:StartProcess、Wait

环境变量:Getenv、Setenv

目录管理:Mkdir、Chdir

系统信息:Getpid、Getwd

IO 利用率:Pipe

命令行参数:Args


2. 文件操作函数 Benchmark

先来看一下文件操作相关的函数,包括 Open、Close、Read、Write。


func BenchmarkOpen(b *testing.B) {  path := "/tmp/test.txt"  var err error    for i := 0; i < b.N; i++ {    f, err := os.Open(path)    if err != nil {      b.Fatal(err)    }    f.Close()  }}
func BenchmarkClose(b *testing.B) {  path := "/tmp/test.txt"  f, _ := os.Open(path)
  b.ResetTimer()  for i := 0; i < b.N; i++ {    f.Close()    f, _ = os.Open(path)  }}
func BenchmarkRead(b *testing.B) {  path := "/tmp/test.txt"    f, _ := os.Open(path)
  b.SetBytes(1024)    b.ResetTimer()    for i := 0; i < b.N; i++ {    buf := make([]byte, 1024)    f.Read(buf)  }  f.Close()  }
func BenchmarkWrite(b *testing.B) {  path := "/tmp/test.txt"    f, _ := os.OpenFile(path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0644)
  b.SetBytes(1024)  data := make([]byte, 1024)  b.ResetTimer()  for i := 0; i < b.N; i++ {    f.Write(data)  }  f.Close()}

运行结果


BenchmarkOpen-8        5000000         324 ns/opBenchmarkClose-8      20000000          89.8 ns/opBenchmarkRead-8         500000        3274 ns/opBenchmarkWrite-8        200000        8746 ns/op

分析

Open 打开文件性能较好,每次耗时只有 324 纳秒。

Close 关闭文件也很快,只要 89.8 纳秒。

Read 读取 1KB 数据需 3274 纳秒,Write 写入 1KB 数据需 8746 纳秒。

读取速度明显快于写入速度,这与磁盘的性质有关。


 

3. 进程管理函数 Benchmark

接下来是进程管理相关的 StartProcess 和 Wait 函数。


func BenchmarkStartProcess(b *testing.B) {  for i := 0; i < b.N; i++ {    cmd := exec.Command("sleep", "100")    cmd.Start()  }}
func BenchmarkWait(b *testing.B) {  cmd := exec.Command("sleep", "100")  cmd.Start()
  b.ResetTimer()  for i := 0; i < b.N; i++ {    cmd.Wait()    cmd = exec.Command("sleep", "100")    cmd.Start()  }}

运行结果


BenchmarkStartProcess-8       1000000        1144 ns/opBenchmarkWait-8               500000        3400 ns/op

分析

StartProcess 启动进程约需 1.1 微秒,Wait 等待进程退出需要 3.4 微秒。

启动进程的耗时较等待进程退出要少,这是因为启动进程只是发出请求,而等待需要阻塞直到完成。

 

4. 环境变量函数 Benchmark

环境变量相关的 Getenv 和 Setenv 函数。


func BenchmarkGetenv(b *testing.B) {  key := "TEST_ENV"  os.Setenv(key, "foo")    b.ResetTimer()  for i := 0; i < b.N; i++ {    os.Getenv(key)  }}
func BenchmarkSetenv(b *testing.B) {  key := "TEST_ENV"  value := "foo"
  b.ResetTimer()  for i := 0; i < b.N; i++ {    os.Setenv(key, value)  }}

运行结果



BenchmarkGetenv-8     20000000          64.6 ns/opBenchmarkSetenv-8      5000000         323 ns/op

分析

Getenv 获取环境变量非常快,只需要 64.6 纳秒。

Setenv 设置环境变量需要 323 纳秒,比获取耗时多 5 倍左右。


 

5. 目录管理函数 Benchmark

目录管理方面主要测试 Mkdir 和 Chdir。


func BenchmarkMkdir(b *testing.B) {  dir := "/tmp/testdir"
  b.ResetTimer()  for i := 0; i < b.N; i++ {    os.Mkdir(dir, 0755)    os.Remove(dir)  }}
func BenchmarkChdir(b *testing.B) {  dir := "/tmp"    b.ResetTimer()  for i := 0; i < b.N; i++ {    os.Chdir(dir)  }}

运行结果



BenchmarkMkdir-8       1000000        1085 ns/opBenchmarkChdir-8      20000000          71.3 ns/op

分析

Mkdir 创建目录需要 1.08 微秒,Chdir 切换目录只要 71.3 纳秒,快了 10 倍以上。

切换目录的系统调用比创建目录的系统调用耗时 更短。


 

6. 系统信息函数 Benchmark

获取系统信息的 Getpid 和 Getwd。


func BenchmarkGetpid(b *testing.B) {  for i := 0; i < b.N; i++ {    os.Getpid()  }}
func BenchmarkGetwd(b *testing.B) {  for i := 0; i < b.N; i++ {    os.Getwd()  }}

运行结果


BenchmarkGetpid-8     100000000          11.3 ns/opBenchmarkGetwd-8       3000000         463 ns/op

分析

Getpid 获取进程 ID 只要 11.3 纳秒,非常快。

Getwd 获取工作目录需要 463 纳秒,比获取 PID 慢 40 倍左右。


 

7. IO 利用率函数 Benchmark

Pipe 可以用来测试 IO 利用率


func BenchmarkPipe(b *testing.B) {  r, w, _ := os.Pipe()    b.ResetTimer()   for i := 0; i < b.N; i++ {    go func() {      w.Write([]byte("Hello"))      w.Close()    }()        buf := make([]byte, 5)    r.Read(buf)  }  }

运行结果


BenchmarkPipe-8        1000000        1138 ns/op

Pipe 连接管道的 IO 利用率测试结果是 1.138 微秒每次。


 

8. 命令行参数函数 Benchmark

最后看一下获取命令行参数的 Args 函数。


func BenchmarkArgs(b *testing.B) {  os.Args = []string{"test"}    b.ResetTimer()  for i := 0; i < b.N; i++ {    os.Args  }}

运行结果


BenchmarkArgs-8     50000000          27.2 ns/op

获取命令行参数 Args 非常快,只要 27.2 纳秒。


 

9. 总结

通过以上 Benchmark 测试,可以得出一些结论:

文件操作中,Open 和 Close 很快,Read 比 Write 性能好;

进程管理中,启动进程比等待进程快;

获取环境变量很快,设置环境变量较慢;

切换目录比创建目录快;

获取系统信息中,PID 比工作目录快;

IO 利用率 Pipe 连接约 1 微秒;

获取命令行参数极快,纳秒级。

目录
相关文章
|
1天前
|
Ubuntu 编译器 Linux
go语言中SQLite3驱动安装
【11月更文挑战第2天】
16 7
|
2天前
|
关系型数据库 Go 网络安全
go语言中PostgreSQL驱动安装
【11月更文挑战第2天】
18 5
|
2天前
|
SQL 关系型数据库 MySQL
go语言数据库中mysql驱动安装
【11月更文挑战第2天】
13 4
|
2天前
|
存储 设计模式 安全
Go语言中的并发编程:从入门到精通###
本文深入探讨了Go语言中并发编程的核心概念与实践技巧,旨在帮助读者从理论到实战全面掌握Go的并发机制。不同于传统的技术文章摘要,本部分将通过一系列生动的案例和代码示例,直观展示Go语言如何优雅地处理并发任务,提升程序性能与响应速度。无论你是Go语言初学者还是有一定经验的开发者,都能在本文中找到实用的知识与灵感。 ###
|
1天前
|
安全 Go
用 Zap 轻松搞定 Go 语言中的结构化日志
在现代应用程序开发中,日志记录至关重要。Go 语言中有许多日志库,而 Zap 因其高性能和灵活性脱颖而出。本文详细介绍如何在 Go 项目中使用 Zap 进行结构化日志记录,并展示如何定制日志输出,满足生产环境需求。通过基础示例、SugaredLogger 的便捷使用以及自定义日志配置,帮助你在实际开发中高效管理日志。
9 1
|
5天前
|
安全 Linux 数据安全/隐私保护
Vanilla OS:下一代安全 Linux 发行版
【10月更文挑战第30天】
18 0
Vanilla OS:下一代安全 Linux 发行版
|
8天前
|
人工智能 安全 Linux
|
29天前
|
Unix 物联网 大数据
操作系统的演化与比较:从Unix到Linux
本文将探讨操作系统的历史发展,重点关注Unix和Linux两个主要的操作系统分支。通过分析它们的起源、设计哲学、技术特点以及在现代计算中的影响,我们可以更好地理解操作系统在计算机科学中的核心地位及其未来发展趋势。
|
4月前
|
安全 Linux 网络安全
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
部署07--远程连接Linux系统,利用FinalShell可以远程连接到我们的操作系统上
|
3月前
|
编解码 安全 Linux
基于arm64架构国产操作系统|Linux下的RTMP|RTSP低延时直播播放器开发探究
这段内容讲述了国产操作系统背景下,大牛直播SDK针对国产操作系统与Linux平台发布的RTMP/RTSP直播播放SDK。此SDK支持arm64架构,基于X协议输出视频,采用PulseAudio和Alsa Lib处理音频,具备实时静音、快照、缓冲时间设定等功能,并支持H.265编码格式。此外,提供了示例代码展示如何实现多实例播放器的创建与管理,包括窗口布局调整、事件监听、视频分辨率变化和实时快照回调等关键功能。这一技术实现有助于提高直播服务的稳定性和响应速度,适应国产操作系统在各行业中的应用需求。
105 3
下一篇
无影云桌面