-
Notifications
You must be signed in to change notification settings - Fork 220
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing
9 changed files
with
324 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,4 +5,6 @@ require ( | |
github.com/yuin/gopher-lua v1.1.0 | ||
) | ||
|
||
require github.com/DmitriyVTitov/size v1.5.0 | ||
|
||
go 1.14 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,12 @@ | ||
github.com/DmitriyVTitov/size v1.5.0 h1:/PzqxYrOyOUX1BXj6J9OuVRVGe+66VL4D9FlUaW515g= | ||
github.com/DmitriyVTitov/size v1.5.0/go.mod h1:le6rNI4CoLQV1b9gzp1+3d7hMAD/uu2QcJ+aYbNgiU0= | ||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZpUGpz5+4FfNmIU+FmZg2P3Xaj2v2bfNWmk= | ||
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= | ||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= | ||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= | ||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= | ||
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9 h1:k/gmLsJDWwWqbLCur2yWnJzwQEKRcAHXo6seXGuSwWw= | ||
github.com/yuin/gopher-lua v0.0.0-20210529063254-f4c35e4016d9/go.mod h1:E1AXubJBdNmFERAOucpDIxNzeGfLzg0mYh+UfMWdChA= | ||
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64 h1:5mLPGnFdSsevFRFc9q3yYbBkB6tsm4aCwwQV/j1JQAQ= | ||
github.com/yuin/gopher-lua v0.0.0-20220504180219-658193537a64/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= | ||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= | ||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= | ||
github.com/yuin/gopher-lua v1.1.0 h1:BojcDhfyDWgU2f2TOzYK/g5p2gxMrku8oupLDqlnSqE= | ||
github.com/yuin/gopher-lua v1.1.0/go.mod h1:GBR0iDaNXjAgGg9zfCvksxSRnQx76gclCIb7kdAd1Pw= | ||
golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
|
||
Credits to DmitriyVTitov on his package https://github.com/DmitriyVTitov/size |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,138 @@ | ||
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 | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
package size | ||
|
||
import ( | ||
"testing" | ||
) | ||
|
||
func TestOf(t *testing.T) { | ||
tests := []struct { | ||
name string | ||
v interface{} | ||
want int | ||
}{ | ||
{ | ||
name: "Array", | ||
v: [3]int32{1, 2, 3}, // 3 * 4 = 12 | ||
want: 12, | ||
}, | ||
{ | ||
name: "Slice", | ||
v: make([]int64, 2, 5), // 5 * 8 + 24 = 64 | ||
want: 64, | ||
}, | ||
{ | ||
name: "String", | ||
v: "ABCdef", // 6 + 16 = 22 | ||
want: 22, | ||
}, | ||
{ | ||
name: "Map", | ||
// (8 + 3 + 16) + (8 + 4 + 16) = 55 | ||
// 55 + 8 + 10.79 * 2 = 84 | ||
v: map[int64]string{0: "ABC", 1: "DEFG"}, | ||
want: 84, | ||
}, | ||
{ | ||
name: "Struct", | ||
v: struct { | ||
slice []int64 | ||
array [2]bool | ||
structure struct { | ||
i int8 | ||
s string | ||
} | ||
}{ | ||
slice: []int64{12345, 67890}, // 2 * 8 + 24 = 40 | ||
array: [2]bool{true, false}, // 2 * 1 = 2 | ||
structure: struct { | ||
i int8 | ||
s string | ||
}{ | ||
i: 5, // 1 | ||
s: "abc", // 3 * 1 + 16 = 19 | ||
}, // 20 + 7 (padding) = 27 | ||
}, // 40 + 2 + 27 = 69 + 6 (padding) = 75 | ||
want: 75, | ||
}, | ||
} | ||
for _, tt := range tests { | ||
t.Run(tt.name, func(t *testing.T) { | ||
if got := Of(tt.v); got != tt.want { | ||
t.Errorf("Of() = %v, want %v", got, tt.want) | ||
} | ||
}) | ||
} | ||
} |