-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #710 from devlights:add-heapalloc-with-clone-method
Add using strings.Clone() example
- Loading branch information
Showing
4 changed files
with
166 additions
and
0 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
app |
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,38 @@ | ||
# これは何? | ||
|
||
Go 1.18 で追加された ```strings.Clone()``` を利用したサンプルです。 | ||
|
||
内部で大きな文字列を確保している状態で、それらの部分文字列を別の場所に確保する処理を実施しています。 | ||
|
||
現状(2023-12-05 現在)のGoの標準コンパイラでは、元の文字列と部分文字列は同じメモリデータを共有するので | ||
|
||
部分文字列をシャローコピーして別のストアに保持したままだと、メモリが開放されません。 | ||
|
||
```strings.Clone()``` を利用することにより、ディープコピーが行われるので、メモリが開放されるようになります。 | ||
|
||
## 実行例 | ||
|
||
```sh | ||
$ task | ||
task: [build] go build -o app main.go | ||
task: [run-not-use-clone] ./app | ||
Title HeapAlloc HeapObjects | ||
[start ] 192792 144 | ||
[gen ] 11482528 4576 | ||
[store ] 11487008 4588 | ||
[checkpoint] 8471296 1363 | ||
[checkpoint] 8475728 1372 | ||
[checkpoint] 8475728 1372 | ||
[checkpoint] 8475728 1372 | ||
[checkpoint] 8475736 1373 | ||
task: [run-use-clone] ./app -use | ||
Title HeapAlloc HeapObjects | ||
[start ] 192824 144 | ||
[gen ] 11497632 4607 | ||
[store ] 11507440 4952 | ||
[checkpoint] 296112 724 | ||
[checkpoint] 300536 732 | ||
[checkpoint] 300536 732 | ||
[checkpoint] 300544 733 | ||
[checkpoint] 300544 733 | ||
``` |
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,19 @@ | ||
# https://taskfile.dev | ||
|
||
version: '3' | ||
|
||
tasks: | ||
default: | ||
deps: [ build ] | ||
cmds: | ||
- task: run-not-use-clone | ||
- task: run-use-clone | ||
build: | ||
cmds: | ||
- go build -o app main.go | ||
run-not-use-clone: | ||
cmds: | ||
- ./app | ||
run-use-clone: | ||
cmds: | ||
- ./app -use |
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,108 @@ | ||
package main | ||
|
||
import ( | ||
"flag" | ||
"io" | ||
"log" | ||
"os/exec" | ||
"runtime" | ||
"strings" | ||
"unsafe" | ||
) | ||
|
||
const ( | ||
NUM_ITEMS = 1000 | ||
SHELL = "/bin/bash" | ||
) | ||
|
||
var ( | ||
store = make([]string, NUM_ITEMS) | ||
) | ||
|
||
func init() { | ||
log.SetFlags(0) | ||
} | ||
|
||
func mem(prefix string) { | ||
var ( | ||
m = runtime.MemStats{} | ||
) | ||
|
||
runtime.ReadMemStats(&m) | ||
log.Printf("[%s]\t%8d\t%8d\n", prefix, m.HeapAlloc, m.HeapObjects) | ||
} | ||
|
||
func gen() []string { | ||
var ( | ||
l = make([]string, NUM_ITEMS) | ||
) | ||
|
||
for i := 0; i < NUM_ITEMS; i++ { | ||
output, _ := exec.Command(SHELL, "-c", "openssl rand -base64 4096 | tr -d '\n'").Output() | ||
l[i] = unsafe.String(&output[0], len(output)) | ||
} | ||
|
||
return l | ||
} | ||
|
||
func main() { | ||
log.Println("Title \tHeapAlloc\tHeapObjects") | ||
mem("start ") | ||
|
||
var ( | ||
use = flag.Bool("use", false, "Use strings.Clone()") | ||
) | ||
flag.Parse() | ||
|
||
var ( | ||
l = gen() | ||
) | ||
mem("gen ") | ||
|
||
for i := 0; i < NUM_ITEMS; i++ { | ||
storeValue := l[i][:5] | ||
|
||
if *use { | ||
store[i] = strings.Clone(storeValue) | ||
} else { | ||
store[i] = storeValue | ||
} | ||
} | ||
mem("store ") | ||
|
||
runtime.GC() | ||
|
||
for i, v := range store { | ||
if i%200 == 0 { | ||
runtime.GC() | ||
mem("checkpoint") | ||
} | ||
|
||
io.Discard.Write(unsafe.Slice(unsafe.StringData(v), len(v))) | ||
} | ||
|
||
/* | ||
$ task | ||
task: [build] go build -o app main.go | ||
task: [run-not-use-clone] ./app | ||
Title HeapAlloc HeapObjects | ||
[start ] 192792 144 | ||
[gen ] 11482528 4576 | ||
[store ] 11487008 4588 | ||
[checkpoint] 8471296 1363 | ||
[checkpoint] 8475728 1372 | ||
[checkpoint] 8475728 1372 | ||
[checkpoint] 8475728 1372 | ||
[checkpoint] 8475736 1373 | ||
task: [run-use-clone] ./app -use | ||
Title HeapAlloc HeapObjects | ||
[start ] 192824 144 | ||
[gen ] 11497632 4607 | ||
[store ] 11507440 4952 | ||
[checkpoint] 296112 724 | ||
[checkpoint] 300536 732 | ||
[checkpoint] 300536 732 | ||
[checkpoint] 300544 733 | ||
[checkpoint] 300544 733 | ||
*/ | ||
} |