SlideShare a Scribd company logo
The 1990s Called. They Want Their
Code Back.
5 Ways Your Code is Stuck in the 90s
3 Mar 2015
Jonathan Oliver
$ whoami
@jonathan_oliver
http://jonathanoliver.com
http://github.com/joliver
http://keybase.com/joliver
Distributed Podcast
Chief SmartyPants, SmartyStreets
Overview
Disclaimers
Why Go Exists
#1 Implicit messaging
#2 Complex Threading
#3 RPC Everywhere
#4 GC
#5 Logging
Conclusion
Caveats: But, but, but...
Your mileage may vary
Don't apply blindly or wholesale
Sharp knife
Our experience
C# on Windows vs Go on Linux (512 req/s)
hdrhistogram.org
C# Windows vs Golang Linux at 4096 req/s
hdrhistogram.org
C# Windows vs Golang Linux at 8192 req/s
hdrhistogram.org
Why Go Exists
(The real reason)
Compile times?
Multi-core, networked systems
1990ism #1: Implicit Messaging
Hint Dropping Fallacy
If you have to ask, it doesn't mean as much
If you really loved me, you'd know
Implicit Messaging: PHP
<?php
$sql = 'UPDATE Users SET ' +
'firstname = ' $_GET['firstname'] + ','+
'lastname = ' $_GET['lastname'] + ','+
'phone = ' $_GET['phone'] + ','+
'password = ' hash($_GET['password']) + ','+
'WHERE id=' + $_GET['id'];
mysql_query($sql, $connection) or die("Couldn't execute query.");
?>
Implicit Messaging: Go
Where does HTTP stop and the application start?
func implicit(response http.ResponseWriter, request *http.Request) {
query := request.URL.Query()
statement := `UPDATE Users
SET firstname = '%s',
lastname = '%s',
phone = '%s',
password='%s'
WHERE id = %s;`
sql.Execute(statement,
query.Get("firstname"),
query.Get("lastname"),
query.Get("phone"),
hashAndSalt(query.Get("password")),
query.Get("id"))
response.WriteHeader(200)
}
Implicit Messaging: Boundaries
HTTP bleeds all over the application
.NET: System.Web.HttpContext.Current.Request...
Implicit Messaging: Intention?
I know! I'll use a DTO that corresponds to my table!
Hello, Ruby on Rails / Active Record
type User struct {
ID int
FirstName string
LastName string
Phone string
Password []byte
}
Staring at the table salt: implicit or inferred understanding
type User struct {
ID int
FirstName string
LastName string
Phone string
Password []byte
}
Solution #1: Explicit Contracts
Application Protocols 101:
HTTP: Hypertext Transfer Protocol
SMTP: Simple Mail Transfer Protocol
FTP: File Transfer Protocol (control channel, port 21)
Transfering what?
Messages!
Review HTTP, SMTP, etc. RFC specifications
e.g. HTTP message body, HTTP message headers, etc.
HTTP, SMTP, etc. encapsulate a message
DTOs: What Are Your Intentions?
Implicit / Inferred (Active Record)
type User struct {
ID int
FirstName string
LastName string
Phone string
Password []byte
}
Explicit
type ChangePasswordCommand struct {
UserID int
NewPassword string
NewPasswordConfirmed string
OldPassword string
}
Messaging How-To
HTTP values into message struct
URL+VERB determines message type
Query String
Form Values
Deserialize body or HTTP 400
Messaging How-To (continued)
HTTP is an interface to application
Push message into application layer
Additional interfaces, e.g. SMTP, AMQP, CLI, etc.
1990ism #2: Complex Threading Code
Goroutine per HTTP request
Terrible for shared state like:
Incrementing a counter
Modify a map
Updating object references
Goroutine per request = manual synchronization of shared state
Go doesn't save us from synchronization code
go keyword can make things harder
package main
import "fmt"
import "time"
func main() {
for i := 0; i < 4; i++ {
go func() {
fmt.Println(i) // bad closure
}()
}
time.Sleep(time.Millisecond)
}
Solution #2: In-process "microservices" (Actors)
Actor Example:
// uncontended state
func listen() {
for message := this.incomingChannel {
// single-threaded with synchronization primitives
counter++
map[message.UserID]++
// additional message processing code
this.outgoingChannel <- message
}
}
The Unix Way: Small & Composable
Message In, Message Out: Easy Testing
Pipes and Filters
Marshal to external process
Break Apart Stateful and Stateless Operations
func (this CounterPhase) listen() {
for message := this.incomingChannel {
counter++ // stateful; single-threaded with no sync code
message.Sequence = counter
this.outgoingChannel <- message // outgoing to process phase
}
}
func (this ProcessPhase) listen() {
// can be stateless because state was assigned in previous phase
for i := 0; i < runtime.NumCPU(); i++ {
go func() {
for message := this.incomingChannel { // incoming from counter phase
// process message (CPU/network operations)
this.outgoingChannel <- message
}
}()
}
}
HTTP RPC
Block the caller until the work is done
func handle(w http.ResponseWriter, r *http.Request) {
var wg sync.WaitGroup
wg.Add(1)
query := r.URL.Query()
this.application <- ChangePasswordCommand{
UserID: cookie.Get("user-id"),
OldPassword: query.Get("old-password"),
NewPassword: query.Get("new-password"),
NewPasswordConfirmed: query.Get("new-password-confirmed"),
WaitGroup: &wg,
}
wg.Wait()
// return result of application
}
Queues and Natural Backpressure
Typical performance characteristics at 90% vs 99% utilization
1990ism #3: Remote Procedure Call Everywhere
Fallacies of Distributed Computing
The Network is Reliable
Latency is Zero
Typical Application Behavior (Transaction Script)
Opens a DB connection
Start a transaction
Execute DB operation(s)
Other operations? (Send email, etc.)
Commit transaction
Wash, rinse, repeat
What could possibly go wrong?
Fragile RPC
Per business demands, we add "one more thing", e.g. email, etc.
When network is down, lots of things break
Bill credit card, send email, etc.
Netflix architecture
Solution #3: Actors (again) + Embrace Failure
Simple Retry Code
import "time"
func listen() {
// simple retry
for message := range this.incoming {
for attempt := 0; attempt < 5; attempt++ {
if err := emailReceipt(message); err != nil {
time.Sleep(time.Second * 30)
continue
}
}
}
}
BONUS POINTS: Simple Batching
Story: Moving one box at a time
func listen() {
for message := range this.incoming {
addToUnitOfWork(message)
if len(this.incoming) == 0 || len(batch) >= 100 {
commit()
newTransaction()
}
}
}
1-2 order of magnitude performance increase
1990ism #4: Abuse Garbage Collection
Primitive, mark-and-sweep implementation
But getting better...
Java and .NET
pointers
maps
strings
slices
The 1990s Called. They Want Their Code Back.
GC Pause Latency and You
Are 500 ms GC pauses okay?
How about 5 seconds?
What is latency costing you?
Solution #4: Understanding GC Behavior
Measure, measure, measure
Avoid pointers (where possible)
Preallocate and re-use structures (where possible)
My bug report (issue #9477) & maps of structs (v1.5)
Keep byte slices off heap (where possible)
Size of the heap
1990ism #5: Logging Is Sufficient
Logging is awesome, but very "trees" focused
Stored?
Where?
How long?
Who analyzes and when?
Calls to log.Print result in blocking syscalls that yield the goroutine
Hard to make blocking/yielding calls
Solution #5: Metrics, Metrics, Everywhere
Business Value (Coda Hale: Metrics, Metrics, Everywhere)
Business value is anything which makes people more likely to give us money
We want to generate more business value
Our code generates business value when it runs—NOT when we write it.
We need to make better decisions about our code
We need to know what our code does when it runs
We can’t do this unless we MEASURE it
Our mental model of our code is not our code.
Example: This code can’t possibly work; it works.
Example: This code can’t fail; it fails
Example: Do these changes make things faster?
We can’t know until we MEASURE it
We improve our mental model by measuring what our code DOES
A better mental model makes us better at deciding what to do—at generating business
value
The 1990s Called. They Want Their Code Back.
Understanding Your Application
Instrument your application (metrics)
Understand how it's being used
Understand the pathways that are taken (counters)
Understand how much (disk/memory/etc) you have left (gauges)
Service Providers
Librato (http://github.com/smartystreets/metrics)
Boundary
Datadog
Key Takeaways
Go != other languages
Work with concurrency primitives
Explicit messages
Message pipelines ("actors")
Simple logic, simple code
Thank you
3 Mar 2015
Jonathan Oliver
@jonathan_oliver(http://twitter.com/jonathan_oliver)
http://jonathanoliver.com(http://jonathanoliver.com)
http://github.com/joliver(http://github.com/joliver)
http://keybase.com/joliver(http://keybase.com/joliver)
Distributed Podcast
Chief SmartyPants, SmartyStreets

More Related Content

PPTX
Europe Virtual ALT.NET - EventStore v3
PPTX
Low latency in java 8 v5
PDF
Building a blockchain on tendermint
PPTX
Kerberos, NTLM and LM-Hash
PDF
Zimbra scripting with python
PPTX
Kerberos and its application in cross realm operations
PPT
SSO with kerberos
PDF
The 7 characteristics of container native infrastructure, LinuxCon/ContainerC...
Europe Virtual ALT.NET - EventStore v3
Low latency in java 8 v5
Building a blockchain on tendermint
Kerberos, NTLM and LM-Hash
Zimbra scripting with python
Kerberos and its application in cross realm operations
SSO with kerberos
The 7 characteristics of container native infrastructure, LinuxCon/ContainerC...

What's hot (20)

PDF
Cosmos SDK Workshop: How to Build a Blockchain from Scratch
PPTX
Chronicle Accelerate Crypto Investor conference
PPTX
Kerberos
PDF
The lies we tell our code, LinuxCon/CloudOpen 2015-08-18
PDF
Greyhound - Powerful Pure Functional Kafka Library
PPTX
WebSocket MicroService vs. REST Microservice
PDF
Advanced Microservices Caching Patterns - Devoxx UK
PDF
7 characteristics of container-native infrastructure, Docker Zurich 2015-09-08
PDF
Transaction Support in Pulsar 2.5.0
PDF
Ntlm Unsafe
PDF
Micro on NATS - Microservices with Messaging
PPTX
Making communications across boundaries simple with NServiceBus
PDF
Deep Dive In To Kerberos
PPTX
Chenli linux-kerne-community
PPTX
.NET Fest 2019. Irina Scurtu. Forget about HTTP
PDF
How Zhaopin contributes to Pulsar community
PDF
OpenSlava Infrastructure Automation Patterns
PDF
Micro Service Architecture
KEY
Webinar: Building Web Applications with MongoDB and Spring
PPTX
OpenStack and OpenFlow Demos
Cosmos SDK Workshop: How to Build a Blockchain from Scratch
Chronicle Accelerate Crypto Investor conference
Kerberos
The lies we tell our code, LinuxCon/CloudOpen 2015-08-18
Greyhound - Powerful Pure Functional Kafka Library
WebSocket MicroService vs. REST Microservice
Advanced Microservices Caching Patterns - Devoxx UK
7 characteristics of container-native infrastructure, Docker Zurich 2015-09-08
Transaction Support in Pulsar 2.5.0
Ntlm Unsafe
Micro on NATS - Microservices with Messaging
Making communications across boundaries simple with NServiceBus
Deep Dive In To Kerberos
Chenli linux-kerne-community
.NET Fest 2019. Irina Scurtu. Forget about HTTP
How Zhaopin contributes to Pulsar community
OpenSlava Infrastructure Automation Patterns
Micro Service Architecture
Webinar: Building Web Applications with MongoDB and Spring
OpenStack and OpenFlow Demos
Ad

Viewers also liked (7)

PPTX
Science education in the philippines 1960s
PDF
Journey in the Basic Education Curricular reforms
PPTX
Curriculum and instruction
PPTX
Postmodernism
PPT
Philippine education presentation
PPT
Introduction to post modernism
PDF
Curriculum models (Philippines' Curriculum Models)
Science education in the philippines 1960s
Journey in the Basic Education Curricular reforms
Curriculum and instruction
Postmodernism
Philippine education presentation
Introduction to post modernism
Curriculum models (Philippines' Curriculum Models)
Ad

Similar to The 1990s Called. They Want Their Code Back. (20)

PPTX
Go from a PHP Perspective
PDF
Building Web APIs that Scale
KEY
Google Go Overview
PDF
GoLang - Why It Matters
PDF
F# and SignalR for a FastWeb
PDF
Concurrency with Go
PPTX
Golang 101 (Concurrency vs Parallelism)
PPTX
Introduction to GoLang
PDF
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
PDF
JavaScript for Enterprise Applications
PDF
Messaging is not just for investment banks!
PDF
Go Building Web Applications 1st Edition Nathan Kozyra Mat Ryer download pdf
PDF
Taking the hippie bus to the enterprise
PDF
What is Reactive programming?
PDF
Enterprise 2020
PDF
Douglas Crockford: Serversideness
PDF
Download full Go Building Web Applications 1st Edition Nathan Kozyra Mat Ryer...
PDF
Instant Access to Go Building Web Applications 1st Edition Nathan Kozyra Mat ...
PDF
(Ebook) Go: Building Web Applications by Nathan Kozyra, Mat Ryer
KEY
node.js: Javascript's in your backend
Go from a PHP Perspective
Building Web APIs that Scale
Google Go Overview
GoLang - Why It Matters
F# and SignalR for a FastWeb
Concurrency with Go
Golang 101 (Concurrency vs Parallelism)
Introduction to GoLang
Voxxed Days Vienna - The Why and How of Reactive Web-Applications on the JVM
JavaScript for Enterprise Applications
Messaging is not just for investment banks!
Go Building Web Applications 1st Edition Nathan Kozyra Mat Ryer download pdf
Taking the hippie bus to the enterprise
What is Reactive programming?
Enterprise 2020
Douglas Crockford: Serversideness
Download full Go Building Web Applications 1st Edition Nathan Kozyra Mat Ryer...
Instant Access to Go Building Web Applications 1st Edition Nathan Kozyra Mat ...
(Ebook) Go: Building Web Applications by Nathan Kozyra, Mat Ryer
node.js: Javascript's in your backend

Recently uploaded (20)

PPTX
newyork.pptxirantrafgshenepalchinachinane
PDF
Alethe Consulting Corporate Profile and Solution Aproach
PPT
Ethics in Information System - Management Information System
PPTX
APNIC Report, presented at APAN 60 by Thy Boskovic
PPTX
E -tech empowerment technologies PowerPoint
PPTX
Cyber Hygine IN organizations in MSME or
DOC
Rose毕业证学历认证,利物浦约翰摩尔斯大学毕业证国外本科毕业证
PDF
mera desh ae watn.(a source of motivation and patriotism to the youth of the ...
PPTX
Mathew Digital SEO Checklist Guidlines 2025
PDF
Exploring The Internet Of Things(IOT).ppt
PPTX
1402_iCSC_-_RESTful_Web_APIs_--_Josef_Hammer.pptx
PDF
The Ikigai Template _ Recalibrate How You Spend Your Time.pdf
PDF
FINAL CALL-6th International Conference on Networks & IOT (NeTIOT 2025)
PPTX
Internet Safety for Seniors presentation
PPTX
Power Point - Lesson 3_2.pptx grad school presentation
PDF
Session 1 (Week 1)fghjmgfdsfgthyjkhfdsadfghjkhgfdsa
PPTX
Slides PPTX: World Game (s): Eco Economic Epochs.pptx
PDF
Introduction to the IoT system, how the IoT system works
PDF
Uptota Investor Deck - Where Africa Meets Blockchain
PPT
isotopes_sddsadsaadasdasdasdasdsa1213.ppt
newyork.pptxirantrafgshenepalchinachinane
Alethe Consulting Corporate Profile and Solution Aproach
Ethics in Information System - Management Information System
APNIC Report, presented at APAN 60 by Thy Boskovic
E -tech empowerment technologies PowerPoint
Cyber Hygine IN organizations in MSME or
Rose毕业证学历认证,利物浦约翰摩尔斯大学毕业证国外本科毕业证
mera desh ae watn.(a source of motivation and patriotism to the youth of the ...
Mathew Digital SEO Checklist Guidlines 2025
Exploring The Internet Of Things(IOT).ppt
1402_iCSC_-_RESTful_Web_APIs_--_Josef_Hammer.pptx
The Ikigai Template _ Recalibrate How You Spend Your Time.pdf
FINAL CALL-6th International Conference on Networks & IOT (NeTIOT 2025)
Internet Safety for Seniors presentation
Power Point - Lesson 3_2.pptx grad school presentation
Session 1 (Week 1)fghjmgfdsfgthyjkhfdsadfghjkhgfdsa
Slides PPTX: World Game (s): Eco Economic Epochs.pptx
Introduction to the IoT system, how the IoT system works
Uptota Investor Deck - Where Africa Meets Blockchain
isotopes_sddsadsaadasdasdasdasdsa1213.ppt

The 1990s Called. They Want Their Code Back.

  • 1. The 1990s Called. They Want Their Code Back. 5 Ways Your Code is Stuck in the 90s 3 Mar 2015 Jonathan Oliver
  • 3. Overview Disclaimers Why Go Exists #1 Implicit messaging #2 Complex Threading #3 RPC Everywhere #4 GC #5 Logging Conclusion
  • 4. Caveats: But, but, but... Your mileage may vary Don't apply blindly or wholesale Sharp knife
  • 5. Our experience C# on Windows vs Go on Linux (512 req/s) hdrhistogram.org
  • 6. C# Windows vs Golang Linux at 4096 req/s hdrhistogram.org
  • 7. C# Windows vs Golang Linux at 8192 req/s hdrhistogram.org
  • 8. Why Go Exists (The real reason) Compile times? Multi-core, networked systems
  • 10. Hint Dropping Fallacy If you have to ask, it doesn't mean as much If you really loved me, you'd know
  • 11. Implicit Messaging: PHP <?php $sql = 'UPDATE Users SET ' + 'firstname = ' $_GET['firstname'] + ','+ 'lastname = ' $_GET['lastname'] + ','+ 'phone = ' $_GET['phone'] + ','+ 'password = ' hash($_GET['password']) + ','+ 'WHERE id=' + $_GET['id']; mysql_query($sql, $connection) or die("Couldn't execute query."); ?>
  • 12. Implicit Messaging: Go Where does HTTP stop and the application start? func implicit(response http.ResponseWriter, request *http.Request) { query := request.URL.Query() statement := `UPDATE Users SET firstname = '%s', lastname = '%s', phone = '%s', password='%s' WHERE id = %s;` sql.Execute(statement, query.Get("firstname"), query.Get("lastname"), query.Get("phone"), hashAndSalt(query.Get("password")), query.Get("id")) response.WriteHeader(200) }
  • 13. Implicit Messaging: Boundaries HTTP bleeds all over the application .NET: System.Web.HttpContext.Current.Request...
  • 14. Implicit Messaging: Intention? I know! I'll use a DTO that corresponds to my table! Hello, Ruby on Rails / Active Record type User struct { ID int FirstName string LastName string Phone string Password []byte } Staring at the table salt: implicit or inferred understanding
  • 15. type User struct { ID int FirstName string LastName string Phone string Password []byte }
  • 17. Application Protocols 101: HTTP: Hypertext Transfer Protocol SMTP: Simple Mail Transfer Protocol FTP: File Transfer Protocol (control channel, port 21) Transfering what?
  • 18. Messages! Review HTTP, SMTP, etc. RFC specifications e.g. HTTP message body, HTTP message headers, etc. HTTP, SMTP, etc. encapsulate a message
  • 19. DTOs: What Are Your Intentions? Implicit / Inferred (Active Record) type User struct { ID int FirstName string LastName string Phone string Password []byte } Explicit type ChangePasswordCommand struct { UserID int NewPassword string NewPasswordConfirmed string OldPassword string }
  • 20. Messaging How-To HTTP values into message struct URL+VERB determines message type Query String Form Values Deserialize body or HTTP 400
  • 21. Messaging How-To (continued) HTTP is an interface to application Push message into application layer Additional interfaces, e.g. SMTP, AMQP, CLI, etc.
  • 22. 1990ism #2: Complex Threading Code
  • 23. Goroutine per HTTP request Terrible for shared state like: Incrementing a counter Modify a map Updating object references
  • 24. Goroutine per request = manual synchronization of shared state Go doesn't save us from synchronization code go keyword can make things harder package main import "fmt" import "time" func main() { for i := 0; i < 4; i++ { go func() { fmt.Println(i) // bad closure }() } time.Sleep(time.Millisecond) }
  • 25. Solution #2: In-process "microservices" (Actors)
  • 26. Actor Example: // uncontended state func listen() { for message := this.incomingChannel { // single-threaded with synchronization primitives counter++ map[message.UserID]++ // additional message processing code this.outgoingChannel <- message } } The Unix Way: Small & Composable Message In, Message Out: Easy Testing Pipes and Filters Marshal to external process
  • 27. Break Apart Stateful and Stateless Operations func (this CounterPhase) listen() { for message := this.incomingChannel { counter++ // stateful; single-threaded with no sync code message.Sequence = counter this.outgoingChannel <- message // outgoing to process phase } } func (this ProcessPhase) listen() { // can be stateless because state was assigned in previous phase for i := 0; i < runtime.NumCPU(); i++ { go func() { for message := this.incomingChannel { // incoming from counter phase // process message (CPU/network operations) this.outgoingChannel <- message } }() } }
  • 28. HTTP RPC Block the caller until the work is done func handle(w http.ResponseWriter, r *http.Request) { var wg sync.WaitGroup wg.Add(1) query := r.URL.Query() this.application <- ChangePasswordCommand{ UserID: cookie.Get("user-id"), OldPassword: query.Get("old-password"), NewPassword: query.Get("new-password"), NewPasswordConfirmed: query.Get("new-password-confirmed"), WaitGroup: &wg, } wg.Wait() // return result of application }
  • 29. Queues and Natural Backpressure Typical performance characteristics at 90% vs 99% utilization
  • 30. 1990ism #3: Remote Procedure Call Everywhere
  • 31. Fallacies of Distributed Computing The Network is Reliable Latency is Zero
  • 32. Typical Application Behavior (Transaction Script) Opens a DB connection Start a transaction Execute DB operation(s) Other operations? (Send email, etc.) Commit transaction Wash, rinse, repeat What could possibly go wrong?
  • 33. Fragile RPC Per business demands, we add "one more thing", e.g. email, etc. When network is down, lots of things break Bill credit card, send email, etc. Netflix architecture
  • 34. Solution #3: Actors (again) + Embrace Failure
  • 35. Simple Retry Code import "time" func listen() { // simple retry for message := range this.incoming { for attempt := 0; attempt < 5; attempt++ { if err := emailReceipt(message); err != nil { time.Sleep(time.Second * 30) continue } } } }
  • 36. BONUS POINTS: Simple Batching Story: Moving one box at a time func listen() { for message := range this.incoming { addToUnitOfWork(message) if len(this.incoming) == 0 || len(batch) >= 100 { commit() newTransaction() } } } 1-2 order of magnitude performance increase
  • 37. 1990ism #4: Abuse Garbage Collection
  • 38. Primitive, mark-and-sweep implementation But getting better... Java and .NET pointers maps strings slices
  • 40. GC Pause Latency and You Are 500 ms GC pauses okay? How about 5 seconds? What is latency costing you?
  • 42. Measure, measure, measure Avoid pointers (where possible) Preallocate and re-use structures (where possible) My bug report (issue #9477) & maps of structs (v1.5) Keep byte slices off heap (where possible) Size of the heap
  • 43. 1990ism #5: Logging Is Sufficient
  • 44. Logging is awesome, but very "trees" focused Stored? Where? How long? Who analyzes and when? Calls to log.Print result in blocking syscalls that yield the goroutine Hard to make blocking/yielding calls
  • 45. Solution #5: Metrics, Metrics, Everywhere
  • 46. Business Value (Coda Hale: Metrics, Metrics, Everywhere) Business value is anything which makes people more likely to give us money
  • 47. We want to generate more business value
  • 48. Our code generates business value when it runs—NOT when we write it.
  • 49. We need to make better decisions about our code
  • 50. We need to know what our code does when it runs
  • 51. We can’t do this unless we MEASURE it
  • 52. Our mental model of our code is not our code.
  • 53. Example: This code can’t possibly work; it works.
  • 54. Example: This code can’t fail; it fails
  • 55. Example: Do these changes make things faster?
  • 56. We can’t know until we MEASURE it
  • 57. We improve our mental model by measuring what our code DOES
  • 58. A better mental model makes us better at deciding what to do—at generating business value
  • 60. Understanding Your Application Instrument your application (metrics) Understand how it's being used Understand the pathways that are taken (counters) Understand how much (disk/memory/etc) you have left (gauges)
  • 63. Go != other languages Work with concurrency primitives Explicit messages Message pipelines ("actors") Simple logic, simple code
  • 64. Thank you 3 Mar 2015 Jonathan Oliver @jonathan_oliver(http://twitter.com/jonathan_oliver) http://jonathanoliver.com(http://jonathanoliver.com) http://github.com/joliver(http://github.com/joliver) http://keybase.com/joliver(http://keybase.com/joliver) Distributed Podcast Chief SmartyPants, SmartyStreets