|
package main |
|
|
|
import ( |
|
"fmt" |
|
"github.com/stretchr/testify/assert" |
|
"github.com/stretchr/testify/require" |
|
"io/ioutil" |
|
"os" |
|
"path/filepath" |
|
"syscall" |
|
"testing" |
|
) |
|
|
|
func TestSpaseFileSize(t *testing.T) { |
|
dataDir, err := ioutil.TempDir("", "go-spase-test") |
|
require.Nil(t, err) |
|
t.Logf("dataDir %s", dataDir) |
|
defer os.RemoveAll(dataDir) |
|
err = os.MkdirAll(dataDir, os.ModePerm) |
|
if err != nil { |
|
panic(err) |
|
} |
|
|
|
f, err := os.OpenFile(dataDir+"/test", os.O_CREATE|os.O_RDWR|os.O_TRUNC, os.ModePerm) |
|
require.Nil(t, err) |
|
defer f.Close() |
|
|
|
stat, err := f.Stat() |
|
require.Nil(t, err) |
|
if syscallStat, ok := stat.Sys().(*syscall.Stat_t); ok { |
|
t.Logf("size=%d, blocks=%d, blksize=%d", syscallStat.Size, syscallStat.Blocks, syscallStat.Blksize) |
|
assert.Equal(t, int64(0), syscallStat.Size) |
|
assert.Equal(t, int64(0), syscallStat.Blocks) |
|
} |
|
|
|
_, err = f.WriteAt([]byte{1}, 10000) |
|
require.Nil(t, err) |
|
_ = f.Sync() |
|
|
|
stat, err = f.Stat() |
|
require.Nil(t, err) |
|
if syscallStat, ok := stat.Sys().(*syscall.Stat_t); ok { |
|
t.Logf("size=%d, blocks=%d, blksize=%d", syscallStat.Size, syscallStat.Blocks, syscallStat.Blksize) |
|
assert.Equal(t, int64(10001), syscallStat.Size) |
|
assert.Equal(t, int64(8), syscallStat.Blocks) |
|
} |
|
|
|
buff := make([]byte, 4096) |
|
_, err = f.WriteAt(buff, 0) |
|
require.Nil(t, err) |
|
_ = f.Sync() |
|
|
|
stat, err = f.Stat() |
|
require.Nil(t, err) |
|
if syscallStat, ok := stat.Sys().(*syscall.Stat_t); ok { |
|
t.Logf("size=%d, blocks=%d, blksize=%d", syscallStat.Size, syscallStat.Blocks, syscallStat.Blksize) |
|
assert.Equal(t, int64(10001), syscallStat.Size) |
|
assert.Equal(t, int64(16), syscallStat.Blocks) |
|
} |
|
} |
|
|
|
func BenchmarkStat1k(b *testing.B) { |
|
names, closer := initFiles(1000) |
|
defer closer() |
|
|
|
b.Run("syscall.Stat", benchSyscallStat(names)) |
|
b.Run("os.Stat", benchOsStat(names)) |
|
} |
|
|
|
func BenchmarkStat10k(b *testing.B) { |
|
names, closer := initFiles(10000) |
|
defer closer() |
|
|
|
b.Run("syscall.Stat", benchSyscallStat(names)) |
|
b.Run("os.Stat", benchOsStat(names)) |
|
} |
|
|
|
func benchSyscallStat(names []string) func(b *testing.B) { |
|
return func(b *testing.B) { |
|
var totalBlocks int64 |
|
for i := 0; i < b.N; i++ { |
|
var stat syscall.Stat_t |
|
for _, name := range names { |
|
err := syscall.Stat(name, &stat) |
|
if err != nil { |
|
panic(err) |
|
} |
|
totalBlocks += stat.Blocks |
|
} |
|
} |
|
} |
|
} |
|
|
|
func benchOsStat(names []string) func(b *testing.B) { |
|
return func(b *testing.B) { |
|
var totalBlocks int64 |
|
for i := 0; i < b.N; i++ { |
|
for _, name := range names { |
|
stat, err := os.Stat(name) |
|
if err != nil { |
|
panic(err) |
|
} |
|
syscallStat := stat.Sys().(*syscall.Stat_t) |
|
totalBlocks += syscallStat.Blocks |
|
} |
|
} |
|
} |
|
} |
|
|
|
func initFiles(numFiles int) ([]string, func() error) { |
|
dataDir, err := ioutil.TempDir("", "go-stat-bench") |
|
if err != nil { |
|
panic(err) |
|
} |
|
|
|
names := make([]string, numFiles) |
|
for i := 0; i < numFiles; i++ { |
|
name := filepath.Join(dataDir, fmt.Sprintf("%5d", i)) |
|
names[i] = name |
|
f, err := os.Create(name) |
|
if err != nil { |
|
panic(err) |
|
} |
|
err = f.Close() |
|
if err != nil { |
|
panic(err) |
|
} |
|
} |
|
return names, func() error { |
|
return os.RemoveAll(dataDir) |
|
} |
|
} |