質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

コピー

元のオブジェクトを破壊することなく、オブジェクトの複製を生成することをコピーと呼びます。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

Q&A

解決済

1回答

2638閲覧

Go言語の関数で、スライスの値渡しとポインタ渡しの効率の違い

mask_mus

総合スコア37

Go

Go(golang)は、Googleで開発されたオープンソースのプログラミング言語です。

コピー

元のオブジェクトを破壊することなく、オブジェクトの複製を生成することをコピーと呼びます。

ポインタ

ポインタはアドレスを用いてメモリに格納された値を"参照する"変数です。

0グッド

0クリップ

投稿2021/03/06 12:07

構造体のスライス([]Person)を関数の引数として渡すとき、スライス要素の構造体のコピーが起こらないように、[]Personではなく[]*Personのようにしました。(ソースコードは1番下です)
調べてみたところ、スライスを引数に渡しても要素自体はコピーされないとのことだったのですが、引数の型の違いでベンチマークに違いが出ていました。
以下に4回分のベンチマークの結果を載せます。

1

1BenchmarkA-6 565 2143826 ns/op 2196458 B/op 19401 allocs/op 2BenchmarkB-6 549 2221813 ns/op 2016721 B/op 24241 allocs/op 3BenchmarkC-6 561 2111836 ns/op 2196518 B/op 19403 allocs/op 4BenchmarkD-6 540 2188856 ns/op 2016780 B/op 24243 allocs/op

2

1BenchmarkA-6 538 2161718 ns/op 2196458 B/op 19401 allocs/op 2BenchmarkB-6 541 2234250 ns/op 2016715 B/op 24241 allocs/op 3BenchmarkC-6 566 2131299 ns/op 2196509 B/op 19403 allocs/op 4BenchmarkD-6 538 2223253 ns/op 2016782 B/op 24243 allocs/op

3

1BenchmarkA-6 552 2258949 ns/op 2196457 B/op 19401 allocs/op 2BenchmarkB-6 511 2225532 ns/op 2016711 B/op 24241 allocs/op 3BenchmarkC-6 537 2195281 ns/op 2196499 B/op 19403 allocs/op 4BenchmarkD-6 535 2236069 ns/op 2016787 B/op 24243 allocs/op

4

1BenchmarkA-6 554 2279453 ns/op 2196468 B/op 19401 allocs/op 2BenchmarkB-6 525 2234598 ns/op 2016723 B/op 24241 allocs/op 3BenchmarkC-6 544 2158688 ns/op 2196510 B/op 19403 allocs/op 4BenchmarkD-6 523 2262048 ns/op 2016791 B/op 24243 allocs/op

割り当てメモリサイズはどちらも変わらないと思っていたのですが、ポインタ渡しの方が少なくなっています。
また、実行速度はポインタ渡しの方が遅くなっていますが、どのあたりで速度が落ちているのでしょうか。
メモリ割り当て回数が増えているのでそれが関係していると思うのですが、どのあたりでメモリ割り当てが起こっているのでしょうか?

以下にソースコードを載せます。
A:[]Person
B:[]Person
C:
[]Person
D:*[]*Person

go

1package test 2 3import ( 4 "bufio" 5 "fmt" 6 "os" 7 "strconv" 8 "strings" 9 "testing" 10) 11 12const fileName = "test.dat" 13 14var bodyInfo []string = []string{"height", "weight", "age"} 15 16type Person struct { 17 name string 18 body map[string]int 19} 20 21func inputA() []Person { 22 var ps []Person 23 f, _ := os.Open(fileName) 24 defer f.Close() 25 26 s := bufio.NewScanner(f) 27 28 for s.Scan() { 29 p := Person{} 30 p.body = make(map[string]int) 31 data := strings.Split(s.Text(), ",") 32 p.name = data[0] 33 for i := 0; i < 3; i++ { 34 p.body[bodyInfo[i]], _ = strconv.Atoi(data[i+1]) 35 } 36 ps = append(ps, p) 37 } 38 return ps 39} 40 41func inputB() []*Person { 42 var ps []*Person 43 f, _ := os.Open(fileName) 44 defer f.Close() 45 46 s := bufio.NewScanner(f) 47 48 for s.Scan() { 49 p := &Person{} 50 p.body = make(map[string]int) 51 data := strings.Split(s.Text(), ",") 52 p.name = data[0] 53 for i := 0; i < 3; i++ { 54 p.body[bodyInfo[i]], _ = strconv.Atoi(data[i+1]) 55 } 56 ps = append(ps, p) 57 } 58 return ps 59} 60 61func inputC() *[]Person { 62 var ps []Person 63 f, _ := os.Open(fileName) 64 defer f.Close() 65 66 s := bufio.NewScanner(f) 67 68 for s.Scan() { 69 p := Person{} 70 p.body = make(map[string]int) 71 data := strings.Split(s.Text(), ",") 72 p.name = data[0] 73 for i := 0; i < 3; i++ { 74 p.body[bodyInfo[i]], _ = strconv.Atoi(data[i+1]) 75 } 76 ps = append(ps, p) 77 } 78 return &ps 79} 80 81func inputD() *[]*Person { 82 var ps []*Person 83 f, _ := os.Open(fileName) 84 defer f.Close() 85 86 s := bufio.NewScanner(f) 87 88 for s.Scan() { 89 p := &Person{} 90 p.body = make(map[string]int) 91 data := strings.Split(s.Text(), ",") 92 p.name = data[0] 93 for i := 0; i < 3; i++ { 94 p.body[bodyInfo[i]], _ = strconv.Atoi(data[i+1]) 95 } 96 ps = append(ps, p) 97 } 98 return &ps 99} 100 101func A(ps []Person) []Person { 102 var nps []Person 103 104 for _, v := range ps { 105 if v.body["height"] >= 180 && v.body["weight"] >= 80 && v.body["age"] >= 20 { 106 nps = append(nps, v) 107 } 108 } 109 return nps 110} 111 112func B(ps []*Person) []*Person { 113 var nps []*Person 114 115 for _, v := range ps { 116 if v.body["height"] >= 180 && v.body["weight"] >= 80 && v.body["age"] >= 20 { 117 nps = append(nps, v) 118 } 119 } 120 return nps 121} 122 123func C(ps *[]Person) *[]Person { 124 var nps []Person 125 126 for _, v := range *ps { 127 if v.body["height"] >= 180 && v.body["weight"] >= 80 && v.body["age"] >= 20 { 128 nps = append(nps, v) 129 } 130 } 131 return &nps 132} 133 134func D(ps *[]*Person) *[]*Person { 135 var nps []*Person 136 137 for _, v := range *ps { 138 if v.body["height"] >= 180 && v.body["weight"] >= 80 && v.body["age"] >= 20 { 139 nps = append(nps, v) 140 } 141 } 142 return &nps 143} 144 145func BenchmarkA(b *testing.B) { 146 b.ResetTimer() 147 for i := 0; i < b.N; i++ { 148 ps := inputA() 149 nps := A(ps) 150 f, _ := os.Create(fmt.Sprintf("./A/%d.dat", i)) 151 w := bufio.NewWriter(f) 152 for _, v := range nps { 153 w.WriteString(v.name + "\n") 154 } 155 w.Flush() 156 f.Close() 157 } 158} 159 160func BenchmarkB(b *testing.B) { 161 b.ResetTimer() 162 for i := 0; i < b.N; i++ { 163 ps := inputB() 164 nps := B(ps) 165 f, _ := os.Create(fmt.Sprintf("./B/%d.dat", i)) 166 w := bufio.NewWriter(f) 167 for _, v := range nps { 168 w.WriteString(v.name + "\n") 169 } 170 w.Flush() 171 f.Close() 172 } 173} 174 175func BenchmarkC(b *testing.B) { 176 b.ResetTimer() 177 for i := 0; i < b.N; i++ { 178 ps := inputC() 179 nps := C(ps) 180 f, _ := os.Create(fmt.Sprintf("./C/%d.dat", i)) 181 w := bufio.NewWriter(f) 182 for _, v := range *nps { 183 w.WriteString(v.name + "\n") 184 } 185 w.Flush() 186 f.Close() 187 } 188} 189 190func BenchmarkD(b *testing.B) { 191 b.ResetTimer() 192 for i := 0; i < b.N; i++ { 193 ps := inputD() 194 nps := D(ps) 195 f, _ := os.Create(fmt.Sprintf("./D/%d.dat", i)) 196 w := bufio.NewWriter(f) 197 for _, v := range *nps { 198 w.WriteString(v.name + "\n") 199 } 200 w.Flush() 201 f.Close() 202 } 203} 204

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

いま例示しているベンチマークの数値は5%前後の差で微差に見える結果です。
メモリ操作のベンチマークにファイル操作を混在させるのは比較したいものに対して適切ではありません。
一般にメモリ操作に対してファイル操作の処理時間はうん十倍のオーダーなので。
メモリ操作だけの処理にするともっとはっきりと差が出ると思います。

投稿2021/03/07 02:18

nobonobo

総合スコア3367

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問