Skip to content

Commit 53f9560

Browse files
authored
Merge pull request #710 from devlights:add-heapalloc-with-clone-method
Add using strings.Clone() example
2 parents 5d0597b + 04afd88 commit 53f9560

File tree

4 files changed

+166
-0
lines changed

4 files changed

+166
-0
lines changed
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
app
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# これは何?
2+
3+
Go 1.18 で追加された ```strings.Clone()``` を利用したサンプルです。
4+
5+
内部で大きな文字列を確保している状態で、それらの部分文字列を別の場所に確保する処理を実施しています。
6+
7+
現状(2023-12-05 現在)のGoの標準コンパイラでは、元の文字列と部分文字列は同じメモリデータを共有するので
8+
9+
部分文字列をシャローコピーして別のストアに保持したままだと、メモリが開放されません。
10+
11+
```strings.Clone()``` を利用することにより、ディープコピーが行われるので、メモリが開放されるようになります。
12+
13+
## 実行例
14+
15+
```sh
16+
$ task
17+
task: [build] go build -o app main.go
18+
task: [run-not-use-clone] ./app
19+
Title HeapAlloc HeapObjects
20+
[start ] 192792 144
21+
[gen ] 11482528 4576
22+
[store ] 11487008 4588
23+
[checkpoint] 8471296 1363
24+
[checkpoint] 8475728 1372
25+
[checkpoint] 8475728 1372
26+
[checkpoint] 8475728 1372
27+
[checkpoint] 8475736 1373
28+
task: [run-use-clone] ./app -use
29+
Title HeapAlloc HeapObjects
30+
[start ] 192824 144
31+
[gen ] 11497632 4607
32+
[store ] 11507440 4952
33+
[checkpoint] 296112 724
34+
[checkpoint] 300536 732
35+
[checkpoint] 300536 732
36+
[checkpoint] 300544 733
37+
[checkpoint] 300544 733
38+
```
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# https://taskfile.dev
2+
3+
version: '3'
4+
5+
tasks:
6+
default:
7+
deps: [ build ]
8+
cmds:
9+
- task: run-not-use-clone
10+
- task: run-use-clone
11+
build:
12+
cmds:
13+
- go build -o app main.go
14+
run-not-use-clone:
15+
cmds:
16+
- ./app
17+
run-use-clone:
18+
cmds:
19+
- ./app -use
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package main
2+
3+
import (
4+
"flag"
5+
"io"
6+
"log"
7+
"os/exec"
8+
"runtime"
9+
"strings"
10+
"unsafe"
11+
)
12+
13+
const (
14+
NUM_ITEMS = 1000
15+
SHELL = "/bin/bash"
16+
)
17+
18+
var (
19+
store = make([]string, NUM_ITEMS)
20+
)
21+
22+
func init() {
23+
log.SetFlags(0)
24+
}
25+
26+
func mem(prefix string) {
27+
var (
28+
m = runtime.MemStats{}
29+
)
30+
31+
runtime.ReadMemStats(&m)
32+
log.Printf("[%s]\t%8d\t%8d\n", prefix, m.HeapAlloc, m.HeapObjects)
33+
}
34+
35+
func gen() []string {
36+
var (
37+
l = make([]string, NUM_ITEMS)
38+
)
39+
40+
for i := 0; i < NUM_ITEMS; i++ {
41+
output, _ := exec.Command(SHELL, "-c", "openssl rand -base64 4096 | tr -d '\n'").Output()
42+
l[i] = unsafe.String(&output[0], len(output))
43+
}
44+
45+
return l
46+
}
47+
48+
func main() {
49+
log.Println("Title \tHeapAlloc\tHeapObjects")
50+
mem("start ")
51+
52+
var (
53+
use = flag.Bool("use", false, "Use strings.Clone()")
54+
)
55+
flag.Parse()
56+
57+
var (
58+
l = gen()
59+
)
60+
mem("gen ")
61+
62+
for i := 0; i < NUM_ITEMS; i++ {
63+
storeValue := l[i][:5]
64+
65+
if *use {
66+
store[i] = strings.Clone(storeValue)
67+
} else {
68+
store[i] = storeValue
69+
}
70+
}
71+
mem("store ")
72+
73+
runtime.GC()
74+
75+
for i, v := range store {
76+
if i%200 == 0 {
77+
runtime.GC()
78+
mem("checkpoint")
79+
}
80+
81+
io.Discard.Write(unsafe.Slice(unsafe.StringData(v), len(v)))
82+
}
83+
84+
/*
85+
$ task
86+
task: [build] go build -o app main.go
87+
task: [run-not-use-clone] ./app
88+
Title HeapAlloc HeapObjects
89+
[start ] 192792 144
90+
[gen ] 11482528 4576
91+
[store ] 11487008 4588
92+
[checkpoint] 8471296 1363
93+
[checkpoint] 8475728 1372
94+
[checkpoint] 8475728 1372
95+
[checkpoint] 8475728 1372
96+
[checkpoint] 8475736 1373
97+
task: [run-use-clone] ./app -use
98+
Title HeapAlloc HeapObjects
99+
[start ] 192824 144
100+
[gen ] 11497632 4607
101+
[store ] 11507440 4952
102+
[checkpoint] 296112 724
103+
[checkpoint] 300536 732
104+
[checkpoint] 300536 732
105+
[checkpoint] 300544 733
106+
[checkpoint] 300544 733
107+
*/
108+
}

0 commit comments

Comments
 (0)