ElixirでIoT#1.3：IoTボードで動いた！Phoenixが立った！性能評価と考察

この記事は「[Elixir or Phoenix Advent Calendar 2017](https://qiita.com/advent-calendar/2017/elixir-or-phoenix)」の17日目です．
昨日は@zacky1972さんの「[ZEAM開発ログv0.1.2 AI/MLを爆速にしたい！ Flow のコードを OpenCL で書いてみる〜CPU編](https://qiita.com/zacky1972/items/c5c43794bd8af75a9800)」でした．

:black_square_button::black_large_square::black_square_button:　お知らせ　:black_square_button::black_large_square::black_square_button:
**[「fukuoka.ex#11：DB／データサイエンスにコネクトするElixir」](https://fukuokaex.connpass.com/event/87241/)**を6/22(金) 19時に開催します
私も「ElixirでIoTやってみた」ネタで発表します！是非ともご参加下さい！！

[![https://fukuokaex.connpass.com/event/87241/](https://camo.qiitausercontent.com/bcffdf573a5efe4bf524e0bce325dfc175e74fc5/68747470733a2f2f636f6e6e706173732d746f6b796f2e73332e616d617a6f6e6177732e636f6d2f7468756d62732f63622f31332f63623133306130333334336263333130623037323434633330386239343064622e706e67)](https://fukuokaex.connpass.com/event/87241/)

なお発表ネタへの仕込みはまだ成果ゼロです，，，
発表駆動開発は進捗を確実に生み出せますがオススメはしません^^;

# はじめに

こんにちは．
組込マーとはいってもC至上主義から抜け出したい今日この頃です．

先日の勉強会「[fukuoka.ex#8(福岡Elixir会)：2018年 春のElixir入学式](https://fukuokaex.connpass.com/event/85038/)」にて発表した内容を加筆編集しながら，**ElixirをIoTボードで動かしたらどうなんの？**という異色ネタをお届けしています．

これまでの記事では，IoTボード上でElixirが実行できる環境を構築し，性能評価のためのベンチマークアプリを整備してきました．

- [ElixirでIoT#1.0：IoTボードへのLinux環境の準備](https://qiita.com/takasehideki/items/9e3db412a40659233384)
- [ElixirでIoT#1.1：IoTボードへのElixir環境の構築とEEloTツールキットの紹介](https://qiita.com/takasehideki/items/fc570ae92a895caed213)（12/07版・05/01公開）
- [ElixirでIoT#1.2：いろいろ分かるベンチマークを整備してみる](https://qiita.com/takasehideki/items/e1dcb4058c7d0b51d554)（12/12版・05/06公開）

今回はいよいよElixir成分もIoT成分も高くいきましょう！！
[EEloT](https://github.com/takasehideki/EEloT)ツールキットを用いてIoTボードの性能あれこれを評価した結果をお送りします．また，前回の記事で書き忘れていたベンチマークアプリの動かし方も紹介します．

## IoTボードの仕様

本連載で使用したIoTボードのスペックをおさらいしておきましょう．ラズパイは2種類のOSを試しています．


| Board | OS | Core | Memory | Network |
|:---|:---|:---|:---|:---|
| [Raspberry Pi 3 Model B](https://www.raspberrypi.org/products/raspberry-pi-3-model-b/) | [Raspbian Stretch with Desktop 4.9](https://www.raspberrypi.org/downloads/raspbian/) / [Ubuntu MATE 16.04](https://ubuntu-mate.org/raspberry-pi/) | 4x 1.2GHz Cortex-A53 (64-bit) | 1GB LPDDR2 | 150Mbps 2.4GHz 802.11b/g/n WiFi |
| [ODROID-XU3](http://www.hardkernel.com/main/products/prdt_info.php?g_code=g140448267127) | [ubuntu-16.04-mate-odroid-xu3-20170731](https://odroid.in/ubuntu_16.04lts/) | 4x 2.0GHz Cortex-A15 + 4x 1.4GHz Cortex-A7 (32-bit) | 2GB LPDDR3 | 300Mbps 2.4GHz 802.11n/g/b WiFi |
| [ZYBO](https://japan.xilinx.com/products/boards-and-kits/1-4azfte.html) | [Xillinux-2.0](http://xillybus.com/xillinux) | 2x 650MHz Cortex-A9 (32-bit) | 512MB DDR3 | 1GBit Ethernet PHY |

さーElixirを動かした時の性能はどうなる？
プロセッサアーキテクチャとかOSの違いは影響するのか！？

なお，今回の評価結果は，1回動かしただけのものを掲載しています．本当は何度も測定して平均値とか分散とか見て他プロセスの稼働状況を加味して，，，まぁそういうacademicな細かいことは気にしないでおきましょう．

また，以降の説明では，下記を作業済みであることを前提とします．

* [EEloT](https://github.com/takasehideki/EEloT)ツールキットを`$ git clone`してきたディレクトリ上で作業していること
* `$ ./setup.sh`を実行済みであること
* `$ ./install.sh source`で環境をソースビルドしていること

```shell-session
$ elixir --version 
Erlang/OTP 20 [erts-9.3] [source] [smp:4:4] [ds:4:4:10] [async-threads:10] [hipe] [kernel-poll:false]
```

つい先日に[Elixirのバージョンアップ](https://twitter.com/elixirlang/status/993483135601074176)がアナウンスされましたね，，，

# 演算性能

まずはEEloTにベタのソースで入っている3種類のアプリを一気にいきましょう．

* leibniz_formula.ex：ライプニッツ級数を用いた円周率の計算
    * 小数点演算の性能を評価できる
    * 和の上限は10^8とする
* fibonacci_simple.ex：フィボナッチ数列計算のシングルプロセス版
    * 整数演算およびスタック消費時の性能を評価できる
    * 100_000までの数列を計算する
* fibonacci_process.ex：フィボナッチ数列計算のマルチプロセス版
    * 並列処理時の性能を評価できる
    * 37までの数列を6個同時に，10プロセス並列で計算する

## 動かし方

EEloTではとってもシンプルです．

```shell-session
$ elixir -e Measure.allex 
```

## 評価結果

表中の単位は秒です．

|Board|OS|leibniz_formula|fibonacci_simple|fibonacci_process|
|:---|:---|---:|---:|---:|
|RaspberryPi3B|Raspbian| 114.470 | 14.329 | 14.474 |
| |Ubuntu| 118.107 | 5.050 | 15.888 |
|ODROID-XU3|Ubuntu| 48.475 | 6.816 | 6.943 |
|ZYBO|Ubuntu| 161.342 | (><) | 41.789 |

**ODROID-XU3が最強**です！
`leibniz_formula`では，単一プロセスなのでマスタコアの1.4GHz Cortex-A7 (32-bit)で動作しているはずなのですが，1.2GHz Cortex-A53 (64-bit)のラズパイ3を軽々とブッチギッています．`fibonacci_simple`ではUbuntuだと盛り返していますが，ここまで差が出たのは驚きでした．
古い情報になりますが，[64-bitではErlangがメモリを喰うため32-bitに劣る](http://www.erlang-factory.com/upload/presentations/105/KennethLundin-ErlangFactory2009London-AboutErlangOTPandMulti-coreperformanceinparticular.pdf)という話しもあるようです．詳しく議論してみたいところです．

そして注目すべきはやはり並列性能でしょう！`fibonacci_process`では，物理コアを8個持つODROID-XU3が圧倒しています．マイクロアーキのハンデをコア数で凌駕しています．

ZYBOは，思ったより健闘したけど，まぁ残念でした，，，
なお`(><)`のところは，
`eheap_alloc: Cannot allocate 220742620 bytes of memory (of type "old_heap").`
と言ってお亡くなりになりました．まぁ512MB Memoryですからねぇ^^;


# 大規模データの処理性能

次はCSVデータ処理アプリである[elixir_agg_csv](https://github.com/enpedasi/elixir_agg_csv)です．
入力データは[fukuokaex5_csv](https://github.com/enpedasi/fukuokaex5_csv)のものをそのまま使います．


## 動かし方

`iex`上で動かします．
EEloTスクリプトがビルドだけでなく入力データの用意まで自動でやってくれるので，やはりとってもシンプル．

```shell-session
$ cd elixir_agg_csv/
$ iex -S mix
iex(1)> ElixirFlow.run("test_300000.csv")
iex(2)> ElixirFlow.run("test_3_000_000.csv")
```

## 評価結果

表中の単位は秒です．

|Board|OS|test_300000.csv|test_3_000_000.csv|
|:---|:---|---:|---:|
|RaspberryPi3B|Raspbian| 11.128 | 81.776 |
| |Ubuntu| 9.326 | 82.487 |
|ODROID-XU3|Ubuntu| 4.828 | 46.956 |
|ZYBO|Ubuntu| 34.380 | 284.712 |

ここでもODROID-XU3が圧倒しています！
**高性能なものをドンと置くよりもコアをズラッと並べるほうが有利！**というElixirの特徴は，IoTボードでも活きてくるようです．

先のアプリでは出ていたラズパイ3同士のOS間の差は，本アプリではほぼ無くなっていますね．そもそもErlang VM性能はOSに影響するのか，またまた興味が出てきます．

ZYBOはまぁ，，，FPGAの力を借りてのリベンジに期待ですかね^^;

# Phoenixサーバ性能

[phoenix-showdown](http://muziyoshiz.hatenablog.com/entry/2016/12/24/205321)を使ってPhoenixサーバのレイテンシとスループットの性能を評価します．
なお，オリジナルのリポジトリだとElixirのバージョンアップに追従しておらずライブラリの追加変更が必要でしたので，[私のGitHubアカウントにforkしたもの](https://github.com/takasehideki/phoenix-showdown)を使っています．

## Phoenixが立った！

ところでそもそもIoTボードでPhoenixは立つのか！？
Webブラウザから`http://<BoardIP>:4000/showdown`にアクセスしてみました．

<img width="946" alt="スクリーンショット 2018-05-07 19.44.54.png" src="https://qiita-image-store.s3.amazonaws.com/0/240349/1ab0f95e-e1f9-a0d2-31c9-f7b4c3b0526e.png">

安心してください，立ってますよ！？

なお，今回はまだIoTボードにDBまでは導入していません．[piacereさんの記事](https://qiita.com/piacere/items/a7558adc6856e3577dc6)を参考にして導入したいと思っています．


## 動かし方

まず，IoTボード上では下記を実行します．

```shell-session
$ cd phoenix-showdown/phoenix/benchmarker/
$ mix phoenix.server
```

その後，母艦のMacbook Proから下記を実行します．

```shell-session
$ wrk -t4 -c100 -d30S --timeout 2000 "http://<BoardIP>:4000/showdown"
```

4スレッド，同時100コネクション，30秒の負荷を掛けています．

ネットワーク接続の構成も大事そうなので，きちんと紹介しておきます．

* ラズパイ3はオンボードのWiFiモジュール（150Mbps）で無線接続
* ODROID-XU3はUSB-WiFiアダプタ（[WLI-UC-G301N](http://buffalo.jp/products/catalog/network/wli-uc-g301n/)，300Mbps）で無線接続
* ZYBOは有線LAN（Trimode (1Gbit/100Mbit/10Mbit) Ethernet PHY）で接続
    * まぁこのくらいのハンデはあげましょう，，，
* ルータは[Buffalo WCR-1166DS](http://buffalo.jp/product/wireless-lan/ap/wcr-1166ds/)を使用


## 評価結果


|Board|OS|Throughput [req/s]|Latency [ms]|Consistency [σ ms]|
|:---|:---|---:|---:|---:|
|RaspberryPi3B|Raspbian| 785.25 | 351.47 | 771.85 |
| |Ubuntu| 878.89 | 113.30 | 31.68 |
|ODROID-XU3|Ubuntu| 859.60 | 112.67 | 25.82 |
|ZYBO|Ubuntu| 459.28 | 216.72 | 83.10 |

スループットについては**ラズパイ3／Ubuntuに軍配が上がりました！**オンボードWiFiの利点を活かせたのでしょう．
ODROID-XU3も遜色ない結果が出ています．ネットワークの負荷による影響もありますので，誤差の範囲内と言えるかもしれませんね．OSの違うラズパイ3／Raspbianだと劣るのも興味深い結果です．
ZYBOは，，，有線接続のハンデを活かせませんでした^^; ネットワーク接続方法よりもコア性能のほうが大事なのかもしれません．

# まとめ

ということで性能評価の全体をまとめます．

- IoTボードでもElixirは動く！Phoenixだって立つ！！
- Elixir並列処理はすごい！マイクロアーキよりコア数！！
    - IoTボードでも高性能なものをドンと置くよりもコアをズラッと並べるほうが有利！
    - XU3/A15は最大2.0GHzなのも効いている？
- サーバ性能はネットワーク接続方法も大事なのかも？
    - Ethernet接続で対決させたら違う傾向になるかも
- ZYBOは健闘はしたものの，，，FPGA活用に期待しましょう
- なお消費電力は？？
    - ZYBO << XU3 < RPi3 <<<(超えられない壁)<<< Mac
- [EEloT](https://github.com/takasehideki/EEloT)を使えば性能の比較評価もお手のもの

演算性能評価のアプリはパラメータを振ってみたらどうなるか面白そうです．さらに，コア周波数を揃えてみたらどんな結果になるかも興味深いです．これらの話しは長くなりそうなので，別記事にまとめたいと思います．
また，バージョン毎・他言語／フレームワークの比較もしてみたら面白いかもしれませんね．



# ところでこれってIoT？？

まぁネットワークに繋がってるし，，，エッジサーバには使える評価結果だし，，，という言い訳はさておき，やはり**IoTは環境センシング／アクチュエーションがキモ**です．せめてLチカくらいはしたいですよね〜
次回の記事ではこの辺りの実現方法を調査して試してみたいと思っています．

明日のAdvent Calendarは@piacere_exさんによる
「[Excelから関数型言語マスター4回目：Webに外部APIデータ表示](https://qiita.com/piacere/items/4c212615a4eb699dd109)」
です．