From 2e1b699a875e8477393e2d32f2f7b23209dcce07 Mon Sep 17 00:00:00 2001 From: Tobie Morgan Hitchcock Date: Wed, 20 Nov 2019 13:10:34 +0000 Subject: [PATCH] Improve memory allocations when data.Doc cloning --- util/data/data.go | 3 ++- util/dupe/dupe.go | 62 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 util/dupe/dupe.go diff --git a/util/data/data.go b/util/data/data.go index 5ad45a0e..1a9f8120 100644 --- a/util/data/data.go +++ b/util/data/data.go @@ -22,6 +22,7 @@ import ( "encoding/json" + "github.com/abcum/surreal/util/dupe" "github.com/abcum/surreal/util/pack" ) @@ -66,7 +67,7 @@ func (d *Doc) Data() interface{} { // Copy returns a duplicated copy of the internal data object. func (d *Doc) Copy() *Doc { - return new(Doc).Decode(d.Encode()) + return Consume(dupe.Duplicate(d.data)) } // Encode encodes the data object to a byte slice. diff --git a/util/dupe/dupe.go b/util/dupe/dupe.go new file mode 100644 index 00000000..ab5f39c4 --- /dev/null +++ b/util/dupe/dupe.go @@ -0,0 +1,62 @@ +// Copyright © 2016 Abcum Ltd +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package dupe + +type Copyable interface { + Copy() interface{} +} + +type Cloneable interface { + Clone() interface{} +} + +func Duplicate(v interface{}) interface{} { + + switch x := v.(type) { + case map[string]interface{}: + out := make(map[string]interface{}, len(x)) + for k, v := range x { + switch y := v.(type) { + case map[string]interface{}: + out[k] = Duplicate(y) + case []interface{}: + out[k] = Duplicate(y) + default: + out[k] = y + } + } + return out + case []interface{}: + out := make([]interface{}, len(x)) + for k, v := range x { + switch y := v.(type) { + case map[string]interface{}: + out[k] = Duplicate(y) + case []interface{}: + out[k] = Duplicate(y) + default: + out[k] = y + } + } + return out + case Cloneable: + return x.Clone() + case Copyable: + return x.Copy() + default: + return x + } + +}