diff options
Diffstat (limited to 'vendor/github.com')
-rw-r--r-- | vendor/github.com/DmitriyVTitov/size/.gitignore | 19 | ||||
-rw-r--r-- | vendor/github.com/DmitriyVTitov/size/LICENSE | 21 | ||||
-rw-r--r-- | vendor/github.com/DmitriyVTitov/size/README.md | 48 | ||||
-rw-r--r-- | vendor/github.com/DmitriyVTitov/size/size.go | 142 |
4 files changed, 230 insertions, 0 deletions
diff --git a/vendor/github.com/DmitriyVTitov/size/.gitignore b/vendor/github.com/DmitriyVTitov/size/.gitignore new file mode 100644 index 000000000..ae4c566d2 --- /dev/null +++ b/vendor/github.com/DmitriyVTitov/size/.gitignore @@ -0,0 +1,19 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ + +example +.idea +go.sum
\ No newline at end of file diff --git a/vendor/github.com/DmitriyVTitov/size/LICENSE b/vendor/github.com/DmitriyVTitov/size/LICENSE new file mode 100644 index 000000000..507b0b74c --- /dev/null +++ b/vendor/github.com/DmitriyVTitov/size/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2020 Dmitriy Titov (Дмитрий Титов) + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/github.com/DmitriyVTitov/size/README.md b/vendor/github.com/DmitriyVTitov/size/README.md new file mode 100644 index 000000000..215a749cc --- /dev/null +++ b/vendor/github.com/DmitriyVTitov/size/README.md @@ -0,0 +1,48 @@ +# size - calculates variable's memory consumption at runtime + +### Part of the [Transflow Project](http://transflow.ru/) + +Sometimes you may need a tool to measure the size of object in your Go program at runtime. This package makes an attempt to do so. Package based on `binary.Size()` from Go standard library. + +Features: +- supports non-fixed size variables and struct fields: `struct`, `int`, `slice`, `string`, `map`; +- supports complex types including structs with non-fixed size fields; +- supports all basic types (numbers, bool); +- supports `chan` and `interface`; +- supports pointers; +- implements infinite recursion detection (i.e. pointer inside struct field references to parent struct). + +### Usage example + +``` +package main + +import ( + "fmt" + + // Use latest tag. + "github.com/DmitriyVTitov/size" +) + +func main() { + a := struct { + a int + b string + c bool + d int32 + e []byte + f [3]int64 + }{ + a: 10, // 8 bytes + b: "Text", // 16 (string itself) + 4 = 20 bytes + c: true, // 1 byte + d: 25, // 4 bytes + e: []byte{'c', 'd', 'e'}, // 24 (slice itself) + 3 = 27 bytes + f: [3]int64{1, 2, 3}, // 3 * 8 = 24 bytes + } // 84 + 3 (padding) = 87 bytes + + fmt.Println(size.Of(a)) +} + +// Output: 87 +``` diff --git a/vendor/github.com/DmitriyVTitov/size/size.go b/vendor/github.com/DmitriyVTitov/size/size.go new file mode 100644 index 000000000..b52e2c41d --- /dev/null +++ b/vendor/github.com/DmitriyVTitov/size/size.go @@ -0,0 +1,142 @@ +// Package size implements run-time calculation of size of the variable. +// Source code is based on "binary.Size()" function from Go standard library. +// size.Of() omits size of slices, arrays and maps containers itself (24, 24 and 8 bytes). +// When counting maps separate calculations are done for keys and values. +package size + +import ( + "reflect" + "unsafe" +) + +// Of returns the size of 'v' in bytes. +// If there is an error during calculation, Of returns -1. +func Of(v interface{}) int { + // Cache with every visited pointer so we don't count two pointers + // to the same memory twice. + cache := make(map[uintptr]bool) + return sizeOf(reflect.Indirect(reflect.ValueOf(v)), cache) +} + +// sizeOf returns the number of bytes the actual data represented by v occupies in memory. +// If there is an error, sizeOf returns -1. +func sizeOf(v reflect.Value, cache map[uintptr]bool) int { + switch v.Kind() { + + case reflect.Array: + sum := 0 + for i := 0; i < v.Len(); i++ { + s := sizeOf(v.Index(i), cache) + if s < 0 { + return -1 + } + sum += s + } + + return sum + (v.Cap()-v.Len())*int(v.Type().Elem().Size()) + + case reflect.Slice: + // return 0 if this node has been visited already + if cache[v.Pointer()] { + return 0 + } + cache[v.Pointer()] = true + + sum := 0 + for i := 0; i < v.Len(); i++ { + s := sizeOf(v.Index(i), cache) + if s < 0 { + return -1 + } + sum += s + } + + sum += (v.Cap() - v.Len()) * int(v.Type().Elem().Size()) + + return sum + int(v.Type().Size()) + + case reflect.Struct: + sum := 0 + for i, n := 0, v.NumField(); i < n; i++ { + s := sizeOf(v.Field(i), cache) + if s < 0 { + return -1 + } + sum += s + } + + // Look for struct padding. + padding := int(v.Type().Size()) + for i, n := 0, v.NumField(); i < n; i++ { + padding -= int(v.Field(i).Type().Size()) + } + + return sum + padding + + case reflect.String: + s := v.String() + hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) + if cache[hdr.Data] { + return int(v.Type().Size()) + } + cache[hdr.Data] = true + return len(s) + int(v.Type().Size()) + + case reflect.Ptr: + // return Ptr size if this node has been visited already (infinite recursion) + if cache[v.Pointer()] { + return int(v.Type().Size()) + } + cache[v.Pointer()] = true + if v.IsNil() { + return int(reflect.New(v.Type()).Type().Size()) + } + s := sizeOf(reflect.Indirect(v), cache) + if s < 0 { + return -1 + } + return s + int(v.Type().Size()) + + case reflect.Bool, + reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, + reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64, + reflect.Int, reflect.Uint, + reflect.Chan, + reflect.Uintptr, + reflect.Float32, reflect.Float64, reflect.Complex64, reflect.Complex128, + reflect.Func: + return int(v.Type().Size()) + + case reflect.Map: + // return 0 if this node has been visited already (infinite recursion) + if cache[v.Pointer()] { + return 0 + } + cache[v.Pointer()] = true + sum := 0 + keys := v.MapKeys() + for i := range keys { + val := v.MapIndex(keys[i]) + // calculate size of key and value separately + sv := sizeOf(val, cache) + if sv < 0 { + return -1 + } + sum += sv + sk := sizeOf(keys[i], cache) + if sk < 0 { + return -1 + } + sum += sk + } + // Include overhead due to unused map buckets. 10.79 comes + // from https://golang.org/src/runtime/map.go. + return sum + int(v.Type().Size()) + int(float64(len(keys))*10.79) + + case reflect.Interface: + return sizeOf(v.Elem(), cache) + int(v.Type().Size()) + + } + + return -1 +} |