🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
CPU

CPUは、コンピュータの中心となる処理装置(プロセッサ)で中央処理装置とも呼ばれています。プログラム演算や数値計算、その他の演算ユニットをコントロール。スマホやPCによって内蔵されているCPUは異なりますが、処理性能が早いほど良いとされています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

スレッドセーフ

マルチスレッド環境において、複数のスレッド上で常に正常に実行する事が可能なコードを、スレッドセーフなコードと呼びます。

同期

複数のディレクトリに存在するファイルを更新した場合に、すべてのファイルにも更新が行われる事、又は、同じ記憶領域に同時にアクセスして内容の整合性が失われてしまう事をを防ぐ制御などを同期と呼びます。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

Q&A

解決済

1回答

882閲覧

CPUコアが一つのサーバ上で動くウェブアプリケーション内で、sleep(3)やwhile(true)のような待機処理が書かれた際の挙動

raitomata

総合スコア5

CPU

CPUは、コンピュータの中心となる処理装置(プロセッサ)で中央処理装置とも呼ばれています。プログラム演算や数値計算、その他の演算ユニットをコントロール。スマホやPCによって内蔵されているCPUは異なりますが、処理性能が早いほど良いとされています。

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

スレッドセーフ

マルチスレッド環境において、複数のスレッド上で常に正常に実行する事が可能なコードを、スレッドセーフなコードと呼びます。

同期

複数のディレクトリに存在するファイルを更新した場合に、すべてのファイルにも更新が行われる事、又は、同じ記憶領域に同時にアクセスして内容の整合性が失われてしまう事をを防ぐ制御などを同期と呼びます。

非同期処理

非同期処理とは一部のコードを別々のスレッドで実行させる手法です。アプリケーションのパフォーマンスを向上させる目的でこの手法を用います。

0グッド

1クリップ

投稿2019/10/26 10:17

CPUのプロセスとスレッドについて勉強していてふと疑問に思ったことがあります。
どの言語にもおそらく待機させる処理があるかと思いますが

CPUコアを1つだけ積んだサーバー上で、ウェブアプリケーションをワーカー数3で起動していた場合、3人が同時にアクセスしてきて、sleep処理を実行していると4人目は誰かの待機処理及びfunc_Bが終わるまでfunc_Aも実行されない状態になってしまうのでしょうか?

func_A() sleep(3) func_B()

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

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

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

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

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

guest

回答1

0

ベストアンサー

sleep処理を実行していると4人目は誰かの待機処理及びfunc_Bが終わるまでfunc_Aも実行されない状態になってしまうのでしょうか?

ならないです。現代のOSはそんなに単純ではないので安心してください。

まず、sleepを実行したときから、そのアプリケーションはOSに制御を委ねます。文字通りそのアプリケーションは眠った状態になります。OSは別のプロセスに制御を移します。sleepで指定した時間が満了すると、OSはまたそのアプリケーションに制御を移し、そのアプリケーションの実行が再開されます。上記の説明はsleepと言うメソッドの実行を契機として別のプロセスが動く例ですが、、実際はさらに、各プロセスに割り当てた細かい時間単位で制御が移り渡っていきます(時分割/タイムスライス)。スレッドが関係すればさらに細かくなります。

CPUがシングルコアではなく、マルチコア、メニイコアの場合は、良くWEBの記事ではコア1つに対して1スレッドなどと説明がありますが、そうとも限りません。割り当てられなければ1つのコアで複数のスレッドが時分割されて動きますし、反対に複数のコアでもスレッドが1つしか使われないようなケースもあります。


コメントを受けて追記しました:2019-10-27 09:02

※回答欄へのコメントより引用:

(ここでのワーカーはunicornなどでのワーカーです)

前提がそうであると、上記の私の回答は該当しませんね。この場合は質問者さんの疑問どおり、
「ワーカー数3で起動していた場合、3人が同時にアクセスしてきて、sleep処理を実行していると4人目は誰かの待機処理及びfunc_Bが終わるまでfunc_Aも実行されない状態」になります。

手間取りましたが、Ubuntu16上でRuby Sinatra + Unicorn + nginxを使って確認してみました。
unicornを起動した状態が、以下のようであるとします。ワーカープロセスは3881, 3883, 3886の3つです。

bash

1$ unicorn -c unicorn.conf -D 2 3$ ps -ax 4... 5 3879 pts/19 Sl+ 0:00 unicorn master -c unicorn.conf 6 3881 pts/19 Sl+ 0:00 unicorn worker[0] -c unicorn.conf 7 3883 pts/19 Sl+ 0:00 unicorn worker[1] -c unicorn.conf 8 3886 pts/19 Sl+ 0:00 unicorn worker[2] -c unicorn.conf

この状況で Sinatraで造ったWEBアプリを動作させます。http://<server>/test1へのGETで、10秒sleepするだけするものです。処理の前後でタイムスタンプを保存し、レスポンス中にプロセスIDと共にデータとして載せます。

$ cat config.ru require 'rubygems' require 'sinatra/base' class HelloApp < Sinatra::Base get '/test1' do now1 = Time.now sleep(10) now2 = Time.now ts = now1.strftime("%H:%M:%S") te = now2.strftime("%H:%M:%S") s = "PID=#{Process.pid}, s=#{ts}, e=#{te}" return s end end run HelloApp

この状態で、クライアント側からwgetコマンドで3つのリクエストを送ります。3つが受け付けられた後、更に1つのリクエストを送出します。すると、以下のような結果が得られました。

# 1つ目のリクエストでのレスポンス内容 PID=3881, s=08:13:33, e=08:13:43 # 2つ目のリクエストでのレスポンス内容 PID=3886, s=08:13:34, e=08:13:44 # 3つ目のリクエストでのレスポンス内容 PID=3883, s=08:13:36, e=08:13:46 # 4つ目のリクエスト PID=3881, s=08:13:43, e=08:13:53

4つ目のリクエストによるレスポンスが、接続はWEBサーバーであるnginxに受け付けられるものの、実際にUnicornのワーカープロセスの処理に制御に移るのは、1つ目のリクエストの処理が終わったPID=3881のプロセスによるものであることが分かります。

大量の同時リクエストがあったとしてもプロセス数の制限を設けることで堅牢性やメモリ占有率を担保しようとする(<たぶん)Unicornのような形態をとるWEBアプリでは、ワーカープロセスの終了まで長時間占有するような処理はご法度、と言うことですね。数に制限のあるスレッドプールなどにも言えそうです。なお、CPUコアの数が依然として関係ないのは前の回答と同様のはずです。~~なぜならば、Unicorn自体がプロセス数の制限を担っているからです。~~ご質問に提示されたコードと私のコードは、CPUコア数の多少に影響されるものではありません。

技術的な疑問から出た今回のご質問だったと思いますが、1プロセスで長時間占有するようなWEBアプリの処理は考えたことも無かったので、私も勉強になりました。

参考に、確認に使ったunicorn.confの内容とnginxの設定内容を記しておきます。

unicorn.confの内容:

worker_processes 3 listen '/tmp/unicorn.sock' stderr_path File.expand_path('unicorn.log', File.dirname(__FILE__)) stdout_path File.expand_path('unicorn.log', File.dirname(__FILE__)) preload_app true

nginxのconfの内容:(/etc/nginx/sites-available/default)

upstream unicornapps { server unix:tmp/unicorn.sock; } server { listen 80 default_server; listen [::]:80 default_server; root /var/www/html; index index.html index.htm index.nginx-debian.html; server_name _; location / { proxy_pass http://unicornapps; } }

投稿2019/10/26 11:19

編集2019/10/27 00:29
dodox86

総合スコア9256

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

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

raitomata

2019/10/26 12:00

ありがとうございます、ワーカー数が3である場合でもそのように動くのでしょうか? (ここでのワーカーはunicornなどでのワーカーです) ウェブアプリケーション自体がプロセスを最大で3つしかつくらないという事だと思っています。 sleepにさしかかったプロセスはCPUを独占することをやめて、ほかのプロセスがCPUを使うと思いますが、sleepがかかれた実行プロセスは消えるわけではないので、3人(3プロセス)が同時にsleepに差し掛かっている場合、4人目はやはり3人のうち誰かのsleepが終わってくれるまで処理が実行されないということにはなりませんか? 我ながら日本語がわかりづらくてもうしわけないです。。。
winterboum

2019/10/26 21:38

なりません。 『短い時間で切り分けて複数のプロセスを動かしている』 というのがベースです。 多くの場合はプログラムの途中で時間切れで次のプロセスに移ります。 で、 入力待ちなどのときはCPUを遊ばせるのはもったいないので、即座に次のプロセスに移ります。 sleepもその即座の一つです
dodox86

2019/10/27 00:12

> raitomataさん > (ここでのワーカーはunicornなどでのワーカーです) 「ワーカー」と言う単語に「??」と思つつの当初の回答でしたが、なるほどUnicornでしたか。回答は早とちりだったようです。「CPUのプロセスとスレッドについて勉強していて」とご質問の冒頭にあったので、当初の回答で述べたようなことはraitomataさんは理解済みだったのでしょう。大変失礼しました。回答の前提が変わりましたので確認の上、追記しました。ご参照ください。 >winterboumさん フォローありがとうございます。前提条件を私が取り違えていました。1リクエストごとに無尽蔵にプロセスやスレッドを割り当てるケースではないので、それにはあたらなかったようです。ご面倒おかけしました。
raitomata

2019/11/04 10:19

検証までしていただきありがとうございます、大変大変参考になりました。 遅ればせながらベストアンサーを押下させていただきました><
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問