web-dev-qa-db-ja.com

Erlangがこれらすべての小さな数学ベンチマークでJavaより遅いのはなぜですか?

Java分散/並行/フェイルオーバー/スケーラブルなバックエンド環境のJava $ ===の代替案を検討しているときに、Erlangを発見しました。本や記事のほとんどすべて(Java中毒の人)は、そのような環境ではErlangがより良い選択であると言います。なぜなら、多くの有用なものが箱から出してエラーを起こしにくい方法だからです。

Erlangはほとんどの場合主に異なるガベージコレクション戦略(プロセスごと)、共有状態(b/wスレッドとプロセス)がないこと、およびよりコンパクトなデータ型のために高速であると確信していました。しかし、 Erlang vs Java= math samples の比較)を見つけたとき、私は非常に驚きました。

複数のコアと単一のコアの両方での並行タスクでも。

その理由は何ですか?これらの答えが頭に浮かんだ:

  • ほとんどのタスクでのJavaプリミティブ(=>ヒープなし/ GC))の使用
  • JavaコードとErlangプロセスのスレッド数が同じであるため、ここではアクターモデルに利点はありません。
  • またはJavaは静的に型付けされていますが、Erlangはそうではありません
  • 他に何か?

これらが非常に具体的な数学アルゴリズムであるためである場合、誰かがより現実的な/実際のパフォーマンステストを示すことができますか?

更新:私はこれまでのところ、Erlangがそのような特定の「高速Javaケース」に適したツールではないことを要約していますが、不明確なこと-主な理由は何ですか?このようなErlangの非効率性:動的型付け、GC、または貧弱なネイティブコンパイル?

35
yetanothercoder

Erlangは数学のために作られていません。通信、並列処理、スケーラビリティを念頭に置いて構築されているため、数学のタスクをテストすることは、手持ち削岩機がさわやかなマッサージ体験を提供するかどうかをテストするのと少し似ています。

とはいえ、少し外してみましょう。
JVMでErlangスタイルのプログラミングが必要な場合は、 Scala Actors または Akka framework または Vert.x をご覧ください。

32
npe

ベンチマークは、実際にテストしている以外のことを言うのに適しているわけではありません。ベンチマークがプリミティブとクラシックスレッドモデルのみをテストしていると感じた場合は、それについて知識を得ます。 Javaは、プリミティブの数学およびこれらのタイプの問題の古典的なスレッドモデルではErlangよりも高速であると確信を持って言うことができます。大規模なパフォーマンスについては何もわかりません。スレッド数、またはベンチマークがテストしていないため、より複雑な問題の場合。

ベンチマークでテストした種類の数学を実行している場合は、Javaを使用してください。これは明らかにそのジョブに適したツールです。共有状態がほとんどないかまったくない状態で、非常にスケーラブルな処理を実行したい場合、そのためのベンチマークを見つけるか、少なくともErlangを再評価します。

本当にErlangで重い計算を行う必要がある場合は、HiPEの使用を検討してください(とにかくそれを考慮してください)。

14
Emil Vikström

他の回答で指摘したように、Erlangはベンチマークの問題とは正反対の現実の問題を効果的に解決するように設計されています。

しかし、私はもう1つの側面-ベンチマークの実装を比較した後、簡単に結論付けることができるアーランコードのpithiness(場合によっては開発の迅速さを意味します)を啓発したいと思います。

たとえば、k-ヌクレオチドベンチマーク:
Erlangバージョン: http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=hipe&id=
Javaバージョン: http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=Java&id=

より現実的なベンチマークが必要な場合は、お勧めします Motorola TelecomsソフトウェアのC++とErlangの比較

8
stemm

ベンチマークのいくつかは遺伝子シーケンシングなどのアーランに完全に適合しているので、私はこれに興味を持ちました。つまり、 http://benchmarksgame.alioth.debian.org/ 私が最初に行ったのは、CとErlangの両方の逆補数実装とテストの詳細を確認することでした。 VM/wスケジューラーを開始するのにerlangがかかる時間を割り引かないため、テストが偏っていることがわかりました。ネイティブにコンパイルされたCがより速く開始されます。これらのベンチマーク測定方法は基本的に:time erl -noshell -s revcomp5 main < revcomp-input.txt

ベンチマークはJavaに1.4秒かかり、erlang/w HiPEに11かかったと言います。)(シングルスレッドの)Erlangコードの実行には0.15秒かかり、vmの起動にかかる時間を割り引くと、実際のワークロードは3000マイクロ秒(0.003秒)しかかかりませんでした。

だから私はそれがどのようにベンチマークされているのか分かりません、それが100回行われた場合、アーランを開始するコストVMはx100になるので意味がありません。入力が与えられたよりもはるかに長い場合、それは理にかなっていますが、そのWebページには詳細が表示されません。マネージ言語のベンチマークをより公平にするために、コード(Erlang/Java)にpython =(ベンチマークを行っている)スタートアップ関数にヒットした。

ベンチマークはさておき、erlang VMは本質的に最後にマシンコードを実行するだけでなく、Java VMも実行します。したがって、数学演算が実行する方法はありません。 ErlangはJavaよりも時間がかかります。

Erlangの悪いところは、頻繁に変更する必要があるデータです。連鎖ブロック暗号など。文字「0123456789」があるとすると、暗号化は最初の2文字を7ずつxorsし、次の2文字を最初の2つを加算した結果でxorsし、次に現在の2を減算した結果で前の2文字をxorsします。次に、次の4文字をxorsします。など

Erlangのオブジェクトは不変であるため、変更するたびにchar配列全体をコピーする必要があります。そのため、erlangは、この正確な問題を解決するために呼び出すことができるCコードであるNIFSと呼ばれるものをサポートしています。実際、Erlangに同梱されているすべての暗号化(ssl、aes、blowfish ..)と圧縮(zlib、..)はCで実装されています。また、ErlangからCを呼び出すことに関連するコストはほぼゼロです。

したがって、Erlangを使用すると、両方の世界で最良の結果が得られ、Cの速度とErlangの並列性が得られます。

可能な限り高速に逆補数を実装する場合、Cを使用して変異コードを記述しますが、Erlangを使用して並列コードを記述します。無限の入力を想定すると、Erlangは> <<Line/binary, ">", Rest/binary>> = read_streamミリ秒ごとにクラスターにリアルタイムで追加される、無限のEC2プライベートネットワークの隠しノードで構成されるラウンドロビンを介して、ブロックを最初の使用可能なスケジューラーにディスパッチします。

次に、これらのノードはNIFSを介してCを呼び出して処理し(Cはalioth Webサイトでの逆コンプリメントの最速の実装です)、出力をノードマスターに送り返して入力側に送信します。

これらすべてをErlangで実装するには、シングルスレッドプログラムを作成しているようにコードを作成する必要があり、このコードを作成するのに1日もかかりません。

これをJavaで実装するには、シングルスレッドコードを作成する必要があります。マネージドからアンマネージドへの呼び出しのパフォーマンスヒットを取得する必要があります(明らかに、不快な作業にC実装を使用するため)。 64コア。次に、複数のCPUをサポートするように書き換えます。次に、クラスタリングをサポートするように再度書き込みます。次に、再度書き直して、メモリの問題を修正します。

そして、それは一言で言えばアーランです。

7
Vans S

ErlangソリューションはETS、Erlang Term Storageを使用します。これは、別のプロセスで実行されるインメモリデータベースのようなものです。別のプロセスにあるため、そのプロセスとの間のすべてのメッセージは、シリアライズ/デシリアライズする必要があります。これは多くの遅延の原因となると思います。たとえば、「regex-dna」ベンチマークを見ると、ErlangはJavaの場合よりもわずかに遅く、ETSを使用していません。

3
pmarreck

Erlangはすべての値にメモリを割り当てる必要があるという事実に対して、Javaでは、高速にしたい場合は通常変数を再利用します。つまり、「タイトループ」のベンチマークでは常に高速になります。

Javaバージョンを-clientフラグとボックス化プリミティブを使用してベンチマークし、それをerlangと比較することは興味深いことです。

ヒップはアクティブなプロジェクトではないので、それを使用するのは不公平だと思います。これでミッションクリティカルなソフトウェアが実行されているかどうかを知りたいです。

2
Andy Till