From 6bc0fc7615737ef527c595f11dacdf2dfd45519a Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 4 Jul 2023 22:19:08 +0530 Subject: [PATCH] Make serializing data ops avoid a double copy --- tools/rsync/algorithm.go | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/tools/rsync/algorithm.go b/tools/rsync/algorithm.go index 7bceeef28..28a5b672e 100644 --- a/tools/rsync/algorithm.go +++ b/tools/rsync/algorithm.go @@ -17,8 +17,6 @@ import ( "hash" "io" "os" - - "golang.org/x/exp/slices" ) // If no BlockSize is specified in the RSync instance, this value is used. @@ -44,11 +42,16 @@ type Operation struct { BlockIndex uint64 BlockIndexEnd uint64 Data []byte + + serialized_repr []byte } var bin = binary.LittleEndian func (self Operation) Serialize() []byte { + if self.serialized_repr != nil { + return self.serialized_repr + } var ans []byte switch self.Type { case OpBlock: @@ -399,7 +402,13 @@ func (self *Diff) enqueue(op Operation) { } func (self *Diff) send_data() { - self.enqueue(Operation{Type: OpData, Data: slices.Clone(self.buffer[self.data.tail:self.data.head])}) + data := self.buffer[self.data.tail:self.data.head] + srepr := make([]byte, len(data)+5) + copy(srepr[5:], data) + bin.PutUint32(srepr[1:], uint32(len(data))) + srepr[0] = byte(OpData) + op := Operation{Type: OpData, Data: srepr[5:], serialized_repr: srepr} + self.enqueue(op) self.data.tail = self.data.head }