見出し画像

バックエンドの技術選定のメモ

ざっくりの一般論を書くので、キレるのだけはやめてください。常に例外はあります。ただJavaScriptエンジニアなので、その偏見は入ってます。

PythonやRubyやPHP

クライアントからのリクエストごとにプロセスを作るので、大量にアクセスが来ると、プロセスで溢れかえる。またプロセスはメモリの消費量が多いので、どんどんサーバーが重たくなる。その上で非同期通信がメインではないので、データベースとかにアクセスしたら、それ以下のコードが全部止まる。このときOSはメモリの効率化のために、そのプロセスを一度2次記憶などに置きがち。つまりその出し入れだけでもかなり時間がかかる。と考えるとベストな選択肢ではないかも。でもYoutubeとかもPythonで書かれているらしいし、もはや余裕で及第点は超えている気もする。ロードバランサーとか使うとさらに良い気がする。

Node.js

プロセスは1つだけ。クライアントからアクセスが来ても、全部1つのプロセスでイベントループを使って処理する。具体的には一度配列みたいなところに、全部入れて、1つずつ取り出して処理をする。これによってプロセスが作られないから、そこまでメモリもふえず、サーバーも遅くならない。また非同期処理をガンガンに使うので、データベースとかにアクセスする時でも、コードは止まらないし2次記憶を使ったりもしない。V8エンジンが早いから単純な実行速度も良い。JavaScriptを使ってるのでフルスタックで便利。一方で完全に1つのプロセスなので、並列処理0で若干効率悪い。ただしClusterでプロセスを増やしたり、Worker threadsで軽量プロセス(スレッド)を増やすことができるので、手作業で並列処理にすることは可能。とはいえ、Clusterのプロセスはネットワークリクエストの分散のみに、Worker threadsのスレッドは重たい処理の分散のみに使用できる。なので大量にアクセスが来た時と、たくさん重たい処理をする時の、どちらでも最大パフォーマンスを発揮するためには、プロセスとスレッドの数をそれぞれCPUと同じ数ずつ用意しておく必要がある。ただしそうした場合、常に必要以上のプロセスやスレッドがメモリに存在することになるので、少し効率が悪くなる。またその状態で、大量にアクセスが来て、かつ、たくさん重たい処理をする場合、CPUに割り当てられるプロセスやスレッドには限界があるので、それらを高頻度で切り替える(context switching)必要がある。この切り替えも時間がかかる。それらを考慮すると、ClusterかWorker threadsのどちらかだけをプロジェクトの特徴に合わせて使う、もしくは割合を変える、などをした方が良いのかもしれない。例えば大量にアクセスが来て、かつ、たくさん重たい処理をするプロジェクトの場合は、どうせCPUの数が決まってるんだからClusterだけにするとか、リクエストはあまり来ないけど1回あたりの処理が重い場合はWorker threadsだけにするとか、時間によって、大量にリクエストが来るときもあればリクエストはあまり来ないけど重たい処理をするときもある場合は、最適な比率をベンチマークして決めるとか。どちらにせよ手動で調整するのが大変。

Go

Node.jsと同じで、非同期処理メイン。その上で、軽量プロセス(スレッド)がデフォルトでCPUと同じ数あり、そのスレッド上だけで、リクエストの分散や重たい処理の分散などを全て自動で行ってくれる。つまり並列処理を簡単に効率よくやってくれるNode.jsみたいな感じ。不必要なメモリの消費もなければ、不必要なcontext switchingも無いので、常に最大パフォーマンスを出せる。あと単純に静的言語なのでコードが最適化されていてパフォーマンスが普通に高い。ただRustやC++と比べると、ガベージコレクションのせいで割と遅い。ちなみにスレッド数を手動で変えることも一応可能。

C++, Rust, Java, Scala, Kotlin, Elixir

よくわからんです。C++やRustは多分めちゃくちゃ速いと思います。が一方でかなり複雑なのでコスパ悪いかもです。JVM系をするなら、JavaやScalaよりKotlinの方が良いと聞いたことがあります。Elixirは、なんかできるとかっこいいなぁと思います。

結論

多分なんでもそれなりに使えると思います。が、一番コスパのことを考えるとGo言語やNode.jsが良いんじゃないでしょうか。結構簡単に書けて、それなりに早そうです。その上でバックエンド専門ならGo言語、フルスタックでやるならNode.js、くらいがちょうど良い塩梅ではないでしょうか。ちなみにAWS lambdaのようなサーバーレス関数においては、10分ほどアクセスがないと次回アクセス時にcold startとなり、その都度、1からスレッドの立ち上げが行われます。なのでスレッドが多いと時間がかかるということで、少なくする場合は、GoもNode.jsも同じような感じになるかもです。


この記事が気に入ったらサポートをしてみませんか?