Use an aligned slice for file reads

This commit is contained in:
Kovid Goyal
2024-01-31 19:04:33 +05:30
parent de8c1e0206
commit 86a55e2c0a

View File

@@ -10,6 +10,7 @@ import (
"os" "os"
"strings" "strings"
"time" "time"
"unsafe"
"golang.org/x/sys/unix" "golang.org/x/sys/unix"
) )
@@ -31,9 +32,19 @@ func wait_for_file_to_grow(file_name string, limit int64) (err error) {
return return
} }
func aligned_slice(b []byte, alignment uintptr) []byte {
addr := uintptr(unsafe.Pointer(&b))
extra := addr & (alignment - 1)
if extra > 0 {
return b[alignment-extra:]
}
return b
}
func read_input(input_file *os.File, input_file_name string, input_channel chan<- input_line_struct, follow bool, count_carriage_returns bool) { func read_input(input_file *os.File, input_file_name string, input_channel chan<- input_line_struct, follow bool, count_carriage_returns bool) {
const buf_capacity = 8192 const buf_capacity = 8192
var buf_array [buf_capacity]byte var buf_storage [buf_capacity + 128]byte // ensure we have an 64 byte aligned slice with at least 64 bytes after it
buf := aligned_slice(buf_storage[:], 64)[:buf_capacity]
output_buf := strings.Builder{} output_buf := strings.Builder{}
output_buf.Grow(buf_capacity) output_buf.Grow(buf_capacity)
var err error var err error
@@ -92,10 +103,10 @@ func read_input(input_file *os.File, input_file_name string, input_channel chan<
for { for {
for err != nil { for err != nil {
n, err = input_file.Read(buf_array[:]) n, err = input_file.Read(buf)
if n > 0 { if n > 0 {
total_read += int64(n) total_read += int64(n)
process_chunk(buf_array[:n]) process_chunk(buf)
} }
if err == unix.EAGAIN || err == unix.EINTR { if err == unix.EAGAIN || err == unix.EINTR {
err = nil err = nil