Slide 1

Slide 1 text

BIGINT あれこれ BIGINT あれこれ (2018/04/27) (2018/04/27) 小田島 太郎 / @shimataro NODE学園 30時限目 NODE学園 30時限目

Slide 2

Slide 2 text

自己紹介 自己紹介 ウェブリオ株式会社所属(京都) サーバサイドエンジニア 趣味は手品 前回も参加しました: 小田島 太郎 shimataro@GitHub odashima.taro@Facebook shimataro999@Twitter dynamic import あれこれ

Slide 3

Slide 3 text

この発表について この発表について 対象: Number型じゃ物足りない人 技術レベル: 初級〜中級 ↓スライドはこちら↓ https://speakerdeck.com/shimataro https://shimataro.github.io/slides/

Slide 4

Slide 4 text

目次 目次 背景 さっそく使ってみる 速度検証 Numberとの速度比較 本番環境で使うには? まとめ

Slide 5

Slide 5 text

始める前に 始める前に

Slide 6

Slide 6 text

【慶】NODE学園 30回【祝】 【慶】NODE学園 30回【祝】 今後も盛り上げていきましょう!

Slide 7

Slide 7 text

【慶】4/25 NODE.JS V10リリース【賀】 【慶】4/25 NODE.JS V10リリース【賀】

Slide 8

Slide 8 text

【拝】4/20 関西NODE学園 開校【賀】 【拝】4/20 関西NODE学園 開校【賀】 お互い盛り上げていきましょう!

Slide 9

Slide 9 text

それでは始めます それでは始めます

Slide 10

Slide 10 text

背景 背景

Slide 11

Slide 11 text

背景 背景 Number型 64bit(ただし 整数部は53bitまで ) 9007199254740991 (約9千兆)が限界 もっと大きな整数を扱いたい! 全世界の負債総額は 2京円以上 だってさ TwitterのIDも53bitでは表現しきれない 時代は64bit DBにも64bit整数とかあるよね

Slide 12

Slide 12 text

背景 背景 BigInt 登場! 現在はStage3 Node v10 でサポート ただし --harmony-bigint が必要 64bitではなく 任意精度 https://tc39.github.io/proposal-bigint/

Slide 13

Slide 13 text

さっそく使ってみる さっそく使ってみる

Slide 14

Slide 14 text

さっそく使ってみる さっそく使ってみる まずはビルド 正式リリースされたから公式ページからインストール! $ git clone --depth 1 https://github.com/nodejs/node.git $ cd node $ ./configure $ make -j4 # 並列ジョブ数はCPUのコア数に合わせる $ ./node -v # バージョン確認! v10.0.0-pre https://nodejs.org/

Slide 15

Slide 15 text

さっそく使ってみる さっそく使ってみる BigIntの生成 100n, 0x100n BigInt(100), BigInt("100"), BigInt("0x100") 型変換: Number(100n), 100n.toString() 小数点以下は切り捨てられる: (1n / 2n) === 0n Number型との共演はNG ビットシフトすら 1n << 10n と書く 文字列結合は "a" + 1n でOK

Slide 16

Slide 16 text

速度検証 速度検証

Slide 17

Slide 17 text

速度検証 速度検証 現在最大の (2^77232917 - 1) 超速い! メルセンヌ素数 $ time node --harmony-bigint -e "2n ** 77232917n - 1n" real 0m0.110s ←0.11秒!! user 0m0.094s sys 0m0.016s

Slide 18

Slide 18 text

速度検証 速度検証 底を変えてみる $ time node --harmony-bigint -e "3n ** 77232917n - 1n" real 124m47.252s ←2時間!? user 124m43.277s sys 0m0.260s $ time node --harmony-bigint -e "4n ** 77232917n - 1n" real 0m0.161s ←0.16秒! user 0m0.132s sys 0m0.029s

Slide 19

Slide 19 text

速度検証 速度検証 10進文字列に変換してみる 16進文字列に変換してみる $ time node --harmony-bigint -e "(2n ** 77232917n - 1n).toString( real 473m33.712s ←8時間!! user 473m32.767s sys 0m0.208s $ time node --harmony-bigint -e "(2n ** 77232917n - 1n).toString( real 0m0.165s ←0.16秒! user 0m0.125s sys 0m0.040s

Slide 20

Slide 20 text

速度検証 速度検証 結果 2進数で簡単に計算できるものは速い 2の累乗、4の累乗 16進文字列への変換 逆に、2進数で時間がかかるものは遅い 3の累乗 10進文字列への変換 考察: 内部的には2進数ベースで計算している? (考察じゃなくてソース読めよ…)

Slide 21

Slide 21 text

NUMBER型との速度比較 NUMBER型との速度比較

Slide 22

Slide 22 text

NUMBER型との速度比較 NUMBER型との速度比較 雑なベンチマーク let i, j, k, val; for(i = 1; i <= 100; i++) { for(j = 1; j <= 100; j++) { for(k = 1; k <= 100; k++) { for(l = 1; l <= 100; l++) { val = i; val += j; val *= k; val %= l; } } } }

Slide 23

Slide 23 text

NUMBER型との速度比較 NUMBER型との速度比較 Number BigInt(数値に n を追加) Number型で収まる範囲の演算でも、BigIntだと遅い ⇒Numberを使えるなら使ったほうがいい real 0m0.381s ←0.38秒 user 0m0.352s sys 0m0.029s real 0m22.087s ←22秒! user 0m24.116s sys 0m0.355s

Slide 24

Slide 24 text

本番環境で使うには? 本番環境で使うには?

Slide 25

Slide 25 text

本番環境で使うには? 本番環境で使うには? 本番環境ではLTSを使いたい 10月まで待つ? 本番環境は --harmony とかあまり使いたくない v12まで待つ? v12のLTSリリースは来年の10月? 待ってられん!

Slide 26

Slide 26 text

本番環境で使うには? 本番環境で使うには? Babelはどうよ https://babeljs.io/blog/2017/09/12/planning-for- 7.0#stage-3-bigint-new-un nished

Slide 27

Slide 27 text

本番環境で使うには? 本番環境で使うには? 多分こういうこと ↓バベるとこうなる(多分)↓ 全部の演算子を置き換えなきゃアカン a += b; // a, bがBigInt型かどうかわからない class BigInt { ... } // ラップ用のクラス if (typeof a === "BigInt") { a = a.plus(b); } else { a += b; }

Slide 28

Slide 28 text

本番環境で使うには? 本番環境で使うには? 今はまだ big-integer パッケージを使おう 10進数ベースの演算 10000000 単位でパックしている 意外と速い $ npm i -S big-integer const BigInteger = require("big-integer"); // "150" const strValue = BigInteger(100) .plus(50) .toString();

Slide 29

Slide 29 text

まとめ まとめ Node v10で BigInt に対応したよ ただし --harmony-bigint が必要だよ 2進表現で高速に計算できるものは速いよ Numberよりはかなり遅いよ 現時点では big-integer を使おう 関西Node学園もよろしく! 登壇者大募集! 手品に興味があったら声をかけてね!

Slide 30

Slide 30 text

ありがとうございました ありがとうございました

Slide 31

Slide 31 text

おまけ おまけ ここまで見てくれてありがとう( *´艸`)

Slide 32

Slide 32 text

BIGINT VS BIG-INTEGER 2番勝負 BIGINT VS BIG-INTEGER 2番勝負

Slide 33

Slide 33 text

ROUND 1: 雑ベンチ再び ROUND 1: 雑ベンチ再び big-integer版 const BigInteger = require("big-integer"); let i, j, k, val; for(i = 1; i <= 100; i++) { for(j = 1; j <= 100; j++) { for(k = 1; k <= 100; k++) { for(l = 1; l <= 100; l++) { val = BigInteger(i); val = val.plus(j); val = val.multiply(k); val = val.mod(l); } } } }

Slide 34

Slide 34 text

ROUND 1: 雑ベンチ再び ROUND 1: 雑ベンチ再び 計測結果 BigIntの結果(再掲) BigIntより速くね? 実は、big-integerはNumberに収まる範囲の演算はその まま計算するので速い real 0m7.587s user 0m8.001s sys 0m0.362s real 0m22.087s user 0m24.116s sys 0m0.355s

Slide 35

Slide 35 text

ROUND 2: 場外乱闘 ROUND 2: 場外乱闘 …というわけで、Number型の範囲外でもう一度挑戦して みます。

Slide 36

Slide 36 text

ROUND 2: 場外乱闘 ROUND 2: 場外乱闘 big-integer版 const BigInteger = require("big-integer"); let i, j, k, val; for(i = 1; i <= 100; i++) { for(j = 1; j <= 100; j++) { for(k = 1; k <= 100; k++) { for(l = 1; l <= 100; l++) { val = BigInteger(Number.MAX_SAFE_INTEGER).plus(i) val = val.plus(j); val = val.multiply(k); val = val.mod(l); } } } } real 0m41.659s user 0m42.663s sys 0m0.932s

Slide 37

Slide 37 text

ROUND 2: 場外乱闘 ROUND 2: 場外乱闘 BigInt版 let i, j, k, val; for(i = 1n; i <= 100n; i++) { for(j = 1n; j <= 100n; j++) { for(k = 1n; k <= 100n; k++) { for(l = 1n; l <= 100n; l++) { val = BigInt(Number.MAX_SAFE_INTEGER) + i; val += j; val *= k; val %= l; } } } } real 0m30.764s user 0m33.004s sys 0m0.343s

Slide 38

Slide 38 text

ROUND 2: 場外乱闘 ROUND 2: 場外乱闘 BigIntのほうが1.3倍速かった 変換と加算が増えてBigIntさんも遅くなったけどね

Slide 39

Slide 39 text

結論 結論 Numberに収まるときもある場合はbig-integerも検討の 価値あり 収まらないことが明確な場合はBigIntのほうがいい

Slide 40

Slide 40 text

No content