Date post: | 19-Feb-2017 |
Category: |
Technology |
Upload: | steven-proctor |
View: | 555 times |
Download: | 0 times |
BEAMing With Joy
Slides, any videos, and answers to any questions
you may have of this talk can be found at*:
http://www.proctor-it.com/beaming-with-joy/
* To be updated as videos and questions come
The BEAM
• Bogdan/Björn's Erlang Abstract Machine
• a.k.a. The Erlang VM
I thought this was ElixirConf!?
–José Valim on Functional Geekery
“I liked everything I saw there [the Erlang ecosystem], but hated the things I didn’t see.”
Confession Time
Agenda• Scheduler
• Monitoring
• Types - Annotating and Checking
• Testing
• Behaviors
• Erlang and it’s capabilities
• Bonus
Erlang Scheduler
• Run Queues
• Load Balancing
• Schedulers
• Preemptive Scheduling & Reductions
Erlang Scheduler
Image courtesy of Augie De Blieck Jr. (@augiedb) http://www.variousandsundry.com/cs/
Monitoring Your App
• Erlang’s observer module
• Erlang’s c module
:observer.start• System Overview
• Load charts
• Application view
• Process Overview
• Trace and messaging information
• Process messages, backtrace, state
• Remote node connection
:observer
:observer
:observer
:observer
:observer
:observer
:observer
Erlang’s c module
• For when you can’t open observer GUI
• :c.regs/0 & :c.nregs/0
• :c.i/0 & :c.i/3
• :c.pid/3
• :c.bt/1
:c.regs/0> :c.regs
** Registered procs on node nonode@nohost ** Name Pid Initial Call Reds Msgs 'Elixir.Logger' <0.46.0> 'Elixir.GenEvent':init_it 343 0 'Elixir.Logger.Superv <0.45.0> supervisor:'Elixir.Superv 366 0 'Elixir.Logger.Watche <0.48.0> supervisor:'Elixir.Superv 118 0 application_controlle <0.7.0> erlang:apply/2 60418 0 code_server <0.19.0> erlang:apply/2 181953 0 elixir_code_server <0.38.0> elixir_code_server:init/1 52 0 elixir_counter <0.39.0> elixir_counter:init/1 26 0 elixir_sup <0.37.0> supervisor:elixir_sup/1 165 0 erl_prim_loader <0.3.0> erlang:apply/2 944247 0 error_logger <0.6.0> gen_event:init_it/6 481 0 file_server_2 <0.18.0> file_server:init/1 1034 0 global_group <0.17.0> global_group:init/1 59 0 global_name_server <0.13.0> global:init/1 51 0 inet_db <0.16.0> inet_db:init/1 206 0 init <0.0.0> otp_ring0:start/2 16056 0 kernel_safe_sup <0.28.0> supervisor:kernel/1 124 0 kernel_sup <0.11.0> supervisor:kernel/1 49109 0 rex <0.12.0> rpc:init/1 35 0 standard_error <0.21.0> erlang:apply/2 29 0 standard_error_sup <0.20.0> supervisor_bridge:standar 41 0 timer_server <0.59.0> timer:init/1 5633 0 user <0.24.0> group:server/3 68 0 user_drv <0.23.0> user_drv:server/2 6812 0 wxe_master <0.56.0> wxe_master:init/1 679 0
** Registered ports on node nonode@nohost ** Name Id Command :ok
:c.i/0> :c.i Pid Initial Call Heap Reds Msgs Registered Current Function Stack <0.0.0> otp_ring0:start/2 2586 16056 0 init init:loop/1 2 <0.3.0> erlang:apply/2 2586 974483 0 erl_prim_loader erl_prim_loader:loop/3 6 <0.6.0> gen_event:init_it/6 987 481 0 error_logger gen_event:fetch_msg/5 8 <0.7.0> erlang:apply/2 6772 60418 0 application_controlle gen_server:loop/6 7 <0.9.0> application_master:init/4 376 44 0 application_master:main_loop/2 6 <0.10.0> application_master:start_it/4 233 69 0 application_master:loop_it/4 5 <0.11.0> supervisor:kernel/1 4185 49109 0 kernel_sup gen_server:loop/6 9 <0.12.0> rpc:init/1 233 35 0 rex gen_server:loop/6 9 <0.13.0> global:init/1 233 51 0 global_name_server gen_server:loop/6 9 …
:c.i/3> :c.i(0, 46, 0) [registered_name: Logger, current_function: {GenEvent, :fetch_msg, 5}, initial_call: {:proc_lib, :init_p, 5}, status: :waiting, message_queue_len: 0, messages: [], links: [#PID<0.45.0>], dictionary: ["$ancestors": [Logger.Supervisor, #PID<0.44.0>], "$initial_call": {GenEvent, :init_it, 6}], trap_exit: false, error_handler: :error_handler, priority: :normal, group_leader: #PID<0.24.0>, total_heap_size: 752, heap_size: 376, stack_size: 8, reductions: 343, garbage_collection: [min_bin_vheap_size: 46422, min_heap_size: 233, fullsweep_after: 65535, minor_gcs: 3], suspending: []] >
:c.bt/1> :c.bt(:c.pid(0, 46, 0)) Program counter: 0x0000000015266918 ('Elixir.GenEvent':fetch_msg/5 + 72) CP: 0x0000000000000000 (invalid) arity = 0
0x0000000014a18d40 Return addr 0x00000000132eef38 (proc_lib:init_p_do_apply/3 + 56) y(0) false y(1) [] y(2) [{handler,'Elixir.Logger.Backends.Console','Elixir.Logger.Backends.Console',#{colors=>#{debug=>cyan,enabled=>true,error=>red,info=>normal,warn=>yellow},format=>[<<1 byte>>,time,<<1 byte>>,metadata,<<1 byte>>,level,<<2 bytes>>,levelpad,message,<<1 byte>>],level=>nil,metadata=>[]},<0.49.0>,#Ref<0.0.0.87>},{handler,'Elixir.Logger.Config','Elixir.Logger.Config',#{async_threshold=>15,level=>debug,mode=>async,sync_threshold=>20,translators=>[{'Elixir.Logger.Translator',translate}],truncate=>8096,utc_log=>false},<0.47.0>,#Ref<0.0.0.81>}] y(3) 'Elixir.Logger' y(4) <0.45.0>
0x0000000014a18d70 Return addr 0x0000000012774c88 (<terminate process normally>) y(0) Catch 0x00000000132eef58 (proc_lib:init_p_do_apply/3 + 88) :ok >
Types in BEAM
• Strongly Typed
• Small Set of Types
• Dynamically Typed
• Optional Typing
Optional Typing
• Type annotations
• @spec directive
• Type checking
• Success Typing
Dialyzer
• Success Typing1
• “It will hurt your feelings”
• @spec directive
• dialyxir - Dialyzer for Elixir
1. http://user.it.uu.se/~kostis/Papers/succ_types.pdf
–Me
“Sadly, working in a dynamic language makes me lazy
when it comes to thinking about types upfront.”
–and you????
TypEr
• Shows Type information
• Adds Type annotations to source code
1. http://user.it.uu.se/~kostis/Papers/succ_types.pdf
Testing
• Property Testing
• Concurrency Testing
Property Testing
• QuickCheck for Erlang (by QuviQ)
• PropEr
Concurrency Testing
• Concuerror
Behaviours
• Generic implementations of common tasks
• Callbacks provide the specific details
• e.g. gen_server, gen_event, gen_fsm, supervisor
• The best part?
Behaviours
You can create your own!!!!!
Creating Your Own Behaviour
• “Error”-able task
Creating Your Own Behaviour
@callback process(State :: term()) -> {{'ok', Result :: term()} | {'error', Reason :: term()}}.
Learn You Some Erlang
• Don’t need to know the whole language
• Just enough to have general idea of what Erlang provides but Elixir doesn’t (yet) wrap
• Or at least enough to know to look
Learn You Some Erlang
Erlang :gen_tcp.connect/3‘s first argument(Address) is either an :inet.ip_address() which is a tuple of octets or an :inet.hostname() which is a char_list. Write a function format_host that takes a string a returns a valid format for :gen_tcp.connect
format_host("192.168.0.1") #=> {192, 168, 0, 1} format_host("www.example.com") #=> 'www.example.com'
2: http://elixirexperience.com/
Elixir Experience2 Problem: 15
Learn You Some Erlang
def format_host(host_address) do address = to_char_list(host_address) case :inet.parse_strict_address(address) do {:ok, parsed_address} -> parsed_address _ -> address end end
def format_host(host_address) do address = to_char_list(host_address) case :inet.parse_strict_address(address) do {:ok, parsed_address} -> parsed_address _ -> address end end
Other Languages• Core Erlang
• LFE (Lisp Flavoured Erlang) - Lisp
• Joxa - Lisp
• Erlog - Prolog on Erlang VM
• Yhc - York Haskell Compiler
• erlyjs - JavaScript interpreter for Erlang
• microkanren implementation
• luerl - Lua in Erlang
Other “Cool Stuff” For Inspiration
• Webmachine
• Ling - Erlang on Xen
• Unikernels
• Erlang on Mega Core Architecture Research
• and Lots, Lots more
Calls to Action
• Expand your User Groups
• Elixir application usage across BEAM languages
• Plug
• Reach beyond Elixir and share what you know
About Me• @stevenproctor
• http://www.proctor-it.com
• Functional Geekery
• @fngeekery
• PlanetErlang
• @planeterlang
• DFW Erlang User Group
• @dfwerl