C vs C++ vs Rust Part.3

■ このスレッドは過去ログ倉庫に格納されています
2022/01/27(木) 22:19:47.56ID:avZQ9Wm7
闘え
※前スレ
C++ vs Rust
https://mevius.5ch.net/test/read.cgi/tech/1619219089/
C vs C++ vs Rust Part.2
https://mevius.5ch.net/test/read.cgi/tech/1639539350/
2022/01/27(木) 22:28:23.63ID:4DQKoSsj
前スレまでのあらすじ

---
987 デフォルトの名無しさん sage 2022/01/27(木) 17:14:15.89 ID:hWkHkx2k
>>986
> だから専有機なら上限で用いる
「現在の主流」というのは、「専有機」での話?
それとも一般的な話?

994 デフォルトの名無しさん sage 2022/01/27(木) 17:52:30.63 ID:LojT3k5n
自分が理解できないと相手が敵かつ全て同一人物に見える病気のパターンかねw
皆普通に同じことを指している
何が理解できないのか素直に言ってごらん

995 デフォルトの名無しさん sage 2022/01/27(木) 17:55:13.00 ID:hWkHkx2k
>>994
>>987の質問に答えてから続けてね
2022/01/27(木) 22:58:22.92ID:37eem+FW
あらすじが全くわからんw
2022/01/27(木) 23:13:49.64ID:cK3g3Gve
彼はこの部分がわからなくて連投していたみたいだから横から補足説明しましょう

> 大雑把にI/O観点で二つに分けると
> 昔は同期I/Oでブロックされるからマルチスレッド
> 今は非同期プログラミングでスレッド数はシングルからCPUコア数が上限
> RustのFutureタスク、GoのGoルーチン、JavaScriptの非同期Promiseやコールバック
> いずれもプロセス内スケジューラがI/O多重化(select/epoll)やタイマーなど管理して非同期プログラミングを支えている

昔は自分でOSスレッドを立ち上げて使っていたのに対して
今は自分で立ち上げるのがOSスレッドではなくそれよりも粒度が細かく軽い非同期なタスクで
OSスレッドを立ち上げる役割はそれらタスクの非同期なスケジューリングをするランタイムで
そのスレッド立ち上げ個数は効率最大のためCPUコアスレッド総数と一致するのが望ましいため
GoやRustなどではデフォルト値がそうなっていますよってことですよね
もちろん個数を1個つまりシングルスレッドに設定しても動くところが決定的な違いですね

OSがスケジューリングしてくれるけど重くて大きくリソースを喰うOSスレッドを今は直接使わずに
> RustのFutureタスク、GoのGoルーチン、JavaScriptの非同期Promiseやコールバック
これらのもっと軽くて小さなタスクを使うことで何万も同時に処理できるようになったという話ですね

ちなみにRustでは昔と同じ状況にスレッドとタスクを1:1(=n:n)でも使えますし
シングルスレッドにして1:nでも使えますし上述の状況は汎用的なm:nになりますね
2022/01/27(木) 23:14:48.99ID:fMPJxSq8
明らかに間違ってることを自信ありげに語るのはいつものこと
その人達用の隔離スレだから

>>1
2022/01/27(木) 23:25:15.10ID:iujD8pk9
横から?w
本人だろ、お前w
2022/01/27(木) 23:31:40.86ID:m/Awlcjw
複製おじさんのいつもの自演です
2022/01/27(木) 23:34:30.76ID:iujD8pk9
次はgoogleで2件しかヒットしない、「プロセス内スケジューラ」については説明してくれw
2022/01/27(木) 23:49:40.45ID:cK3g3Gve
非同期タスク群のスケジューリングをするランタイム部分のことではないでしょうか
一般的にプロセスの中に1つだと各スレッドへタスクを割り振るコストが高くて
各スレッドの中に独立して1つずつだと暇なスレッドと多忙なスレッドが偏るデメリットがあり
GoでもRustでもそれらのスケジューリング問題を改善するために
各スレッド内に独立キューを持って効率的に処理しつつもグローバルキューも備えることで解決しているようですね
2022/01/28(金) 00:05:15.17ID:EpTP27or
複製おじはGoでもRustでもまともに非同期プログラミングやったことないんだな
2022/01/28(金) 00:14:38.44ID:9bCXgVDe
>>8
OSスレッドがOSによりスケジューリングされることに対する対比じゃね?
タスクは各プロセスの中にスケジューラーがある
Goは言語ランタイムの中だがRustは各自が好きなのを選んだり自作も可能
2022/01/28(金) 01:31:02.15ID:DUuAybqk
どうせRustは普及しないんじゃないかな、知らんけど。
2022/01/28(金) 08:21:58.40ID:OuJICsLX
rustはc++を食うことがあってもピュアcを食うことはなさそう
2022/01/28(金) 08:42:08.00ID:3x0JFp6u
Cは誤解を恐れずに言えばアセンブリ言語みたいなもんだからな
2022/01/28(金) 13:14:51.22ID:7T77Q24K
>>13
C++ 98以前は Cと似てるし、ライブラリも言語とは無関係に自由に作れたから大丈夫。C++11以後はダメ言語になった。
2022/01/28(金) 13:17:06.82ID:7T77Q24K
そもそも、CやC++が普及したのはTurboCのおかげ。
TurboCはライブラリが分かり易かった。
C++11以後、言語もSTLも両方腐っていてTurboCとは全く違うようになり、
人気もがた落ちになった。
2022/01/28(金) 15:22:28.01ID:ePoQjqFg
何頓珍漢な事言ってんだこのバカ
2022/01/28(金) 18:58:54.57ID:9bCXgVDe
>>8
OSによるプロセスやOSスレッドのスケジューラではなく
プロセスの中で動くタスクのためのスケジューラ
各言語によって言語機能として備えている場合と外部ライブラリによる場合がある

Rustではその中間の形態で言語機能としてはasync/awaitの枠組みのみ提供
さらに標準ライブラリとしてFutureやWakerなどの必要とする定義のみ提供
実際に動作するスケジューラは外部ライブラリで様々な提供がなされ自作もできる
その他はこのスライドの前半の解説など参照

Rustのasync/awaitとスケジューラの話
https://speakerdeck.com/osuke/rust-async-await
2022/01/28(金) 21:04:45.07ID:zI6nuxFY
前スレ946の三つのサイトから数値を入手して和を求める例を練習のためにやってみたんだが
httpのheader取得までとbody取得の2回awaitが入るのがなるほどと思った
あと文字列を数値に変換parseも当然必要だったのでawait部分がちょっと長い
#[async_std::main]
async fn main() -> surf::Result<()> {
let n1 = surf::get("https://httpbin.org/base64/MTEx";); // 111
let n2 = surf::get("https://httpbin.org/base64/MjIy";); // 222
let n3 = surf::get("https://httpbin.org/base64/MzMz";); // 333
let sum = n1.await?.body_string().await?.parse::<i32>()?
+ n2.await?.body_string().await?.parse::<i32>()?
+ n3.await?.body_string().await?.parse::<i32>()?;
assert_eq!(666, sum);
Ok(())
}
利用させてもらったテストサイトはURLで返す値など指定できるhttpbin.org
これで動いて値取得もできて合計値assertも通ったのだが実は落とし穴があることに気付いた
2022/01/28(金) 21:49:38.11ID:YDzvJ7+G
元のJSのコードもだけど
await連発すんなよw
2022/01/28(金) 22:11:12.59ID:zI6nuxFY
そのテストサイトにhttp返答を遅延させるdelay機能があるので試した時に露見した
同時に指定値を返せないようなので数値化と足し算の意味はないが遅延時間を知りたかった
let d1 = surf::get("https://httpbin.org/delay/4";); // 4秒
let d2 = surf::get("https://httpbin.org/delay/5";); // 5秒
let d3 = surf::get("https://httpbin.org/delay/3";); // 3秒
let sum = d1.await?.body_string().await?.parse::<i32>().unwrap_or(0)
+ d2.await?.body_string().await?.parse::<i32>().unwrap_or(0)
+ d3.await?.body_string().await?.parse::<i32>().unwrap_or(0);
結果は12秒かかってしまい期待と異なり直列に実行されていた
肝心なことを忘れていた
2022/01/28(金) 23:09:26.07ID:zI6nuxFY
JavaScriptではPromiseを返す関数を3つ呼べばそれで3つ並行に実行される
しかしRustでは並行に動くタスクを自分で明示的に起動しなければいけなかったのだ
よく考えればGoでも自分で明示的にgoと前置指定することで別goルーチンを起動している
Rustではそれがspawnでありgoと同じくそれによりスケジューラに登録されるようだ
use async_std::task::spawn;
let d1 = spawn(surf::get("https://httpbin.org/delay/4";)); // 4秒
let d2 = spawn(surf::get("https://httpbin.org/delay/5";)); // 5秒
let d3 = spawn(surf::get("https://httpbin.org/delay/3";)); // 3秒
このようにspawnを付けて以降は同じ実行をすると全体で結果5秒となり並行に実行された
言語自体に魔法の仕組みはなく自分で明示的にスケジューラに登録指定するのはわかりやすくて安心した
そのスケジューラも手作りできるらしく興味深い
2022/01/28(金) 23:23:01.28ID:JUEBwV02
自分でblock_on書かないとRustのasyncは身に付かない
■ このスレッドは過去ログ倉庫に格納されています
5ちゃんねるの広告が気に入らない場合は、こちらをクリックしてください。

ニューススポーツなんでも実況