[過去ログ] Go language part 5 (1002レス)
前次1-
抽出解除 レス栞

このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
リロード規制です。10分ほどで解除するので、他のブラウザへ避難してください。
12
(3): デフォルトの名無しさん [sage] 2022/02/27(日) 17:20:40.92 ID:+yReYAPt(2/3) AAS
>>6
6(2): デフォルトの名無しさん [sage] 2022/02/27(日) 09:39:32.40 ID:+yReYAPt(1/3) AAS
ちなみに前スレ1000と同じく、1桁少ない1000スレッドで同じPCでgoを測ると
$ go version
go version go1.13.8 linux/amd64
$ go build main.go && ./t ./main
real 12.02s
user 0.91s
sys 0.22s
rss 3808k
$
やはり4Mを超えない(rssでいいの?とは思うけど)
自己レスです。
Goは1.4からamd64だとスタック2k
外部リンク:github.com
今回試した1.13.8だと当該コードがCからgoに変わったりして跡形もなかったが、_StackMin = 2048はそのままだった
外部リンク[go]:github.com
つまり2Mであれば残り1.8Mということで矛盾はない
13
(1): デフォルトの名無しさん [sage] 2022/02/27(日) 17:32:40.97 ID:Xl3wWN+O(1/2) AAS
>>12
1000個立ち上げなんて1桁減らして測定してるからメモリ使用量がわかりにくいような
素直に1万個と10万個で調べて差を見れば1個あたりがはっきりするような
18
(1): デフォルトの名無しさん [sage] 2022/02/27(日) 22:00:44.12 ID:PVy06kKY(7/8) AAS
>>12
ちなみにコードが素晴らしくメンテされてれば、

_StackMin = 1024

にするだけで、スタックサイズが1kBになるような気もします。
23
(1): デフォルトの名無しさん [sage] 2022/02/28(月) 00:35:47.82 ID:EeqSDih1(1/3) AAS
>>17
17(1): デフォルトの名無しさん [sage] 2022/02/27(日) 21:41:54.35 ID:PVy06kKY(6/8) AAS
>>14
もしかして俺が前スレ962で単純に40MB足してたのが気になってたのなら申し訳ない。
あれは足しすぎだった。RSSの意味は以下。
外部リンク:stackoverflow.com
十分なメモリがある状況で普通に実行させた直後(スワップされてない状況)なら、RSSで問題ない。(はず)

以下は前スレ992内にある図だが
外部リンク[svg]:commons.wikimedia.org
これ全部を待避するのに1kB程度かかるらしく(真面目に数えれば正確な数値は出せるが、やる気無し)
この分をOS側が待避するので、単純に言えばスレッド数*1kB程OS側のメモリを食ってる。
これがgoroutineだと必要ない(Goランタイム管轄で待避で、RSSに計上されてる)ので文句付けられてる。

だから公平に見るなら、goroutineはRSSそのままで良く、OSのthreadを使うならスレッド数*1KB程度追加かと。
(40MBはスレッド数*4kBにしてるので、多すぎ。
アクセスのない、単なる待避領域なので、ページ単位である必要はない。)

そして関数呼び出しのオーバーヘッドについてはそこにモロに書いてあるな。(GitHub上ソースの17行目〜60行目)
0〜4Cycleのオーバーヘッドになる。
方式としては、スタックの底に96Bytes(=40+56)の領域があらかじめ確保してあって、
これらはメモリが足りない時に呼ばれるdeferproc()とmorestack()に必要なスタックサイズなのだが、
逆に言えば96Bytes以下のスタックしか使わない関数ならスタックポインタがそこを越えてなければ問題ないわけで、
以下チェックを通してる。(guardがスタック満タン-96Bytesのアドレスを示してる)
> CMPQ guard, SP
> JHI 3(PC)
> MOVQ m->morearg, $(argsize << 32)
> CALL morestack(SB)
まあスタック増加がなければINT/BR/NOP/NOPなので、オーバーヘッドは通常1か2Cycleじゃないかと思うけども。
>18
むしろ前スレ957のベンチ(元記事)では、

"In particular, 10k threads with default stack sizes need about 40mb of page tables to map virtual memory."

と訂正しているのだから、前スレ962の計算で40MB足してるのはおかしくない。
ただ、>>4
4(1): デフォルトの名無しさん [sage] 2022/02/27(日) 08:59:11.36 ID:PVy06kKY(1/8) AAS
>>992(前スレ)
読んだ。で、やっぱり奇妙なんだけど、多分オーバーヘッドはないと思うよ。

一般的にはガードページなんて必要なくて、コピーオンライトと同じで、
ページ境界を跨いだ場合はハードウェアで検出出来るから、まず普通はそれを使う。
この場合は自前でのチェックは必要ない(ソフトウェアには必要ない)ので、オーバーヘッドはない。
だからGoの当初の初期スタックサイズが4kだったのは非常に納得出来た。ここまではいい。

これを小さくするならハードウェアのサポート無しになるから当然自前でチェックするしかないが、この場合、
・2kも大きすぎ。自分でやるならRustのように64Bytesからとか、4kに拘らず凄く小さいスタックサイズから可能だし、普通はそうする。
・そもそも必要スタックサイズを予見出来ない。というか出来るならコンパイル時に確定的に割り当てれば済んでる。
であって、Rustの実装は非常に納得出来るのだけど、Goのは若干意味不明なんだよ。
(ただまあ何かしら理由はあると思うけど)

2kとかいう、4kに拘ったサイズになってるんだから、多分何かしらハードウェアのサポートを受けてて、
自前ではスタックサイズのチェックはしてないと思うよ。(つまりオーバーヘッドがない)
可能性があるのは、2kをはみ出る時には4k境界を跨ぐようにして(つまりまずは上側を割り当てる)
はみ出た時に2kずらしていくとかだけど。
ただこの方式の場合、初期アロケーションだけは4kでされてしまうので、957のベンチでは40MB越えないとおかしくて、矛盾してる。
だから正直よく分からないが、
多分オーバーヘッドのない方式で実装してて、だから2kとかいう中途半端な巨大サイズになってるのではないかと思う。
で再び「957のベンチでは40MB越えないとおかしくて、矛盾してる」と言ってるのが、普通に考えるとRSS対象なので、スレッド数を10kから1kにした俺版でも前スレ1000のC++版との対比する意味もあり、改めてgo版の結果を同じ条件で出した(>>6)だけ。
結論は同様にRSSは4MBを超えないので、仮想メモリ側にあるという元記事の主張で正しいようにも見える。
しかし、go処理系が不明な元記事と違い、自分でやっていれば実際バージョンは分かるわけで、そこが分かればスタックサイズはソースを見れば一目瞭然ということで経緯と一緒に調べたのが、>>12で結論としては2Kだったということ。
すると元記事の推測と自分の計測結果には矛盾があり、2KBが仮想メモリにあるかどうかを明確にする必要が出たため、>>14
14(2): デフォルトの名無しさん [sage] 2022/02/27(日) 17:44:54.95 ID:+yReYAPt(3/3) AAS
>>13
時間かかるのが嫌で減らしただけです。。。

ちなみに後ろにウェイト入れて、cat /proc/[pid]/statusした結果
VmHWM: 3296 kB
VmRSS: 3296 kB
VmSwap: 0 kB
なので、rssだけでいいと思います。
で/procに頼った。
結論は仮想メモリ(swap)使ってないよって話だったので、少なくとも俺の環境では元記事とは違いRSSでいいという結論が出て、>12の結論とも整合が取れた。

別にdistro標準(ubuntu 20.04)のgo処理系を使っているので、ソースを引っ張ってくれば簡単に1KBに変更は出来るか確認出来ると思うけど、面倒なのでそこまではしない。
前次1-
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 0.041s