[過去ログ] Go language part 4 (1002レス)
前次1-
抽出解除 必死チェッカー(本家) (べ) 自ID レス栞 あぼーん

このスレッドは過去ログ倉庫に格納されています。
次スレ検索 歴削→次スレ 栞削→次スレ 過去ログメニュー
935: デフォルトの名無しさん [sage] 2022/02/26(土) 01:11:35 ID:kpnhrKVl(1/10) AAS
>>915
915(1): デフォルトの名無しさん [sage] 2022/02/25(金) 11:57:21 ID:ifNOEbaN(2/2) AAS
>>912
2番で良いも何も無くて、まず「全てにおいて1番というシンプルな解は無い」なんよ。
だから「Rustが1番、Goが2番、でも書きやすいからGoを使う」という発想がおかしい。
「この案件にはGoが1番良い」という発想でGoを選定するんよ。
科学分野での競争を強いられた結果、道具が先鋭化しただけでしょ。十分に1番を目指してるよ。

プログラミングのパラダイムとしてのasyncであれば、goは同期関数のように書いてもほぼ全ての行に対してasync/awaitだよ。それがgoroutineなんよ。mainもgoroutineだからね。
それをN:Mスレッドで回すの。

try-catchが全てにおいて良いかと言うとそうでもないから、goは多値で返したんよ。
そうではない言語であればtry-catchは必要だと思うよ。
そしてasync/await・Promise以前のtry-catchは使い物になりません。
> だから「Rustが1番、Goが2番、でも書きやすいからGoを使う」という発想がおかしい。
この発想は俺は別におかしいとは思ってない。
例えばアメリカでは「Pythonで書け」と言われるらしいが、これは、
「Pythonは糞だが誰でも読める。前任者がいなくなっても後任者がすぐ見つかる」からであり、
自分個人で完結する物以外は言語特性や好みだけで選べるものでもない。
だからWeb系なら「とりあえずJS/TSで書け」となるのが妥当、という話はすでに788でした通り。
が、まあ、これはさておき、

> 「この案件にはGoが1番良い」という発想でGoを選定するんよ。
だからこれは何なんだよ?という話だろ。Web系ではない、というか、
TS/Node/Rustが出てきた時点でWeb系に最適な解ではなくなったというのは792,857で言ったとおり。

> プログラミングのパラダイムとしてのasyncであれば、
> goは同期関数のように書いてもほぼ全ての行に対してasync/awaitだよ。それがgoroutineなんよ。
これは言いすぎだが、goroutineでasyncの代替になるのは事実だ。
ただ、そういう書き方って基本的にしてないでしょ。
多くの人はマルチスレッドだと思って書いてるし、Goの公式ドキュメントもそうだったと思ったが。
(goroutineは非同期を実現するための物です!!!なんて謳ってたっけ?)

マルチスレッド:同期関数を実行するスレッドが沢山。
 単に高火力を必要とするならスレッドを複数起動して既にあるコードをぶち込めばOK。
非同期:非同期ジョブは『どの順で完了しても』問題なく動くように書く必要があり、
 また、非同期ジョブの実行順/完了順の指定も出来ない。
 (だから数珠繋ぎにするしかなく、コールバック地獄だPromiseだ、という話になる)

だから非同期の場合は根本的にマルチスレッドとはプログラミングを変える必要があって、
具体的にはイベントドリブンで書く事になる。だからJSにはmainがない。
ところがGUIもイベントドリブンで書くので、元々GUI担当のJSとは相性がいい。
(というか、だから当時は異端でしかない「非同期」を採用したのかもしれないが)
936: デフォルトの名無しさん [sage] 2022/02/26(土) 01:11:53 ID:kpnhrKVl(2/10) AAS
逆にmainがあるのは、
mainから入って、高火力が必要ならスレッド起動で同じコードを走行させる、という
マルチスレッドのパラダイムに適した構造だ。
だからmainがある言語、例えばCでGUIを書くと悲惨なコードになる。元々イベントドリブン向きに出来てないからだ。
Goも同じで、基本的にはfork/joinを完結にgoroutineで出来るようにしてるだけで、それはマルチスレッド向けだよ。

つっても非同期スタイルで書けば書けるのも事実だけどな。
819のベンチでGoはAsynchronousTCPとなってるが、これはそういう事なのかね?
なおNode(multithread)に1.5倍も負けてるのは、多分ランタイムの問題だよ。
JSは非同期専用のランタイムであり、それに対してマルチスレッド向けのランタイムに非同期コードを載せて非同期にしたくらいでは並べない。
というか、静的コンパイル言語がJITとはいえ動的言語に大差で負けてる事自体があり得ない事で、
これは「同じ土俵で戦えていない」事を意味する。一つはランタイムで、本来は、
・精々マシンスレッドと同程度〜数倍程度のgoroutine用
・マシンスレッドの100-1000倍以上程度のgoroutine用
・非同期コード用
とチューニングや内部構造を変えたランタイムを用意すべきだよ。
資産はコードであり、ランタイムは交換すればいいだけなので、やればいいだけだと思うのだけど。(もうやってるかもしれないが)

あとついでに言うと、ランタイムはやっぱりC/C++で書くべきだよ。境界チェックを遅くなる言い訳にするのなら特に。
Go/Rust共に、「これでCのコードはなくなりました!えっへん!」ってな事をやってたと思ったが、
ランタイムが遅いようでは勝負にならないからね。
「GoをメンテするためにはGoだけ知っていれば十分で、Cを知っている必要はない」ってのはコミュニティの宗教として重要なのは分かるけども、
実用性を考えたら、ランタイムなんて糞速い事が重要であって、何言語だっていいでしょ。
この辺、スクリプト言語はDSLだとわきまえてて、ランタイムを自言語で書こうとかいう無駄な事をやってない。
937
(1): デフォルトの名無しさん [sage] 2022/02/26(土) 01:13:02 ID:kpnhrKVl(3/10) AAS
> そしてasync/await・Promise以前のtry-catchは使い物になりません。
これは言いすぎ。try-catchはろくでもないが、無いよりはましだし、同期でシングルデータならまあ問題ない。
だからGoもtry-catchでも良かったはずだが、採用してないところを見ると、
「多くの場合はtry-catchがgoroutineを跨いで使い物にならない」と思ったのだろう。
ゆうてもGo流の多値返しはCよりはまし程度で、それ以上でもないが。

ただ、try-catchがgoroutineを跨ぐ想定なら、
メインスレッドが仕事を起動し、各goroutineで子細の処理をこなす、マルチスレッドの構造を想定している。
非同期なら、メインスレッドはイベントループだけを担い、手が空いたgoroutineにその都度ジョブを発給する事になるけども、
この場合はジョブの起動はgoroutine内からで、try-catchは完全に機能する。
JSの場合はI/Oを非同期にする事を義務づけらてるからtry-catch内にI/Oが入った時点で意味を為さないし、大体このパターンだが、
Goの場合はI/Oも同期で書けるのだから、全く問題ない。
だからやっぱり元々の想定はマルチスレッドで、文法的には非同期も特に苦労せずに書ける、ってことだと思うのだけど。
(JS的な全面的非同期を想定していた場合は、try-catchを不採用にする理由がない。当時でも既にtry-catchが主流だった)

>>917
917(1): デフォルトの名無しさん [sage] 2022/02/25(金) 12:10:17 ID:aDhOSI3t(2/4) AAS
>>912
RustはGoと異なり非同期タスクをスタックレスで実現している上に
RustはGoと同じくtry-catchを採用していないね
> RustはGoと同じくtry-catchを採用していないね
これ、今見たところPanic方式らしいが、もしかしてGo由来?

try-catchは好きな人は大好きのようだが、俺にはどうにもあれがいいとは思えない。
個人的には、リソース返却ならC#のusingが正解で、
リトライなら、大体元データが壊れてて無理で諦めるのでPanicで問題ない。(エラー通知だけ出来れば十分)
だからtry-catchは非同期では使えない過去の異物として消滅して欲しかったのだけど、
C#がasyncでも無理矢理try-catch出来るようにしたのでちょっと驚いてる。
そこまでしてtry-catchしたくもないし、する内容もないんですけど、ってね。
ある意味JSの「catchなんてしなくても何も問題ないです」というJavaから見れば卒倒しそうな仕様も、解の一つではあると見てる。
941: デフォルトの名無しさん [sage] 2022/02/26(土) 08:45:19 ID:kpnhrKVl(4/10) AAS
>>938
938(1): デフォルトの名無しさん [sage] 2022/02/26(土) 06:42:38 ID:BX4iLvdt(1/2) AAS
>>937
JavaScriptの非同期呼び出しでも普通は無視せずPromiseにcatch付けて捕獲するぜ
例: async_func_foo.catch(err => console.log(err))
あとRustの非同期呼び出しもResultが帰ってくるからエラーを捕獲できる
> 例: async_func_foo.catch(err => console.log(err))
これは字が赤いか黒いかの違いしかないけどな。

まあ俺はtry-catch消極派だから、Go/Rust方式で問題なく、C#の仕様はオーバースペック過ぎるけど、
Goの場合はJSとは違ってtry-catchはそれなりに機能するはずだから、不満持ってる奴もそれなりにいるはずだけど。
(そういう連中は既に去ってる気もするが)
949
(1): デフォルトの名無しさん [sage] 2022/02/26(土) 10:19:30 ID:kpnhrKVl(5/10) AAS
>>943
943(2): デフォルトの名無しさん [sage] 2022/02/26(土) 09:10:48 ID:yRlIqUsp(2/9) AAS
goだと、非同期スタイルで書けるとかでなくて、ブロッキング関数、同期関数を書いたとしてもgoroutine間では適切にスイッチングされて、他の言語で言うawaitがかかってるんよ。常に低コストで。
それはN:M軽量スレッドだからなし得ることなので、他の言語ができてない以上何とも比べづらい。
> ブロッキング関数、同期関数を書いたとしてもgoroutine間では適切にスイッチングされて、他の言語で言うawaitがかかってるんよ。
これは普通はマルチスレッドと言う。Thread/goroutineを複数(マルチ)起動して引っかかったらスイッチングさせるだけなのだから。
そして大概の言語はこれを自然に書けるようになってる。

> それはN:M軽量スレッドだからなし得ることなので、他の言語ができてない以上
これが嘘、というか誤解。他言語でもいくらでもスレッドを起動する事は出来る。(が余計に重くなるので普通はやらない)
goroutineもGo信者が言う程軽くもないのでいくらでも起動していいわけではない。(現実的には)

これを脳死でgoroutineはコストゼロ、だからgoroutineに切り出す事がプログラマの仕事である、と解釈できれば美しいのだが、
これを実際に試して「思ってたよりも全然パフォーマンスが出ねぇ、これならNodeの方が速ぇ…」となった顛末を書いてたのが何度も言ってるブログ。
これは言語と言うよりはランタイムの問題だけど。
962
(1): デフォルトの名無しさん [sage] 2022/02/26(土) 16:17:55 ID:kpnhrKVl(6/10) AAS
>>951
951(2): デフォルトの名無しさん [sage] 2022/02/26(土) 12:15:41 ID:pDCyYMqI(1/2) AAS
>>949
N:Mのグリーンスレッドであって単なるマルチスレッドじゃない。
単に引っかかったら切り替えるんでなくてスティーリングまでやるのは他の言語の言語標準機能にはErlangぐらいにしかない。

どこが嘘なんよ。
コストゼロでは無いが、いわゆるスレッドよりは遥かに軽いぞ。
やってないのはやる必要がないから。
他言語も馬鹿ではないので、改善の努力はしてるし、いい点があったら平気でパクってる。

(Goはgreenthreadで全て解決!と謳っているわけではないけども、そうだとしたら)
そのアイデアは面白かったが、現実的ではなかった。
(ただしこれはランタイムの問題だから改善の余地はあるはず)

非同期はコードがうざくなるのは事実だが、async文法でほぼ払拭された。
だからみんなパクってる。

まあ完全にループだし、材料枯渇でここら辺で終わりかな。
そりゃ信者の念仏を何度聞いても翻意する事はないよ。俺は文系ではないし。
こちらの見解では説明出来ないデータが出て来たら、分析して、考えを修正するけど。

>>957
957(3): デフォルトの名無しさん [sage] 2022/02/26(土) 13:27:19 ID:fRC8OZTs(1/2) AAS
Goの(疑似スレッド+)goroutineのパフォーマンス計測っていいやつないの?
↓見つけたやつ
Goroutines Are Not Significantly Smaller Than Threads
外部リンク[html]:matklad.github.io
virtualの40MBを単純に合算したら、今は4倍軽くて、4k/goroutine時代は2.5倍軽かったという事か。
フットプリントだけの比較ではあるが。
だから極めて単純に言えば、他言語のスレッドでジョブを4つずつ束ねて処理する運用をすれば、
フットプリントでは並んで、速度は余分なスケジューラが入ってない分勝てる事になる。
973
(3): デフォルトの名無しさん [sage] 2022/02/26(土) 20:31:14.25 ID:kpnhrKVl(7/10) AAS
>>969
969(1): デフォルトの名無しさん [sage] 2022/02/26(土) 19:13:38.66 ID:nWK21oqu(2/3) AAS
正直なんだかんだ言って、学習コストに対しての性能パフォーマンスが異様に高いというところがGoの魅力
言語仕様がコンパクトだからミスしにくい(気がする)のも良い
チャネルに容量があることを忘れるうっかりさん以外には

得意な機能は限られててGUIとかは苦手だけど、そんなもんC#やらに任せとけばいいや
> 学習コストに対しての性能パフォーマンスが異様に高い
Cの方が高いけどな。Goよりも小さい仕様で速い。
あとC#もGUIはゴミだぞ。それ以外がいいからunityを制覇してるが。
976
(1): デフォルトの名無しさん [sage] 2022/02/26(土) 21:58:06.53 ID:kpnhrKVl(8/10) AAS
>>974
974(2): デフォルトの名無しさん [sage] 2022/02/26(土) 21:20:48.95 ID:4mZJSMD8(1/4) AAS
>>943
>> それはN:M軽量スレッドだからなし得ることなので、他の言語ができてない以上何とも比べづらい。

RustもM:Nモデルだよ
Goと同じく複数の非同期タスクを複数のOSスレッドに割り当て
しかもGoとは異なりスタックレスなのでGoよりも軽量タスクを実現しているよ

>>951
>> スティーリングまでやるのは他の言語の言語標準機能にはErlangぐらいにしかない。

RustもGoと同じM:Nモデルでワークスティーリングもしているよ
Rustでは以下のランタイムを選ぶことができるよ
・1:1モデル (=M:Mモデル、OSスレッドそのまま利用)
・M:1モデル (シングルOSスレッドで並行マルチタスク)
・M:Nモデル[スレッドプール方式]
・M:Nモデル[ワークスティーリング方式]
それ以下と定義が同じだと、一般的には「ワークスティーリング方式」を「スレッドプール」と呼称するよ。(だからC#のもこれのはずだけど)
外部リンク:tech-blog.optim.co.jp
Rustで何故あえて方言にしているのかは知らん。
というかワークスティーリングじゃない方のメリットなんてない気がするんだが。
980
(2): デフォルトの名無しさん [sage] 2022/02/26(土) 22:54:22.46 ID:kpnhrKVl(9/10) AAS
>>979
979(1): デフォルトの名無しさん [sage] 2022/02/26(土) 22:13:34.76 ID:4mZJSMD8(3/4) AAS
>>976
そこは一般的は話としてまずOSスレッド毎にキューと持つかグローバルにキューを持って割り振るかの2大方式があるよ
それぞれに利点と欠点があってそこは省略するけど
GoもRustもそのハイブリッド方式となっていて普段はスレッド毎にキューを持って各OSスレッドが独立に効率よく処理だね
そしてGoもRustもグローバルにも管理して暇なOSスレッドが生じるとそこへ割り振る(OSスレッドから見るとスティール)するよ
詳細はここで書ききれないほどもう少し複雑だから省略してる点はそれぞれの解説サイトなどを見てね
Goと同じなら805のリンクの内容と同じだからああそうですか程度。
資料が古いがC#のは以下で確認した。同様にハイブリッドでスティーリングもあり。
(ただ.NET6.0とかだともう変わってそうだが)
外部リンク[html]:ufcpp.net
基本グローバルキューで、ただし優先順位はローカルキュー>スティーリング>グローバルキューになってる。
この構造はまあ納得。

> GoもRustもそのハイブリッド方式となっていて普段はスレッド毎にキューを持って各OSスレッドが独立に効率よく処理だね
> そしてGoもRustもグローバルにも管理して暇なOSスレッドが生じるとそこへ割り振る(OSスレッドから見るとスティール)するよ
無駄に複雑で余計に遅くなると思うけどね。.NETの方が単純ですっきりしてていい。
グローバルキューから取り出す時の競合を気にしてるのなら、
Goみたいに100,000goroutineとか目指す場合は分かるけど、Rustは基本そうじゃないだろうから、チューニングミスだと思うけど。
984: デフォルトの名無しさん [sage] 2022/02/26(土) 23:59:29.99 ID:kpnhrKVl(10/10) AAS
>>982
982(3): デフォルトの名無しさん [sage] 2022/02/26(土) 23:40:35.78 ID:BX4iLvdt(2/2) AAS
>>977
VMじゃないと起きる問題点は何?
いずれにせよC/C++/RustはVMでもOSでも記述できるのだからそこに不可能は無い

>>980
言語に関係なくシステムスレッド間のグローバルな操作はデータ競合回避など一定のコストがかかる
だから可能な限り個別にシステムスレッドが動くようにしつつアイドルが出ないよう最小限のグローバル操作
この部分はよほど上位で制約のある仕様としていないならば全ての言語で同じ
それはハードによる。
x86はハードウェアでキャッシュコヒーレンシを取ってくれるので実は共有RAMでもコストは安い。
.NETがローカルキューからの取り出しでFIFOとFILOで競合が減るから、というのはそういう事。
Goの場合はARMを見てるのか、MacがARMに乗り換える布石だったのか、
以前からやたら「共有RAMは遅いから使わない」としてきてるが、
ぶっちゃけx86の場合は
(書き込み頻度と量によるが、タスクの起動=関数ポインタ1つと引数のポインタ程度なら)
OSを利用したチャネル接続よりも共有RAMの方が実は速い。
ここら辺を理解してない奴がグダグダやってるからチューニングし切れてないのだと思うよ。
前次1-
スレ情報 赤レス抽出 画像レス抽出 歴の未読スレ AAサムネイル

ぬこの手 ぬこTOP 4.756s*