From 59333ba1adf065efcca4c706071de0094f6ce5d9 Mon Sep 17 00:00:00 2001 From: Hajime Hoshi Date: Thu, 26 Sep 2019 23:59:00 +0900 Subject: [PATCH] jsutil: Avoid allocating ArrayBuffer unnecessarily --- internal/jsutil/go113_js.go | 28 ++++++++++++++++++++-------- 1 file changed, 20 insertions(+), 8 deletions(-) diff --git a/internal/jsutil/go113_js.go b/internal/jsutil/go113_js.go index 40bb339f4..6d2c06745 100644 --- a/internal/jsutil/go113_js.go +++ b/internal/jsutil/go113_js.go @@ -96,44 +96,56 @@ func sliceToByteSlice(s interface{}) (bs []byte) { return } +var temporaryBuffer = js.Global().Get("ArrayBuffer").New(16) + +func getTemporaryUint8Array(size int) js.Value { + if l := temporaryBuffer.Get("byteLength").Int(); l < size { + for l < size { + l *= 2 + } + temporaryBuffer = js.Global().Get("ArrayBuffer").New(l) + } + return js.Global().Get("Uint8Array").New(temporaryBuffer, 0, size) +} + func SliceToTypedArray(s interface{}) (js.Value, func()) { switch s := s.(type) { case []int8: - a := js.Global().Get("Uint8Array").New(len(s)) + a := getTemporaryUint8Array(len(s)) js.CopyBytesToJS(a, sliceToByteSlice(s)) buf := a.Get("buffer") return js.Global().Get("Int8Array").New(buf, a.Get("byteOffset"), a.Get("byteLength")), func() {} case []int16: - a := js.Global().Get("Uint8Array").New(len(s) * 2) + a := getTemporaryUint8Array(len(s) * 2) js.CopyBytesToJS(a, sliceToByteSlice(s)) buf := a.Get("buffer") return js.Global().Get("Int16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), func() {} case []int32: - a := js.Global().Get("Uint8Array").New(len(s) * 4) + a := getTemporaryUint8Array(len(s) * 4) js.CopyBytesToJS(a, sliceToByteSlice(s)) buf := a.Get("buffer") return js.Global().Get("Int32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {} case []uint8: - a := js.Global().Get("Uint8Array").New(len(s)) + a := getTemporaryUint8Array(len(s)) js.CopyBytesToJS(a, s) return a, func() {} case []uint16: - a := js.Global().Get("Uint8Array").New(len(s) * 2) + a := getTemporaryUint8Array(len(s) * 2) js.CopyBytesToJS(a, sliceToByteSlice(s)) buf := a.Get("buffer") return js.Global().Get("Uint16Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/2), func() {} case []uint32: - a := js.Global().Get("Uint8Array").New(len(s) * 4) + a := getTemporaryUint8Array(len(s) * 4) js.CopyBytesToJS(a, sliceToByteSlice(s)) buf := a.Get("buffer") return js.Global().Get("Uint32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {} case []float32: - a := js.Global().Get("Uint8Array").New(len(s) * 4) + a := getTemporaryUint8Array(len(s) * 4) js.CopyBytesToJS(a, sliceToByteSlice(s)) buf := a.Get("buffer") return js.Global().Get("Float32Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/4), func() {} case []float64: - a := js.Global().Get("Uint8Array").New(len(s) * 8) + a := getTemporaryUint8Array(len(s) * 8) js.CopyBytesToJS(a, sliceToByteSlice(s)) buf := a.Get("buffer") return js.Global().Get("Float64Array").New(buf, a.Get("byteOffset"), a.Get("byteLength").Int()/8), func() {}