Open9

いつか「実践 Erlang/OTP 時雨堂編」を書くためのメモ

voluntasvoluntas

これは「プログラミングErlang」と「すごいErlangゆかいに学ぼう!」を読み終わった人が商用ミドルウェアを Erlang/OTP で書きたいって思ったときに手に取れる 「実践 Erlang/OTP 時雨堂編」という無料のオンライン書籍をいつか書くための雑多なメモ。

著者

  • 時雨堂の中の人
  • Erlang/OTP は R11 から
  • Erlang/OTP を利用した商用パッケージ製品の開発者

これから Erlang/OTP を学ぼうと思う人へ

まずこの2冊を購入してしっかり読み込んでほしい。自分もプログラミング Erlang をひたすら読み込んだ。

また、この 2 冊以外は日本語の書籍は読む必要はない。これに書いていない事は Erlang のドキュメントやソースコードを読む。資料では、この 2 冊に足りていない部分を書いていく。

ドキュメント

海外書籍

資料

voluntasvoluntas

rebar3

ビルドツール。公式で配布してる。

Erlang の文法を覚える前に、rebar3 を覚えた方が良いくらい大事。

rebar3 プラグイン

翻訳書籍には載っていない機能や標準ライブラリや文法

counters と persitent_term と logger は erlang vm にとってブレイクスルーなので、必ず覚えるべき。

HTTP 系ライブラリ

デバッグ系ライブラリ

フォーマッターのライブラリ

  • sile/efmt: Erlang code formatter
    • Rust で書かれた Erlang/OTP フォーマッター
    • 早いのは正義
    • フォーマット前とフォーマット後の動作が同じ事を保証してくれるので安心して使える
voluntasvoluntas

UUIDv4 が使いたい

crypto:strong_rand_bytes/1 を使って簡単に自作できる。

%% https://www.rfc-editor.org/rfc/rfc4122.html
uuidv4() ->
    %% https://www.rfc-editor.org/rfc/rfc4122.html#section-4.1.2
    <<Rand1:48, _:4, Rand2:12, _:2, Rand3:62>> = crypto:strong_rand_bytes(16),
    <<Rand1:48,
      %% https://www.rfc-editor.org/rfc/rfc4122.html#section-4.1.3
      %% Msb0  Msb1  Msb2  Msb3   Version  Description
      %%  0     1     0     0        4     The randomly or pseudo-
      %%                                   randomly generated version
      %%                                   specified in this document.
      2#0100:4,
      Rand2:12,
      %% https://www.rfc-editor.org/rfc/rfc4122.html#section-4.1.1
      %% Msb0  Msb1  Msb2  Description
      %%  1     0     x    The variant specified in this document.
      2#10:2,
      Rand3:62>>.
voluntasvoluntas

ライブラリ FAQ

voluntasvoluntas

書き方 FAQ

  • 何かあったらクラッシュさせていいの?
    • ダメ、把握できる範囲は ok/error で対応する
voluntasvoluntas

OTP 26

https://www.erlang.org/news/160 の翻訳。

Erlang シェル

  • 変数、レコード名、レコードフィールド名、マップキー、関数パラメータタイプ、ファイル名のオートコンプリート
  • シェルで外部エディタを開き、現在の式を編集します
  • シェルでレコード(型あり)、関数、スペック、型を定義

JIT

  • base64モジュールの性能は大幅に改善されました
    • JITを使ったx86_64システム上では、エンコードとデコードの両方がErlang/OTP 25のときよりも3倍近く速くなった
  • 固定サイズのセグメントを持つバイナリの作成とマッチングが最適化されました
  • UTF-8 セグメントの作成とマッチングが最適化されました
  • バイナリへのアペンドが最適化されました
  • コンパイラとJITは、すべてのキーがコンパイル時に分かっているリテラルである小さなマップを作成するためのより良いコードを生成するようになりました

Dialyzer

  • Dialyzerには新しいインクリメンタルモードがあり、Dialyzerの実行時に--incrementalオプションを与えることで起動します。 この新しいインクリメンタルモードは将来のリリースでデフォルトとなる可能性があります

Maps

  • マップ内包が実装されました
  • アトムキーの内部ソート順を変更することにより、いくつかのマップ操作が最適化されました。これは小さなマップのアトムキーがどのように表示され、maps:to_list/1とmaps:next/1 によって返されるかという(文書化されていない)順番を変更します。 新しい順番は予測不可能で、Erlang VMの異なる起動の間で変わるかもしれません
  • マップの要素を決定論的な順序で返すインターレーターを作成するための新しい関数maps:iterator/2が導入されました。 また、マップの要素を順序どおりに印刷するための新しい修飾子kとKが io:format() のフォーマット文字列として導入されました

ssl

  • erl_dist の ssl が ktls に対応

その他

  • BIFのmin/2、max/2がガードやマッチの仕様で使用できるようになりました
  • 選択的受信の最適化が改善され、他の関数から返された参照に対して有効化できるようになりました。これにより、gen_server:send_request/3 やgen_server:wait_response/2 といった関数の性能が大幅に改善されます
  • inet:setopts/2に3つの新しいオプションが追加されました:reuseport,reuseport_lb,exclusiveaddruse
  • application:get_supervisor/1を導入
voluntasvoluntas

基本戦略

  • 依存ライブラリをとにかく減らす
  • 可能なかぎりライブラリは自作する
    • 汎用ライブラリは既存のものを利用する
  • 可能なかぎり標準ライブラリを利用する
  • OSS ライブラリを利用する時はフォークする覚悟で利用する
  • 標準ライブラリでも利用しないのはパッケージに含めない
  • ログは JSON Lines
    • 標準ライブラリの logger を利用して実現してる
    • ログローテーションはしない
    • 将来的にログローテーションや圧縮の仕組みを作り込みたい
voluntasvoluntas

OTP 27.0

https://www.erlang.org/blog/highlights-otp-27/ の雑な翻訳

  • ドキュメントが XML から Markdown へ
  • -doc を利用してドキュメントが書けるようになった
  • <<"しぐれどう"/utf-8>> が ~"しぐれどう" と書けるようになった
    • ~b"しぐれどう" でもよい
  • maybe が設定なしで利用できるようになった
  • json モジュールが入った
  • デバッグ向けにプロセスにラベルが付けられるようになった
    • proc_lib:set_label/1
    • proc_lib:get_label/1
  • tprof という新しいプロファイラーが入った

トリプルクオート

こんな感じでかけるようになった。

S = """
      あいうえお
      かきくけこ
      """
voluntasvoluntas

Erlang/OTP の向いている分野

もし採用する場合

  • プロトコルは自前で実装する
  • 依存ライブラリはできるだけ減らす
  • Raft ライブラリは自作しない
    • WhatsApp と RabbitMQ が公開している
    • https://github.com/rabbitmq/ra
    • https://github.com/WhatsApp/waraft
      • WARaft は、5 つ以上のデータ センターにわたる大規模で強力な一貫性のあるストレージ システムである WhatsApp メッセージストレージの合意プロバイダーとして使用されています
  • ボトルネックは暗号処理とパケット書き込み
  • 暗号処理は OpenSSL を利用するが早くはない
    • Rust と比較したところ Rust の方が 2 倍速かった

時雨堂では

  • WebRTC SFU の実装に利用している
  • プロトコルスタックは全て自前
  • Raft ライブラリは RabbitMQ の Ra を採用
  • できるだけ標準ライブラリを利用