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) { ...@@ -242,8 +242,8 @@ func (ms *MountState) handleRequest(req *request) {
errNo := ms.write(req) errNo := ms.write(req)
if errNo != 0 { if errNo != 0 {
log.Printf("writer: Write/Writev %v failed, err: %v. opcode: %v", log.Printf("writer: Write/Writev failed, err: %v. opcode: %v",
req.outHeaderBytes, errNo, operationName(req.inHeader.Opcode)) errNo, operationName(req.inHeader.Opcode))
} }
} }
...@@ -253,7 +253,7 @@ func (ms *MountState) write(req *request) Status { ...@@ -253,7 +253,7 @@ func (ms *MountState) write(req *request) Status {
return OK return OK
} }
req.serialize() header, data := req.serialize()
if ms.Debug { if ms.Debug {
log.Println(req.OutputDebug()) log.Println(req.OutputDebug())
} }
...@@ -262,16 +262,14 @@ func (ms *MountState) write(req *request) Status { ...@@ -262,16 +262,14 @@ func (ms *MountState) write(req *request) Status {
req.preWriteNs = time.Now().UnixNano() req.preWriteNs = time.Now().UnixNano()
} }
if req.outHeaderBytes == nil { if header == nil {
return OK return OK
} }
var err error var err error
if req.flatData == nil { if data == nil {
_, err = ms.mountFile.Write(req.outHeaderBytes) _, err = ms.mountFile.Write(header)
} else { } else {
_, err = Writev(int(ms.mountFile.Fd()), _, err = Writev(int(ms.mountFile.Fd()), [][]byte{header, data})
[][]byte{req.outHeaderBytes, req.flatData})
} }
return ToStatus(err) return ToStatus(err)
...@@ -286,7 +284,6 @@ func (ms *MountState) writeInodeNotify(entry *raw.NotifyInvalInodeOut) Status { ...@@ -286,7 +284,6 @@ func (ms *MountState) writeInodeNotify(entry *raw.NotifyInvalInodeOut) Status {
status: raw.NOTIFY_INVAL_INODE, status: raw.NOTIFY_INVAL_INODE,
} }
req.outData = unsafe.Pointer(entry) req.outData = unsafe.Pointer(entry)
req.serialize()
result := ms.write(&req) result := ms.write(&req)
if ms.Debug { if ms.Debug {
...@@ -313,7 +310,6 @@ func (ms *MountState) writeEntryNotify(parent uint64, name string) Status { ...@@ -313,7 +310,6 @@ func (ms *MountState) writeEntryNotify(parent uint64, name string) Status {
nameBytes := []byte(name + "\000") nameBytes := []byte(name + "\000")
req.outData = unsafe.Pointer(entry) req.outData = unsafe.Pointer(entry)
req.flatData = nameBytes req.flatData = nameBytes
req.serialize()
result := ms.write(&req) result := ms.write(&req)
if ms.Debug { if ms.Debug {
......
...@@ -579,4 +579,12 @@ func init() { ...@@ -579,4 +579,12 @@ func init() {
} { } {
operationHandlers[op].FileNames = count 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 { ...@@ -40,9 +40,9 @@ type request struct {
status Status status Status
flatData []byte flatData []byte
// Header + structured data for what we send back to the kernel. // Space to keep header + structured data for what we send
// May be followed by flatData. // back to the kernel.
outHeaderBytes []byte outBuf [160]byte
// Start timestamp for timing info. // Start timestamp for timing info.
startNs int64 startNs int64
...@@ -84,7 +84,7 @@ func (r *request) OutputDebug() string { ...@@ -84,7 +84,7 @@ func (r *request) OutputDebug() string {
max := 1024 max := 1024
if len(dataStr) > max { if len(dataStr) > max {
dataStr = dataStr[:max] + fmt.Sprintf(" ...trimmed (response size %d)", len(r.outHeaderBytes)) dataStr = dataStr[:max] + fmt.Sprintf(" ...trimmed")
} }
flatStr := "" flatStr := ""
...@@ -160,20 +160,20 @@ func (r *request) parse() { ...@@ -160,20 +160,20 @@ func (r *request) parse() {
} }
} }
func (r *request) serialize() { func (r *request) serialize() (header []byte, data []byte) {
dataLength := r.handler.OutputSize dataLength := r.handler.OutputSize
if r.outData == nil || r.status > OK { if r.outData == nil || r.status > OK {
dataLength = 0 dataLength = 0
} }
sizeOfOutHeader := unsafe.Sizeof(raw.OutHeader{}) sizeOfOutHeader := unsafe.Sizeof(raw.OutHeader{})
header = r.outBuf[:sizeOfOutHeader+dataLength]
r.outHeaderBytes = make([]byte, sizeOfOutHeader+dataLength) o := (*raw.OutHeader)(unsafe.Pointer(&header[0]))
outHeader := (*raw.OutHeader)(unsafe.Pointer(&r.outHeaderBytes[0])) o.Unique = r.inHeader.Unique
outHeader.Unique = r.inHeader.Unique o.Status = int32(-r.status)
outHeader.Status = int32(-r.status) o.Length = uint32(
outHeader.Length = uint32(
int(sizeOfOutHeader) + int(dataLength) + int(len(r.flatData))) 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