본문 바로가기
벤치마크

[Go] 파일 존재 여부에 대한 os.Stat() vs os.Open()

by dbadoy 2023. 2. 25.

os.Stat() vs os.Open()

일단, 위의 두 메서드는 사용처가 다르다. os.Stat()의 경우 파일에 대한 정보를 얻을 때 사용하며, os.File()의 경우, 파일을 컨트롤 할 때 사용한다.
내가 이 글에서 비교하고자 하는 상황은, 파일이 존재하는지 확인하는 경우이다.

결론

단순히 생각해보았을 때, 파일에 대한 정보만 가져오는 os.Stat()이 훨씬 빠를 것 같다. 실제로도 더 빠르다.

package test

import (
	"os"
	"testing"
)

func BenchmarkStatExistFile(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_, _ = os.Stat("./source")
	}
}

func BenchmarkOpenExistFile(b *testing.B) {

	for i := 0; i < b.N; i++ {
		_, _ = os.Open("./source")

	}
}

func BenchmarkStatNotExistFile(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_, _ = os.Stat("./sourceaaaaaa")
	}
}

func BenchmarkOpenNotExistFile(b *testing.B) {
	for i := 0; i < b.N; i++ {
		_, _ = os.Open("./sourceaaaaaa")
	}
}
BenchmarkStatExistFile-10                1000000               480.1 ns/op
BenchmarkOpenExistFile-10                1000000               567.5 ns/op
BenchmarkStatNotExistFile-10             1000000               483.3 ns/op
BenchmarkOpenNotExistFile-10             1000000               570.2 ns/op

os.Stat()이 더 빠르긴 하지만, 드라마틱하게 빠르진 않다. 약 18% 정도?

막연히 os.Stat()이 빠르다고 생각하던 이유는, os.File()은 직접 파일하고 연결되기 때문에, 파일 정보만 읽어오는 os.Stat()이 더 빠르겠다는 단순한 생각이었다.
하지만 os.File() 리턴값 자체는 파일에 접근할 File Descriptor만 넘어오기 때문에 그렇게 차이가 크지 않다.

그러한 점에서, 오히려 파일 정보를 변수에 담아 리턴하는 os.Stat() 메모리 할당량이 더 크다

type FileInfo interface {
	Name() string       // base name of the file
	Size() int64        // length in bytes for regular files; system-dependent for others
	Mode() FileMode     // file mode bits
	ModTime() time.Time // modification time
	IsDir() bool        // abbreviation for Mode().IsDir()
	Sys() any           // underlying data source (can return nil)
}

benchmark 메모리 할당값

BenchmarkStatExistFile-10                481.4 ns/op           272 B/op          3 allocs/op
BenchmarkOpenExistFile-10                554.6 ns/op            64 B/op          2 allocs/op
BenchmarkStatNotExistFile-10             509.7 ns/op           272 B/op          3 allocs/op
BenchmarkOpenNotExistFile-10             565.8 ns/op            64 B/op          2 allocs/op


아무튼… 결과적으로,

var err error
// case 1
_, err = os.File("./test.txt")
if os.IsNotExist(err) {
	// not exist
}

// case2
_, err = os.Stat("./test.txt")
if os.IsNotExist(err) {
	// not exist
}

위 두개는 굳이 성능을 생각하여 골라 쓸 필요는 없다고 생각된다. 굳이 굳이 성능적인 측면을 비교 해 보자면, 속도가 중요하면 os.Stat(), 메모리 절약이 중요하면 os.File()이 되겠다.

'벤치마크' 카테고리의 다른 글

[Go] strings.ToLower() vs bytes.ToLower()  (0) 2023.02.25