Go language part 4at TECH
Go language part 4 - 暇つぶし2ch999:デフォルトの名無しさん
22/02/26 23:48:39.58 yRlIqUsp.net
>>978
これがなぁ…。過渡期は混ぜるな危険で困らない?そこが不安。
Rustも良いとは思うんだけど、爪切るのにハサミ使ってる気分になる。

1000:デフォルトの名無しさん
22/02/26 23:59:29.99 kpnhrKVl.net
>>982
それはハードによる。
x86はハードウェアでキャッシュコヒーレンシを取ってくれるので実は共有RAMでもコストは安い。
.NETがローカルキューからの取り出しでFIFOとFILOで競合が減るから、というのはそういう事。
Goの場合はARMを見てるのか、MacがARMに乗り換える布石だったのか、
以前からやたら「共有RAMは遅いから使わない」としてきてるが、
ぶっちゃけx86の場合は
(書き込み頻度と量によるが、タスクの起動=関数ポインタ1つと引数のポインタ程度なら)
OSを利用したチャネル接続よりも共有RAMの方が実は速い。
ここら辺を理解してない奴がグダグダやってるからチューニングし切れてないのだと思うよ。

1001:デフォルトの名無しさん
22/02/26 23:59:34.35 4mZJSMD8.net
>>980
>> Goみたいに100,000goroutineとか目指す場合は分かるけど、Rustは基本そうじゃないだろうから、
Rustの非同期タスクはGoroutineよりも更に軽くて
Goとは異なりスタックレスなので付加メモリ消費も非同期ランタイムの管理データ分の1タスクあたり64bytesで済みますよ
そしてグローバルキュー競合コストの件は>>982のように同じですね

1002:デフォルトの名無しさん
22/02/27 00:02:30.74 2GGoVw4G.net
>>982
問題があると言っているわけじゃなくて、VMやOSじゃなければプリエンプションできないからどうやっているのかなと。

1003:デフォルトの名無しさん
22/02/27 00:03:38.38 uWHjNeVw.net
>>973
Cはお爺ちゃんだから…
Cからの乗り換えコストっていう視点でどうかひとつ
あ、でも実装系別の頭おかしくなるコンパイルオプションやらバウンダリやらのメモリモデル考えると、Goのほうが実質勝ってないか学習コスト?

1004:デフォルトの名無しさん
22/02/27 00:11:21.81 uWHjNeVw.net
>>973
ちなみに速さやらサイズでは当然にCとかの圧勝だろ普通に
関数呼び出しごとにオーバーヘッドのかかるGoが単純な速度で勝てる道理はない

1005:デフォルトの名無しさん
22/02/27 00:23:35.14 uWHjNeVw.net
>>973 C#というか.Netのwpfは好き 一般的な手法じゃないだろうけど、MVVMのVM部分を単体テストできて(ディスパッチャ細工してメインスレッドで走らせる)



1007:デフォルトの名無しさん
22/02/27 00:44:59.79 PVy06kKY.net
>>985
> Goとは異なりスタックレスなので
やたらこれを強調しているが、goでもgoroutineにローカルキュー(=関数ポインタの配列)を用意して、順に食わせれば、
各タスク毎にスタックを用意する必要なんて無くて、普通にエミュレーション出来るよ。
(ただしGo信者的にはこれは負けだからやらないとも思うが)
ただこの場合、各タスクが止まらない前提ならこれでいいが、
止めて切り替える分には一般的にはスタック領域が必要になる。
(自動変数を全部ヒープ上に確保すればスタック無しでもいいが、これは遅くなるので多分やってないと思う)
ユーザーが確保しなくていいだけで、実際はランタイムかコンパイラが確保してくれてるだけじゃないか?

1008:デフォルトの名無しさん
22/02/27 00:50:50.94 PVy06kKY.net
>>988
> 関数呼び出しごとにオーバーヘッドのかかるGo
かからないような気がするが、自信はない。かかる理由って何?

1009:デフォルトの名無しさん
22/02/27 02:41:36.05 uWHjNeVw.net
>>991
Goは関数呼び出しごとにスタックをチェックして、不足してたなら拡大するから
関数ごとの静的な自動変数サイズと比較してるだけだと思うけど、そういう処理のおかげで初期スタックサイズを抑えてる
URLリンク(postd.cc)

1010:デフォルトの名無しさん
22/02/27 02:47:33.19 uWHjNeVw.net
>>991
「十分な空間がない場合、ランタイムはヒープに対して大きなスタックセグメントを割り当て、現在のスタックの内容を新しいセグメントにコピーし、古いセグメントを解放し、それから関数呼び出しを再開します。」

1011:デフォルトの名無しさん
22/02/27 03:00:02.25 uWHjNeVw.net
>>991
毎回拡張する訳じゃないけどそのためのチェックは毎回走るんで、単にサブルーチンを呼ぶだけの他言語よりは余分な仕事をしている
おそらくチェックは必要な回数だけだとは思う(ループ内での呼び出しとかの最適化は考えてないとは思わないから)

1012:デフォルトの名無しさん
22/02/27 06:52:35.32 +yReYAPt.net
compiler explorer(URLリンク(godbolt.org))で、goコンパイル結果を普通のamd64用のアセンブラ見ること出来ないの?(Plan9でなく)

1013:デフォルトの名無しさん
22/02/27 07:42:28.85 uWHjNeVw.net
次スレ建ててくる

1014:デフォルトの名無しさん
22/02/27 07:44:00.44 uWHjNeVw.net
Go language part 5
スレリンク(tech板)

1015:デフォルトの名無しさん
22/02/27 07:56:25.05 nXG/aSfD.net
>>990
Rustの非同期タスクは内部的には単純な状態マシンとなり何度も再入可能なコルーチンと同じ状況になります
その中の変数はRustのクロージャがその環境の変数をキャプチャするのと同じだからもちろんメモリを確保します
だからスタックレスで何度も呼べるクロージャみたいな状況でスタック自体はプロセス全体で1本のままとなります
もちろんその非同期タスクから他の非同期でない普通の関数を呼べば通常と同じくスタックが伸びて使われていきます
一方でその非同期タスクから他の非同期な関数を呼ぶとその非同期タスクから一旦離脱してスケジューラーへ戻ります
最初に書いたように「単純な状態マシンとなり何度も再入可能なコルーチン」となっているので再び再開できます
以上がスタックレスなのにRustの非同期タスクがメモリの許す限り多く動くことができる仕組みです

1016:デフォルトの名無しさん
22/02/27 08:07:16.26 c9v4owXb.net
ワッチョイ無しかー(´・ω・`)

1017:デフォルトの名無しさん
22/02/27 08:16:41.16 +yReYAPt.net
goroutineとC++標準ライブラリのスレッドを比較するために>>957のmain.rsのC++版だけ作ってみた(ループは一桁減らした)
$ cat main.cc
#include <thread>
#include <chrono>
#include <vector>
using namespace std;
using namespace std::chrono;
int main() {
vector<unique_ptr<thread>> threads;
for (uint32_t i = 0; i < 1000; ++i) {
threads.emplace_back(
make_unique<thread>([=]{
uint64_t bad_hash = (i * 2654435761) % 200000;
this_thread::sleep_for(microseconds(bad_hash));
for (uint32_t _ = 0; _ < 1000; ++_) {
this_thread::sleep_for(10ms);
}
})
);
}
for (auto const& t: threads) {
t->join();
}
return 0;
}
$ g++ -O3 -pthread main.cc -o main && ./t ./main
real 11.04s
user 0.93s
sys 2.95s
rss 11328k
$
結果はmain.rsとほぼ同じで、やはりスレッド起動コストがデカく、rssもデカい

1018:1001
Over 1000 Thread.net
このスレッドは1000を超えました。
新しいスレッドを立ててください。
life time: 468日 4時間 2分 1秒

1019:過去ログ ★
[過去ログ]
■ このスレッドは過去ログ倉庫に格納されています


最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch