シングルスレッドな言語の並列化・マルチプロセス化についての暫定的な理解をまとめる

たまにはまとまってない情報を書いてもいいじゃないかということで、表題の通り暫定版です。

まえおき

Nodejsのclusterモジュールのドキュメントを読んでいて、
「ほぉ、並列化って簡単にできるんだなぁ」と感じつつ、関連記事をいろいろ調べてみると、

  • 並列化すればスループットが上がる
  • マルチコアの場合は有用。CPUのコア数と同じにすると良い
  • ワーカーやアプリケーションサーバなどは横に並べとけ

的な記述が色々あり、違和感を感じました。
Goなどのマルチスレッドができる言語でやる”並列化”と私が調べているものは別物なのでは?と。

ということで、身近な頼れる方々へ聞いて調べて考えた結果の暫定的な理解を書き留めておきます。 理解に誤りがあったら指摘もらえると喜びます。

パフォーマンスチューニングやスレッドセーフであるための4条項とかそういう込み入った話ではなく、浅い話です。

用語の整理。多重化と並列化とマルチプロセス化は別物である

たとえばGoで並列処理をする場合、goroutineを使用すると思います。
たとえばjsで複数の非同期処理を同時に行おうとした場合、Promise.allを使用すると思います。
Herokuの記事によると、Nodeでワーカーの並列度を最適化するには、throngなどのクラスタリングマネージャを使用して、マルチプロセス化したら良いと思う的なことが書かれています。

一体なにがどれにあたるんだ、違いがわからん と思っていたのですが、
JavaScript(Nodejs)はマルチコアな筐体で動作させたとしても、あくまで シングルスレッド な言語であるという点から整理すると、

  • 多重化
    • 1つのCPUを複数のタスクでシェアし、待ち時間を減らしマルチスレッドかのように振る舞うこと
    • jsの非同期処理や、PHPのcurl_multiはこれ
    • シングルコアで動くgoroutineもこれ
  • 並列化
    • 複数のCPUを使用し、それぞれに異なる計算をさせること
    • マルチコアで動くgoroutineはこれ
  • マルチプロセス
    • プログラム中のある処理ではなく、プロセス自体を横に並べること。多重化や並列化とは別枠というか、比べる対象ではない
    • PHP-FPMやNodeのclusterモジュールがこれ

と理解しました。 多重化と並列化は置いといて、マルチプロセスについてより詳細にまとめていきます。

マルチプロセスの数はいくつが良いのか

頼れるパイセンがアドバイスをくれた。
なんとなーくCPUのコア数と同じって理解だったのが、
LoadAverageという値がCPUのコア数と同じになるように調整すれば良いと判明。

なのでプロセスの数自体はCPUのコア数と必ずしも一致しない模様。

ロードアベレージって何

load averageとは ロードアベレージはシステム全体の負荷状況を表す指標。
「1CPUにおける単位時間あたりの実行待ちとディスクI/O待ちのプロセスの数」で表される。
システムのスループットを上げたい場合はロードアベレージを下げることを目標にする。 load averageを見てシステムの負荷を確認する – Qiita

この引用部分だけでは 低ければ低いほど良い ように見えますが、
CPUコア数よりLoadAverageが高い場合高いは処理待ちが発生しているが、逆に低すぎるとCPUパワーを余らせていることになる

なのでCPUのコア数より高い場合は下がるように改善を。
低すぎる場合は、余ってるマシンパワーを活かすようにプロセス増やしたりCPU負荷が高いけど高速な処理に変えたりと性能改善が可能

マルチプロセスはどのレイヤが担うべきなのか

最後。Nodejsにはclusterやchild_processなどのモジュールが組込みモジュールとして提供されている。
これはもう「アプリケーションをマルチプロセス化して下さい」と言っているようなものなのではないか・・・?
Herokuもthrongという簡易クラスタリング用のライブラリを使った例を出していたりする。

phpにもpcntlというプロセス制御の拡張機能がある。 シングルスレッドの言語でもプロセスを並べれば、スレッドをロックするようなsleep関数等もプロセスマネージャが多重化してくれるので、他の処理を行える。 ただし、PHPにはPHP-FPMなどのプロセスマネージャもある。

実装は、たかだか15行程度のコードで可能。でも実装が必要で、メンテも必要。 これってプログラム言語のレイヤが担うべき責務なのか??言語でやらずにプロセスマネージャを別途利用したほうが良いのか?? というのが最後の疑問。

ちなみにNodejsのサンプルコードはこちら:

会社のパイセンに聞いてみたところ、
「並列処理とマルチプロセスは違う、マルチプロセスをやりたいなら言語レベルではなく、より上位でプロセスマネージャを利用したほうが良い。
なぜなら、本気でクラスタリングしたいなら、Nodeのサンプルコードのような簡素な実装ではままならず、とても複雑な考慮や制御が必要になるのでコストとリスクが高すぎるから。」

と回答を得た。
「え、これ実装しなきゃ早くならないの??実装汚れるなぁ・・・」と不安に思っていたので、独自実装はすべきでないという同じ方向性で良かった。

現時点で理解したことは以上です。

シバン(shebang)をやっと理解した

こんにちは。

composerで提供されているコマンドの中身を見ていたら

と書かれており、そのあとの行にはPHPのコードが。

のように、phpコマンドを使わずに直接PHPのコードが実行出来るようになっていました
この仕組みは シバン(shebang) というらしいです

シバン自体はBashのスクリプトで似たようなものを何度も見たことがあったのですが、おまじない的に捉えており意味を深く考えていませんでした
拡張子や実行コマンドに縛られず、何の言語で書いても良い実行可能なコードを作るのに適しているのでは??
と疑問が湧いたので、調べて理解したものを残しておきます

Continue Reading…

5分で作るPHPフレームワーク(技術調査、設計編)

こんにちは
突然ですが、PHPのフレームワークを作ろうと思います。

大層なタイトルを掲げてしまいましたが、制作自体は全く5分ではありません。けっこう時間かかりました
じっくり時間を書けて調査した結果、記事に倣って書けば5分くらいで完成する、という意味での5分です

記事は2本立ての構成で、今回は技術選定・設計編です。

Continue Reading…

昨今のPHPのテンプレートエンジンについて調べて共通インタフェースを作った

こんにちは。

突然ですが、FuelPHPのビューを書く場合、デフォルトでは生PHP + Viewクラスの構成だと思います。
Viewクラス自体がエスケープ機構を備えているのでXSSは塞げるんですが、生のPHPで書くとisset地獄だったりifが増えたりと不便なところが多く、テンプレートエンジン使いたいと思うことが多々あります。

そんなFuelPHPにはparserというパッケージがあるので、設定を変更すればテンプレートエンジンが簡単に利用できます。

fuelphpでhaml導入したった – ド忘れ防止雑記帳

が、しかし 対応しているテンプレートエンジンの一覧を見てみると、どれも古い。とにかく古い。
良く言えば枯れてるんですが、調べてみると メンテナンスされてないだろこれ… という感じのものが結構ありました。

ということで自分の知見をアップデートするため昨今のテンプレートエンジンについて調べつつ、
parserパッケージのように複数テンプレートエンジンを同一のインタフェースで扱える仕組みを作ってみました。

Continue Reading…

Fluidで任意のWebページをアプリ化する

Untitled

こんにちは。

Google AnalyticsのiOS版がなぜか「Temporary unavailable」で何も情報を出してくれなくなってはや1ヶ月。
もうiPhoneでの閲覧はあきらめてPCでどうにかしようと思い立ったものの、 ただでさえ増えがちなChromeのタブを増やしたくない

たくさんタブ開いちゃうとファビコンすら見えなくなって何のタブかわからなくなるんですよね。動作も重くなるので常に必要最小限のタブだけ開いておきたいんです。
かといってApp storeを探してみてもいいAnalyticsのアプリが見つからない。

ということでWebページをアプリ化するFluidというアプリを使用していくつかのWebサービスをアプリ化してみようと思います。

Continue Reading…

aタグのdownload属性でサーバを介さずにファイルダウンロードする

この記事はHTML5 Advent calendarの16日目の記事です。

HTML5からaタグにdownloadという属性が指定可能になったようです。
この属性が指定されたaタグは、href属性の値をブラウザで開くのではなく、リンク先をファイルとしてダウンロードします。

今までcanvasで画像を生成した画像など、jsで生成したファイルをユーザに保存させるにはwindow.openにdata urlを渡して新窓で表示させ、ユーザに右クリ等で保存してもらう方法しか知らなかったのですが、
aタグのdownload属性がまさにやりたいことドンピシャだったので備忘録を残します。

Continue Reading…

Goの環境を作るAnsibleの設定をリファクタした

Goの環境を作るAnsibleの設定をリファクタした

の投稿です。

まだGoもAnsibleも良くわかってない頃に作った、Goの環境を整えるAnsibleの設定をリファクタリングしました。

やってる事はごく当たり前なんですが、冪等性を担保し、changedが出ないことによって何回でもいつでも実行できる環境にしたので、その過程をメモします。

Continue Reading…