Commit 18ff28f7 authored by Han-Wen Nienhuys's avatar Han-Wen Nienhuys

Use fixed buffer for response header data.

This saves one alloc per request.
parent 88db6cd5
......@@ -242,8 +242,8 @@ func (ms *MountState) handleRequest(req *request) {
errNo := ms.write(req)
if errNo != 0 {
log.Printf("writer: Write/Writev %v failed, err: %v. opcode: %v",
req.outHeaderBytes, errNo, operationName(req.inHeader.Opcode))
log.Printf("writer: Write/Writev failed, err: %v. opcode: %v",
errNo, operationName(req.inHeader.Opcode))
}
}
......@@ -253,7 +253,7 @@ func (ms *MountState) write(req *request) Status {
return OK
}
req.serialize()
header, data := req.serialize()
if ms.Debug {
log.Println(req.OutputDebug())
}
......@@ -262,16 +262,14 @@ func (ms *MountState) write(req *request) Status {
req.preWriteNs = time.Now().UnixNano()
}
if req.outHeaderBytes == nil {
if header == nil {
return OK
}
var err error
if req.flatData == nil {
_, err = ms.mountFile.Write(req.outHeaderBytes)
if data == nil {
_, err = ms.mountFile.Write(header)
} else {
_, err = Writev(int(ms.mountFile.Fd()),
[][]byte{req.outHeaderBytes, req.flatData})
_, err = Writev(int(ms.mountFile.Fd()), [][]byte{header, data})
}
return ToStatus(err)
......@@ -286,7 +284,6 @@ func (ms *MountState) writeInodeNotify(entry *raw.NotifyInvalInodeOut) Status {
status: raw.NOTIFY_INVAL_INODE,
}
req.outData = unsafe.Pointer(entry)
req.serialize()
result := ms.write(&req)
if ms.Debug {
......@@ -313,7 +310,6 @@ func (ms *MountState) writeEntryNotify(parent uint64, name string) Status {
nameBytes := []byte(name + "\000")
req.outData = unsafe.Pointer(entry)
req.flatData = nameBytes
req.serialize()
result := ms.write(&req)
if ms.Debug {
......
......@@ -579,4 +579,12 @@ func init() {
} {
operationHandlers[op].FileNames = count
}
var r request
sizeOfOutHeader := unsafe.Sizeof(raw.OutHeader{})
for code, h := range operationHandlers {
if h.OutputSize + sizeOfOutHeader > unsafe.Sizeof(r.outBuf) {
log.Panicf("request output buffer too small: code %v, sz %d + %d %v", code, h.OutputSize, sizeOfOutHeader, h)
}
}
}
......@@ -40,9 +40,9 @@ type request struct {
status Status
flatData []byte
// Header + structured data for what we send back to the kernel.
// May be followed by flatData.
outHeaderBytes []byte
// Space to keep header + structured data for what we send
// back to the kernel.
outBuf [160]byte
// Start timestamp for timing info.
startNs int64
......@@ -84,7 +84,7 @@ func (r *request) OutputDebug() string {
max := 1024
if len(dataStr) > max {
dataStr = dataStr[:max] + fmt.Sprintf(" ...trimmed (response size %d)", len(r.outHeaderBytes))
dataStr = dataStr[:max] + fmt.Sprintf(" ...trimmed")
}
flatStr := ""
......@@ -160,20 +160,20 @@ func (r *request) parse() {
}
}
func (r *request) serialize() {
func (r *request) serialize() (header []byte, data []byte) {
dataLength := r.handler.OutputSize
if r.outData == nil || r.status > OK {
dataLength = 0
}
sizeOfOutHeader := unsafe.Sizeof(raw.OutHeader{})
r.outHeaderBytes = make([]byte, sizeOfOutHeader+dataLength)
outHeader := (*raw.OutHeader)(unsafe.Pointer(&r.outHeaderBytes[0]))
outHeader.Unique = r.inHeader.Unique
outHeader.Status = int32(-r.status)
outHeader.Length = uint32(
header = r.outBuf[:sizeOfOutHeader+dataLength]
o := (*raw.OutHeader)(unsafe.Pointer(&header[0]))
o.Unique = r.inHeader.Unique
o.Status = int32(-r.status)
o.Length = uint32(
int(sizeOfOutHeader) + int(dataLength) + int(len(r.flatData)))
copy(r.outHeaderBytes[sizeOfOutHeader:], asSlice(r.outData, dataLength))
copy(header[sizeOfOutHeader:], asSlice(r.outData, dataLength))
return header, r.flatData
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment