Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Elixir におけるリスト反転処理の実装を覗いてみよう
Search
Shohei Kajihara
July 01, 2019
Technology
0
2.3k
Elixir におけるリスト反転処理の実装を覗いてみよう
2019/07/01 【学生限定】Akatsuki Geek Live Vol.3【LT会:7/1(月)】 にて発表した資料です。
Shohei Kajihara
July 01, 2019
Tweet
Share
Other Decks in Technology
See All in Technology
OpenTelemetryセマンティック規約の恩恵とMackerel APMにおける活用例 / SRE NEXT 2025
mackerelio
3
2k
衛星運用をソフトウェアエンジニアに依頼したときにできあがるもの
sankichi92
1
1k
All About Sansan – for New Global Engineers
sansan33
PRO
1
1.2k
第64回コンピュータビジョン勉強会「The PanAf-FGBG Dataset: Understanding the Impact of Backgrounds in Wildlife Behaviour Recognition」
x_ttyszk
0
240
ABEMAの本番環境負荷試験への挑戦
mk2taiga
5
1.3k
ロールが細分化された組織でSREは何をするか?
tgidgd
1
420
研究開発部メンバーの働き⽅ / Sansan R&D Profile
sansan33
PRO
3
18k
助けて! XからWaylandに移行しないと新しいGNOMEが使えなくなっちゃう 2025-07-12
nobutomurata
2
200
Contract One Engineering Unit 紹介資料
sansan33
PRO
0
6.9k
LLM拡張解体新書/llm-extension-deep-dive
oracle4engineer
PRO
23
6.3k
shake-upを科学する
rsakata
7
1k
ゼロから始めるSREの事業貢献 - 生成AI時代のSRE成長戦略と実践 / Starting SRE from Day One
shinyorke
PRO
0
110
Featured
See All Featured
What's in a price? How to price your products and services
michaelherold
246
12k
Git: the NoSQL Database
bkeepers
PRO
430
65k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
282
13k
The World Runs on Bad Software
bkeepers
PRO
70
11k
YesSQL, Process and Tooling at Scale
rocio
173
14k
Being A Developer After 40
akosma
90
590k
Optimizing for Happiness
mojombo
379
70k
The Language of Interfaces
destraynor
158
25k
BBQ
matthewcrist
89
9.7k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.4k
Optimising Largest Contentful Paint
csswizardry
37
3.3k
The Psychology of Web Performance [Beyond Tellerrand 2023]
tammyeverts
48
2.9k
Transcript
Elixir における Elixir における リスト反転処理の実装を リスト反転処理の実装を 覗いてみよう 覗いてみよう 2019/07/01 Akatsuki
Geek Live Vol.3 アカツキ サーバーエンジニア 梶原星平 (@s-capybara)
⾃⼰紹介 ⾃⼰紹介 2017 年 アカツキに新卒⼊社(3 年⽬) Elixir でゲームサーバーを書いています
今⽇の⽬的 今⽇の⽬的 Elixir の紹介 プログラミング⾔語の中⾝の学び⽅
Elixir とは Elixir とは プログラミング⾔語 関数型 動的型付け 不変性 (immutability) Erlang
VM 上で動作 並⾏性 (concurrency) 耐障害性 (fault-tolerance) Erlang の関数を呼び出せる
不変性 不変性 予想外の値変更による実装ミスが起きにくくなる defmodule Sample do def foo() do bar
= 1 if :rand.uniform() > 0.5 do bar = 2 IO.puts("Modified bar to 2!") end bar end end iex(1)> Sample.foo() Modified bar to 2! 1
List List iex(2)> numbers = [1, 2, 3] [1, 2,
3]
List の基本操作 List の基本操作 Lisp と同じく Car, Cdr, Cons 処理ができる
Car: リストの先頭を取り出す Cdr: リストの残り部分を取り出す Cons: リストの先頭に要素を⾜す iex(3)> [head | _] = numbers iex(2)> head 1 iex(4)> [_ | tail] = numbers iex(4)> tail [2, 3] iex(5)> [0 | numbers] [0, 1, 2, 3]
Enum.reverse Enum.reverse リスト(など)を反転する関数 標準の関数が⾼速なので、 ⾃前実装は NG と⾔われている iex(6)> Enum.reverse(numbers) [3,
2, 1]
気になるところ 気になるところ 1. リストはどういうデータ構造なのか? 2. 標準の関数はなぜ⾼速なのか?
解決策1: 本を読む 解決策1: 本を読む The Beam Book ( ) Erlang
VM の中⾝が紹介されている (プロセス、スケジューラ、型システム、... ) 無料で読める(ただし英語) 書籍は著者視点による説明 説明の順序にストーリーがあるので⼊⾨に最適 公式ドキュメントなどより先に書籍にあたるのが おすすめ https://github.com/happi/theBeamBook
Erlang VM の型システム Erlang VM の型システム 64 ( または32) bits
で 1 word 末尾 2 bits ( あるいはもっと) で型を表現 リストは「アドレス + 01 」という形の 1 word 00 Header (on heap) CP (on stack) 01 List (cons) 10 boxed 00 11 Pid
単⽅向リストの実体 単⽅向リストの実体 リストはポインタであり、 参照先の隣のアドレスがまたポインタになっている
解決策2: ソースコードを 解決策2: ソースコードを 読む 読む Elixir: Erlang: https://github.com/elixir-lang/elixir https://github.com/erlang/otp
Enum.reverse/1 の実装 Enum.reverse/1 の実装 簡単なやつだけ Elixir レイヤーで定義 結局、Erlang のコードを呼び出している @spec
reverse(t) :: list def reverse([]), do: [] def reverse([_] = list), do: list def reverse([element1, element2]), do: [element2, element1] def reverse([element1, element2 | rest]), do: :lists.reverse(rest, [element2, element1])
lists:reverse/2 の実装 lists:reverse/2 の実装 結局、C ⾔語実装の Built in Funciton (BIF)
を呼び出し ている %% Shadowed by erl_bif_types: lists:reverse/2 -spec reverse(List1, Tail) -> List2 when List1 :: [T], Tail :: term(), List2 :: [T], T :: term(). reverse(_, _) -> erlang:nif_error(undef).
lists_reverse_2 lists_reverse_2 erts/emulator/beam/erl_bif_lists.c というそれっぽい名前のファイルに lists_reverse_2 というそれっぽい名前の関数を発⾒
lists_reverse_2 ( 抜粋) lists_reverse_2 ( 抜粋) CAR, CDR, CONS をやっているらしい
(説明は後で図⽰) while (alloc_top < alloc_end) { // リストをポインタ化する Eterm *pair = list_val(list); // 確保したヒープ領域の先頭を [ リストの先頭 | 反転済みリスト ] に tail = CONS(alloc_top, CAR(pair), tail); // 続きは Cdr から list = CDR(pair); ASSERT(is_list(list) || is_nil(list)); // 2 words 分ヒープ領域のへのポインタを進める alloc_top += 2; }
リスト操作のマクロ リスト操作のマクロ CAR, CDR, CONS の定義(説明は割愛) #define TAG_PRIMARY_LIST 0x1 //
01 の⾜し算でポインタをリストに、引き算でリストをポインタに #define _unchecked_make_list(x) ((Uint)(x) + TAG_PRIMARY_LIST) #define _unchecked_list_val(x) ((Eterm*) ((x) - TAG_PRIMARY_LIST) // ポインタの指すアドレスに値を仕舞ったのちリストにする #define CONS(hp, car, cdr) \ (CAR(hp)=(car), CDR(hp)=(cdr), make_list(hp)) // ポインタの指すアドレスが CAR, その隣が CDR #define CAR(x) ((x)[0]) #define CDR(x) ((x)[1])
lists_reverse_2 の概観 lists_reverse_2 の概観 (1/4) (1/4)
lists_reverse_2 の概観 lists_reverse_2 の概観 (2/4) (2/4)
lists_reverse_2 の概観 lists_reverse_2 の概観 (3/4) (3/4)
lists_reverse_2 の概観 lists_reverse_2 の概観 (4/4) (4/4)
標準の関数は 標準の関数は なぜ速いのか? なぜ速いのか? そもそも C ⾔語なので速い 不変性を保つ必要がない result は
C ⾔語上のローカル変数
結局、理解できて 結局、理解できて 何が嬉しいのか? 何が嬉しいのか? すぐに役⽴つわけではないが... 「この⾔語ではどういう操作のコストが⾼いの か?」など理解したうえでコードが書けるようにな る(かも) トラブルシューティングに強くなる(かも)
まとめ まとめ まず本を読み、その後ソースコードを読もう すぐには役に⽴たないが、中⾝を知っておいた⽅が 安⼼