Skip to content

Commit a16f0c0

Browse files
committed
log/xlog: avoid cgo android_log_write cstr allocs
1 parent 6ff24ee commit a16f0c0

1 file changed

Lines changed: 28 additions & 6 deletions

File tree

intra/log/xlog_android.go

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,20 @@ import "C"
2929
import (
3030
"bytes"
3131
"io"
32+
"sync"
3233
"unsafe"
3334
)
3435

3536
var newlineSep = []byte("\n")
3637

38+
var cstrPool = sync.Pool{
39+
New: func() any {
40+
// 1024: github.com/golang/mobile/blob/2553ed8ce2/internal/mobileinit/mobileinit_android.go#L52
41+
b := make([]byte, 0, 1024)
42+
return &b
43+
},
44+
}
45+
3746
// ctag is the logcat tag used for all log output.
3847
var ctag = C.CString("Firestack")
3948

@@ -59,18 +68,31 @@ func NewAndroidConsole() Console {
5968

6069
// Log implements Console.
6170
func (a *xlog) Log(level LogLevel, msg Logmsg) {
62-
cstr := C.CString((string)(msg))
63-
C.__android_log_write(androidPriority(level), ctag, cstr)
64-
C.free(unsafe.Pointer(cstr))
71+
if len(msg) <= 0 {
72+
return
73+
}
74+
75+
ptr, _ := cstrPool.Get().(*[]byte)
76+
buf := *ptr
77+
buf = buf[:cap(buf)]
78+
79+
// trunc buf to n or n+1: go.dev/play/p/LlNycbtMsF0
80+
n := copy(buf, msg)
81+
term := min(n, len(buf)-1)
82+
buf[term] = 0 // null terminator
83+
buf = buf[:term+1]
84+
85+
C.__android_log_write(androidPriority(level), ctag, (*C.char)(unsafe.Pointer(&buf[0])))
86+
87+
*ptr = buf[:0]
88+
cstrPool.Put(ptr)
6589
}
6690

6791
func (a *xlog) Write(p []byte) (n int, err error) {
6892
p = bytes.TrimRight(p, "\n\r")
6993
for line := range bytes.SplitSeq(p, newlineSep) {
7094
lvl, msg := splitmsg(line)
71-
if len(msg) > 0 {
72-
a.Log(lvl, msg)
73-
}
95+
a.Log(lvl, msg)
7496
}
7597
return len(p), nil
7698
}

0 commit comments

Comments
 (0)