{
    "componentChunkName": "component---src-templates-blog-post-jsx",
    "path": "/post/learn-multi-thread-and-multiplexing/",
    "result": {"data":{"site":{"siteMetadata":{"title":"WEB EGG","author":"Leko - CTO at Yuimedi"}},"markdownRemark":{"id":"2f32dcf1-cb6c-5b45-afe7-04da28ab5c53","excerpt":"たまにはまとまってない情報を書いてもいいじゃないかということで、表題の通り暫定版です。 まえおき Nodejsのclusterモジュールのドキュメントを読んでいて、 「ほぉ、並列化って簡単にできるんだなぁ」と感じつつ、関連記事をいろいろ調べてみると、 並列化すればスループットが上がる マルチコアの場合は有用。CPU…","html":"<p>たまにはまとまってない情報を書いてもいいじゃないかということで、表題の通り暫定版です。</p>\n<h2 id=\"まえおき\" style=\"position:relative;\"><a href=\"#%E3%81%BE%E3%81%88%E3%81%8A%E3%81%8D\" aria-label=\"まえおき permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>まえおき</h2>\n<p>Nodejsの<a href=\"https://nodejs.org/api/cluster.html\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">cluster</a>モジュールのドキュメントを読んでいて、<br>\n「ほぉ、並列化って簡単にできるんだなぁ」と感じつつ、関連記事をいろいろ調べてみると、</p>\n<ul>\n<li>並列化すればスループットが上がる</li>\n<li>マルチコアの場合は有用。CPUのコア数と同じにすると良い</li>\n<li>ワーカーやアプリケーションサーバなどは横に並べとけ</li>\n</ul>\n<p>的な記述が色々あり、違和感を感じました。<br>\nGoなどのマルチスレッドができる言語でやる”並列化”と私が調べているものは別物なのでは？ と。</p>\n<p>ということで、身近な頼れる方々へ聞いて調べて考えた結果の暫定的な理解を書き留めておきます。 理解に誤りがあったら指摘もらえると喜びます。</p>\n<p>パフォーマンスチューニングや<a href=\"https://ja.wikipedia.org/wiki/%E3%82%B9%E3%83%AC%E3%83%83%E3%83%89%E3%82%BB%E3%83%BC%E3%83%95#.E3.82.B9.E3.83.AC.E3.83.83.E3.83.89.E3.82.BB.E3.83.BC.E3.83.95.E3.81.8B.E3.81.A9.E3.81.86.E3.81.8B.E3.81.AE.E5.88.A4.E6.96.AD.E5.9F.BA.E6.BA.96\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">スレッドセーフであるための4条項</a>とかそういう込み入った話ではなく、浅い話です。</p>\n<!--more-->\n<h2 id=\"用語の整理多重化と並列化とマルチプロセス化は別物である\" style=\"position:relative;\"><a href=\"#%E7%94%A8%E8%AA%9E%E3%81%AE%E6%95%B4%E7%90%86%E5%A4%9A%E9%87%8D%E5%8C%96%E3%81%A8%E4%B8%A6%E5%88%97%E5%8C%96%E3%81%A8%E3%83%9E%E3%83%AB%E3%83%81%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E5%8C%96%E3%81%AF%E5%88%A5%E7%89%A9%E3%81%A7%E3%81%82%E3%82%8B\" aria-label=\"用語の整理多重化と並列化とマルチプロセス化は別物である permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>用語の整理。多重化と並列化とマルチプロセス化は別物である</h2>\n<p>たとえば、Goで並列処理をする場合、<a href=\"https://tour.golang.org/concurrency/1\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">goroutine</a>を使用すると思います。<br>\njsで複数の非同期処理を同時に行おうとした場合、<a href=\"https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Promise.all</a>を使用すると思います。<br>\n<a href=\"https://devcenter.heroku.com/articles/node-concurrency\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">Herokuの記事</a>によると、Nodeでワーカーの並列度を最適化するには、<a href=\"https://github.com/hunterloftis/throng\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">throng</a>などのクラスタリングマネージャを使用して、マルチプロセス化したら良いと思う的なことが書かれています。</p>\n<p><strong>一体なにがどれにあたるんだ、違いがわからん</strong> と思っていたのですが、<br>\nJavaScript(Nodejs)はマルチコアな筐体で動作させたとしても、あくまで <strong>シングルスレッド</strong> な言語であるという点から整理すると、</p>\n<ul>\n<li>多重化\n<ul>\n<li>1つのCPUを複数のタスクでシェアし、待ち時間を減らしマルチスレッドかのように振る舞うこと</li>\n<li>jsの非同期処理や、PHPの<a href=\"http://php.net/manual/ja/function.curl-multi-exec.php\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">curl_multi</a>はこれ</li>\n<li>シングルコアで動くgoroutineもこれ</li>\n</ul>\n</li>\n<li>並列化\n<ul>\n<li>複数のCPUを使用し、それぞれに異なる計算をさせること</li>\n<li>マルチコアで動くgoroutineはこれ</li>\n</ul>\n</li>\n<li>マルチプロセス\n<ul>\n<li>プログラム中のある処理ではなく、プロセス自体を横に並べること。多重化や並列化とは別枠というか、比べる対象ではない</li>\n<li><a href=\"http://php-fpm.org/\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">PHP-FPM</a>やNodeのclusterモジュールがこれ</li>\n</ul>\n</li>\n</ul>\n<p>と理解しました。 多重化と並列化は置いといて、マルチプロセスについてより詳細にまとめていきます。</p>\n<h2 id=\"マルチプロセスの数はいくつが良いのか\" style=\"position:relative;\"><a href=\"#%E3%83%9E%E3%83%AB%E3%83%81%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E3%81%AE%E6%95%B0%E3%81%AF%E3%81%84%E3%81%8F%E3%81%A4%E3%81%8C%E8%89%AF%E3%81%84%E3%81%AE%E3%81%8B\" aria-label=\"マルチプロセスの数はいくつが良いのか permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>マルチプロセスの数はいくつが良いのか</h2>\n<blockquote class=\"twitter-tweet\" data-conversation=\"none\" data-cards=\"hidden\" data-lang=\"ja\">\n  <p lang=\"ja\" dir=\"ltr\">\n    <a href=\"https://twitter.com/L_e_k_o\">@L_e_k_o</a> 何をやろうとしてるかわからんけど、node なら 1 core 1 proc で Load Average がコア数に近似する性能を目指せばいいと思う。使ったことないけど rxjs-cluster っての見つけた。<a href=\"https://t.co/QjSFZfg1K9\">https://t.co/QjSFZfg1K9</a>\n  </p>&mdash; けん⚡ (@ken_zookie)   \n  <a href=\"https://twitter.com/ken_zookie/status/753847655789309952\">2016年7月15日</a>\n</blockquote>\n<blockquote class=\"twitter-tweet\" data-lang=\"ja\">\n  <p lang=\"ja\" dir=\"ltr\">\n    <a href=\"https://twitter.com/L_e_k_o\">@L_e_k_o</a> top コマンドで見える LoadAverage の値がCPUの数と同じであればちょうどCPUの性能を使いきれている、という見方ができる。過負荷試験とかで、どのプロセス数のパターンが最も優れているかの指標になる。\n  </p>&mdash; けん⚡ (@ken_zookie)   \n  <a href=\"https://twitter.com/ken_zookie/status/753849205827919872\">2016年7月15日</a>\n</blockquote>\n<p>頼れるパイセンがアドバイスをくれた。<br>\nなんとなーくCPUのコア数と同じって理解だったのが、<br>\n<code>LoadAverage</code>という値がCPUのコア数と同じになるように調整すれば良いと判明。</p>\n<p>なのでプロセスの数自体はCPUのコア数と必ずしも一致しない模様。</p>\n<h2 id=\"ロードアベレージって何\" style=\"position:relative;\"><a href=\"#%E3%83%AD%E3%83%BC%E3%83%89%E3%82%A2%E3%83%99%E3%83%AC%E3%83%BC%E3%82%B8%E3%81%A3%E3%81%A6%E4%BD%95\" aria-label=\"ロードアベレージって何 permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>ロードアベレージって何</h2>\n<blockquote>\n<p>load averageとは ロードアベレージはシステム全体の負荷状況を表す指標。<br>\n「1CPUにおける単位時間あたりの実行待ちとディスクI/O待ちのプロセスの数」で表される。<br>\nシステムのスループットを上げたい場合はロードアベレージを下げることを目標にする。 <a href=\"http://qiita.com/k0kubun/items/8065f5cf2da7605c8043\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">load averageを見てシステムの負荷を確認する – Qiita</a></p>\n</blockquote>\n<p>この引用部分だけでは <strong>低ければ低いほど良い</strong> ように見えますが、<br>\nCPUコア数よりLoadAverageが高い場合は処理待ちが発生しており、逆に低すぎるとCPUパワーを余らせていることになる</p>\n<p>なのでCPUのコア数より高い場合は下がるように改善を。<br>\n低すぎる場合は、余ってるマシンパワーを活かすようにプロセス増やしたりCPU負荷が高いけど高速な処理に変えたりと性能改善が可能</p>\n<h2 id=\"マルチプロセスはどのレイヤが担うべきなのか\" style=\"position:relative;\"><a href=\"#%E3%83%9E%E3%83%AB%E3%83%81%E3%83%97%E3%83%AD%E3%82%BB%E3%82%B9%E3%81%AF%E3%81%A9%E3%81%AE%E3%83%AC%E3%82%A4%E3%83%A4%E3%81%8C%E6%8B%85%E3%81%86%E3%81%B9%E3%81%8D%E3%81%AA%E3%81%AE%E3%81%8B\" aria-label=\"マルチプロセスはどのレイヤが担うべきなのか permalink\" class=\"autolink-header before\"><svg aria-hidden=\"true\" focusable=\"false\" height=\"16\" version=\"1.1\" viewBox=\"0 0 16 16\" width=\"16\"><path fill-rule=\"evenodd\" d=\"M4 9h1v1H4c-1.5 0-3-1.69-3-3.5S2.55 3 4 3h4c1.45 0 3 1.69 3 3.5 0 1.41-.91 2.72-2 3.25V8.59c.58-.45 1-1.27 1-2.09C10 5.22 8.98 4 8 4H4c-.98 0-2 1.22-2 2.5S3 9 4 9zm9-3h-1v1h1c1 0 2 1.22 2 2.5S13.98 12 13 12H9c-.98 0-2-1.22-2-2.5 0-.83.42-1.64 1-2.09V6.25c-1.09.53-2 1.84-2 3.25C6 11.31 7.55 13 9 13h4c1.45 0 3-1.69 3-3.5S14.5 6 13 6z\"></path></svg></a>マルチプロセスはどのレイヤが担うべきなのか</h2>\n<p>最後。Nodejsにはclusterやchild_processなどのモジュールが組込みモジュールとして提供されている。<br>\nこれはもう「アプリケーションをマルチプロセス化して下さい」と言っているようなものなのではないか…？<br>\nHerokuもthrongという簡易クラスタリング用のライブラリを使った例を出していたりする。</p>\n<p>phpにも<a href=\"http://php.net/manual/en/book.pcntl.php\" target=\"_blank\" rel=\"nofollow noopener noreferrer\">pcntl</a>というプロセス制御の拡張機能がある。 シングルスレッドの言語でもプロセスを並べれば、スレッドをロックするようなsleep関数等もプロセスマネージャが多重化してくれるので、他の処理を行える。 ただし、PHPにはPHP-FPMなどのプロセスマネージャもある。</p>\n<p>実装は、たかだか15行程度のコードで可能。でも実装が必要で、メンテも必要。 <strong>これってプログラム言語のレイヤが担うべき責務なのか？ ？ 言語でやらずにプロセスマネージャを別途利用したほうが良いのか??</strong> というのが最後の疑問。</p>\n<p>ちなみにNodejsのサンプルコードはこちら:</p>\n<div class=\"gatsby-highlight\" data-language=\"javascript\"><pre class=\"language-javascript\"><code class=\"language-javascript\"><span class=\"token keyword\">const</span> cluster <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'cluster'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> http <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'http'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">const</span> numCPUs <span class=\"token operator\">=</span> <span class=\"token function\">require</span><span class=\"token punctuation\">(</span><span class=\"token string\">'os'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">cpus</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span>length<span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">if</span> <span class=\"token punctuation\">(</span>cluster<span class=\"token punctuation\">.</span>isMaster<span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Fork workers.</span>\n  <span class=\"token keyword\">for</span> <span class=\"token punctuation\">(</span><span class=\"token keyword\">var</span> i <span class=\"token operator\">=</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span> i <span class=\"token operator\">&lt;</span> numCPUs<span class=\"token punctuation\">;</span> i<span class=\"token operator\">++</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n    cluster<span class=\"token punctuation\">.</span><span class=\"token function\">fork</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span>\n\n  cluster<span class=\"token punctuation\">.</span><span class=\"token function\">on</span><span class=\"token punctuation\">(</span><span class=\"token string\">'exit'</span><span class=\"token punctuation\">,</span> <span class=\"token punctuation\">(</span><span class=\"token parameter\">worker<span class=\"token punctuation\">,</span> code<span class=\"token punctuation\">,</span> signal</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    console<span class=\"token punctuation\">.</span><span class=\"token function\">log</span><span class=\"token punctuation\">(</span><span class=\"token template-string\"><span class=\"token template-punctuation string\">`</span><span class=\"token string\">worker </span><span class=\"token interpolation\"><span class=\"token interpolation-punctuation punctuation\">${</span>worker<span class=\"token punctuation\">.</span>process<span class=\"token punctuation\">.</span>pid<span class=\"token interpolation-punctuation punctuation\">}</span></span><span class=\"token string\"> died</span><span class=\"token template-punctuation string\">`</span></span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span> <span class=\"token keyword\">else</span> <span class=\"token punctuation\">{</span>\n  <span class=\"token comment\">// Workers can share any TCP connection</span>\n  <span class=\"token comment\">// In this case it is an HTTP server</span>\n  http<span class=\"token punctuation\">.</span><span class=\"token function\">createServer</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">req<span class=\"token punctuation\">,</span> res</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">=></span> <span class=\"token punctuation\">{</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">writeHead</span><span class=\"token punctuation\">(</span><span class=\"token number\">200</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n    res<span class=\"token punctuation\">.</span><span class=\"token function\">end</span><span class=\"token punctuation\">(</span><span class=\"token string\">'hello world\\n'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n  <span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">listen</span><span class=\"token punctuation\">(</span><span class=\"token number\">8000</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n<span class=\"token punctuation\">}</span></code></pre></div>\n<p>会社のパイセンに聞いてみたところ、<br>\n「並列処理とマルチプロセスは違う、マルチプロセスをやりたいなら言語レベルではなく、より上位でプロセスマネージャを利用したほうが良い。<br>\nなぜなら、本気でクラスタリングしたいなら、Nodeのサンプルコードのような簡素な実装ではままならず、とても複雑な考慮や制御が必要になるのでコストとリスクが高すぎるから」</p>\n<p>と回答を得た。<br>\n「え、これ実装しなきゃ早くならないの？ ？ 実装汚れるなぁ…」と不安に思っていたので、独自実装はすべきでないという同じ方向性で良かった。</p>\n<p>現時点で理解したことは以上です。</p>","timeToRead":8,"frontmatter":{"title":"シングルスレッドな言語の並列化・マルチプロセス化についての暫定的な理解をまとめる","tags":["Nodejs","Performance","PHP"],"date":"July 23, 2016","featuredImage":null}}},"pageContext":{"slug":"/learn-multi-thread-and-multiplexing/","previous":{"fields":{"slug":"/how-to-customize-cache-settings-of-google-cloud-storage/"},"frontmatter":{"title":"Google Cloud Storageのキャッシュの設定を変更してみる","tags":null}},"next":{"fields":{"slug":"/event-report-of-builderscon-bbq/"},"frontmatter":{"title":"buildersconのBBQで肉を食ってきた","tags":["Builderscon"]}}}},
    "staticQueryHashes": ["2585454260","2954598359"]}