Files
talks/concurrency/slides.org
T

462 lines
11 KiB
Org Mode
Raw Normal View History

2020-05-31 21:09:26 +00:00
* 1. Concurrency
- David Wen Riccardi-Zhu
- Senior Software Engineer @ Good Uncle
- dwrz@dwrz.net
Slides and code: https://github.com/dwrz/talks/concurrency.
* 2. Why
You'll likely encounter it at work:
- Client requests to your backend
- Database and API requests made by your backend
- Frontend rendering
* 3. Why
Performance Benefits
- Typically outweigh gains from optimized data structures and algorithms.
2020-06-05 14:57:30 +00:00
- I/O versus CPU bound applications.
2020-05-31 21:09:26 +00:00
- Hardware limitations.
- Rate of single core performance improvement is slowing.
- More cores.
* 4. Why
Expressive
* 5. Why
Difficult to do correctly.
Easy to do incorrectly.
* 6. Goals
- Give you a rough sense of what concurrency is.
- Provide context to help you understand how it's made possible.
- Practical demonstration, to expose some of the trade-offs.
* 7. Three Parts
1. Fundamentals
2. Application
3. Infrastructure
* 8. Definition
/Concurrency/
1. A running together in place or time.
2. Simultaneous occurrence.
OK starting point, but:
Time, and simultaneity, is /complicated/.
A second is a duration, not an instant.
Two things can happen in the same second and not be simultaneous.
2020-06-05 16:13:03 +00:00
With computers, this nuance matters.
2020-05-31 21:09:26 +00:00
* 9. Time
|----------------------+----------------+----------------|
| System Event | Actual Latency | Scaled Latency |
|----------------------+----------------+----------------|
| One CPU cycle | 0.4 ns | 1 s |
| Level 1 cache access | 0.9 ns | 2 s |
| Level 2 cache access | 2.8 ns | 7 s |
| Level 3 cache access | 28 ns | 1 min |
| Main memory access | ~100 ns | 4 min |
| NVMe SSD I/O | ~25 μs | 17 hrs |
| SSD I/O | 50–150 μs | 1.5–4 days |
| Rotational disk I/O | 1–10 ms | 1–9 months |
| Internet: SF to NYC | 65 ms | 5 years |
| Internet: SF to HK | 141 ms | 11 years |
|----------------------+----------------+----------------|
Source: [[https://www.prowesscorp.com/computer-latency-at-a-human-scale/]]
* 10. Example
- Get the current temperature of ten most populous cities in the US.
- First, /sequentially./
- Then, /concurrently/.
[[file:cmd/temperatures/run.sh]]
* 11. Example
[[file:images/concurrent-requests.jpg]]
* 12. Cooking Recipes
- Step-by-step
2020-06-05 16:13:03 +00:00
- Concurrent:
- Handle other tasks while:
- Preheating oven
- Boiling water
- Waiting for timers
- Switching back to a task when it is ready for more work.
2020-05-31 21:09:26 +00:00
* 13. Multitasking
Computers can "simultaneously" work on:
- Different /parts/ of a recipe
- Different /recipes/
* 14. htop
* 15. How?
2020-06-05 14:57:30 +00:00
Combination of:
- Operating System *Scheduler*
- Hardware (/interrupts/)
2020-06-05 16:13:03 +00:00
- Keyboard
- Filesystem
- Network Card
- Timer
2020-05-31 21:09:26 +00:00
2020-06-05 16:13:03 +00:00
* 16. Cooperative Scheduling
2020-05-31 21:09:26 +00:00
[[file:images/cooperative-scheduling.jpg]]
2020-06-05 16:13:03 +00:00
* 17. Preemptive Scheduling
2020-05-31 21:09:26 +00:00
[[file:images/preemptive-scheduling.jpg]]
2020-06-05 16:13:03 +00:00
* 18. Preemptive Scheduling
2020-05-31 21:09:26 +00:00
[[file:images/preemptive-scheduling-tree.jpg]]
2020-06-05 16:13:03 +00:00
* 19. Multi Core
2020-05-31 21:09:26 +00:00
[[file:images/preemptive-scheduling-multi-core.jpg]]
2020-06-05 16:13:03 +00:00
* 20. Concurrency versus Parallelism
2020-05-31 21:09:26 +00:00
2020-06-05 14:57:30 +00:00
- Parallelism :: performing computations at the same time.
2020-05-31 21:09:26 +00:00
- Multiple cores.
2020-06-05 16:13:03 +00:00
- Multiple computers.
2020-05-31 21:09:26 +00:00
- Kind of like having multiple cooks in a kitchen.
2020-06-05 14:32:17 +00:00
- Can do different things at the same time.
- Can do one job faster (peeling a lot of potatoes).
2020-05-31 21:09:26 +00:00
- Concurrency :: performing computations over inter-leaving, non-sequential time periods.
- Single or multi-core.
2020-06-05 16:13:03 +00:00
* 21. Processes and Threads
2020-06-05 14:32:17 +00:00
A little more nuance.
2020-05-31 21:09:26 +00:00
- Different /recipes/
2020-06-05 14:32:17 +00:00
- Different /parts/ of a recipe
2020-05-31 21:09:26 +00:00
2020-06-05 14:32:17 +00:00
- Process :: a program in execution.
2020-06-05 16:13:03 +00:00
- Unique resources (memory, code, files, etc.).
2020-06-05 14:32:17 +00:00
- Start off with one thread.
- Can /fork/.
2020-06-05 14:57:30 +00:00
- Communicate via inter-process communication (IPC).
2020-05-31 21:09:26 +00:00
2020-06-05 14:32:17 +00:00
- Thread :: sequence of instructions that can be managed independently by scheduler.
- Share resources ∴ less resource intensive.
- Can communicate via shared resources.
2020-05-31 21:09:26 +00:00
2020-06-05 16:13:03 +00:00
* 22. Processes and Threads
2020-05-31 21:09:26 +00:00
[[file:images/process-vs-thread.jpg]]
Source: https://stackoverflow.com/questions/16354460/forking-vs-threading/16354658
2020-06-05 16:13:03 +00:00
* 23. htop
2020-05-31 21:09:26 +00:00
Press ~H~ to show threads.
2020-06-05 16:13:03 +00:00
* 24. Languages and Runtimes
2020-05-31 21:09:26 +00:00
- ~C~, ~C++~, ~Rust~ allow for fine-grained control of processes and threads.
2020-06-05 14:57:30 +00:00
#+begin_src C :output raw
2020-06-05 14:32:17 +00:00
int main() {
fork();
2020-05-31 21:09:26 +00:00
2020-06-05 14:32:17 +00:00
printf("Hello world!\n");
2020-05-31 21:09:26 +00:00
2020-06-05 14:32:17 +00:00
return 0;
}
#+end_src
2020-05-31 21:09:26 +00:00
2020-06-05 16:13:03 +00:00
* 25. JavaScript
2020-06-05 14:32:17 +00:00
- Single-threaded (for application code).
- Runtimes implement concurrency via an event loop.
2020-05-31 21:09:26 +00:00
[[file:images/nodejs-event-loop.png]]
Source: [[https://medium.com/preezma/node-js-event-loop-architecture-go-deeper-node-core-c96b4cec7aa4]]
2020-06-05 16:13:03 +00:00
* 26. Aside: Event Loop
2020-05-31 21:09:26 +00:00
What is the output of the following? Why?
#+begin_src javascript
console.log('start');
2020-06-05 14:32:17 +00:00
setTimeout(() => console.log('1'), 0);
2020-05-31 21:09:26 +00:00
console.log('middle');
2020-06-05 14:32:17 +00:00
setTimeout(() => console.log('2'), 0);
2020-05-31 21:09:26 +00:00
console.log('end');
#+end_src
2020-06-05 16:13:03 +00:00
* 27. Go
*Runtime scheduler* manages multiple threads.
[[file:images/go-scheduler.png]]
Source: https://freethreads.net/2019/01/23/go-runtime-scheduler-design-internals/
* 28. Quick Review
- Sequential versus Concurrent Steps
- Compare with recipes.
- Concurrency versus Parallelism
- Parallelism: multiple cooks, simultaneously /doing/.
- Concurrency: one or more cooks, /dealing/ with many tasks.
- Operating System Scheduler
- Processes and Threads
- Languages and Runtimes
* 29. Part 2: Using Concurrency
Typical use cases:
- Network I/O between:
- Clients and servers.
- Services and database(s).
- Microservices.
- Service and external APIs.
- User interfaces
- Capturing user input
- Rendering output
- Similar, but independent computations.
- Solving problems that are best expressed with concurrency.
* 30. Go Examples
2020-05-31 21:09:26 +00:00
1. Shared Memory with Mutex (Mutual Exclusion)
- Pitfall: synchronization, debugging.
2020-06-05 16:13:03 +00:00
2. Message Passing (Channels and Goroutines)
- Pitfall: resource usage, complexity.
* 31. Mutex Example
2020-05-31 21:09:26 +00:00
Concurrent updates to a bank account balance.
Code:
[[file:cmd/mutex/main.go]]
Run: [[file:cmd/mutex/run.sh]]
- Without mutex.
2020-06-05 16:13:03 +00:00
* 32. Data Races
2020-05-31 21:09:26 +00:00
[[file:images/data-race.jpg]]
2020-06-05 16:13:03 +00:00
* 33. Mutex
2020-05-31 21:09:26 +00:00
/Mutual Exclusion/
- Purpose: protect a critical section of code.
- Effect: serialization.
2020-06-05 16:13:03 +00:00
Run: [[file:cmd/mutex/run.sh]]
- With mutex.
* 34. Race Detector
How can we be sure?
Race detector can give us /some/ confidence (but no guarantees).
2020-05-31 21:09:26 +00:00
- Without mutex.
- With mutex.
2020-06-05 16:13:03 +00:00
* 35. Tradeoffs: Validating Correctness, Testing, Debugging
2020-05-31 21:09:26 +00:00
- Non-deterministic behavior
- Works fine on one run, fatal bug in another.
- Up to how the scheduler(s) order things at execution time.
- Concealed bugs
2020-06-05 16:13:03 +00:00
* 36. Message Passing
2020-05-31 21:09:26 +00:00
Proverbs:
#+begin_quote
Don't communicate by sharing memory, share memory by communicating.
Channels orchestrate, mutexes serialize.
#+end_quote
2020-06-05 16:13:03 +00:00
* 37. Program Requirements
2020-05-31 21:09:26 +00:00
2020-06-05 14:32:17 +00:00
- Read CSV of zip codes
2020-05-31 21:09:26 +00:00
- 50 in our example
- Full list is ~42,000
- Get temperature with OpenWeatherMap API
- 60 requests per minute
- Need to rate limit our API requests.
- Display running list of top ten temperatures.
2020-06-05 16:13:03 +00:00
* 38. Concurrency Hallmarks
2020-05-31 21:09:26 +00:00
- Repeatedly processing similar data (lines of CSV)
- Network I/O
- UI I/O
2020-06-05 16:13:03 +00:00
* 39. Message Passing Example
2020-05-31 21:09:26 +00:00
Run: [[file:cmd/csp/run.sh]]
2020-06-05 16:13:03 +00:00
* 40. Code Walkthrough
2020-05-31 21:09:26 +00:00
[[file:cmd/csp/main.go]]
2020-06-05 16:13:03 +00:00
* 41. Channels and Goroutines
2020-05-31 21:09:26 +00:00
[[file:images/message-passing-example-diagram.jpg]]
2020-06-05 16:13:03 +00:00
* 42. Channels and Goroutines
2020-05-31 21:09:26 +00:00
[[file:images/go-scheduler.jpg]]
2020-06-05 16:13:03 +00:00
* 43. Scaling
2020-05-31 21:09:26 +00:00
What if:
- We wanted to process the entire list of 42,000 zip codes?
- We had access to the Enterprise tier of the Open Weather Map API (200,000 requests per minute).
Could we just get rid of the limiter?
2020-06-05 16:13:03 +00:00
* 44. Resources
2020-05-31 21:09:26 +00:00
Probably not, because:
- OS limit on open files (~ulimit~)
- Ask me how I know...
- Server load
- Network load
- CPU
- Ranking goroutine becomes a chokepoint.
2020-06-03 03:08:39 +00:00
- Better data structures and algorithms could help here.
2020-05-31 21:09:26 +00:00
- Goroutines are cheap, but not free.
2020-06-05 16:13:03 +00:00
* 45. Possible Solutions
2020-05-31 21:09:26 +00:00
- Use a semaphore to limit concurrency.
- Buffers
2020-06-05 16:13:03 +00:00
* 46. Designing and Managing Concurrency
2020-05-31 21:09:26 +00:00
- Size of input matters.
- Resources
- Pipelines
- Chokepoints
- Backpressure
- Complexity
2020-06-05 16:13:03 +00:00
* 47. Quick Review
2020-05-31 21:09:26 +00:00
Techniques for implementing and managing concurrency:
- Event loop
- Mutexes
- Communication (channels and goroutines)
Concurrency Pitfalls:
- Synchronization
- Resource usage
- Debugging
- Complexity
- Need to think differently about concurrent code.
2020-06-05 16:13:03 +00:00
* 48. Part 3: Infrastructure Concurrency
2020-05-31 21:09:26 +00:00
Concurrent applications running concurrently on distributed computers.
- Client Application
- Backend Application
- Databases
- Host and Network Infrastructure
2020-06-05 16:13:03 +00:00
* 49. Example
2020-05-31 21:09:26 +00:00
[[file:images/infrastructure-data-race.jpg]]
2020-06-05 16:13:03 +00:00
* 50. Review
2020-05-31 21:09:26 +00:00
- What concurrency is
- Sequential versus concurrent
2020-06-05 16:13:03 +00:00
- Comparison with recipes and cooks
2020-05-31 21:09:26 +00:00
- Compared to parallelism
- How it is implemented
- Operating System Scheduler and Interrupts
- Languages and Runtimes
2020-06-05 16:13:03 +00:00
* 51. Review
2020-05-31 21:09:26 +00:00
- When, why, and how to use it
- I/O + UI
- Similar, independent computations
- Expressiveness
- Pitfalls
- Synchronization
2020-06-05 16:13:03 +00:00
- Resource Usage
2020-05-31 21:09:26 +00:00
- Debugging
- Complexity
2020-06-05 16:13:03 +00:00
* 52. Review
2020-05-31 21:09:26 +00:00
- Infrastructure
- Data Race
2020-06-05 16:13:03 +00:00
* 53. Conclusion
2020-05-31 21:09:26 +00:00
- Goals:
- Give you a rough sense of what concurrency is.
- Provide context to help you understand what's going on.
- Practical exposure, to expose some of the trade-offs.
2020-06-03 03:08:39 +00:00
- Awareness and Intuition
2020-05-31 21:09:26 +00:00
- Remember:
- /Premature optimization is the root of all evil/.
- Tradeoffs and economics (resources, costs, developer time).
- Learning is continuous...
2020-06-05 16:13:03 +00:00
* 54. Further Reading
2020-05-31 21:09:26 +00:00
- [[https://slikts.github.io/concurrency-glossary/][Concurrency Glossary]]
- [[https://blog.golang.org/waza-talk][Concurrency is not parallelism]]
- [[https://en.wikipedia.org/wiki/Executable_and_Linkable_Format][Executable and Linkable Format]]
- [[https://www.youtube.com/watch?v=KBZlN0izeiY][GopherCon 2017: Kavya Joshi - Understanding Channels]]
- [[http://web.mit.edu/6.005/www/fa15/][MIT 6.005: Software Construction]]
- Chapters 19, 20, 22, 23
- [[https://www.gopl.io/][The Go Programming Language]]
- [[https://en.wikipedia.org/wiki/Concurrency_(computer_science)][Wikipedia: Concurrency]]
- [[https://en.wikipedia.org/wiki/Concurrency_control][Wikipedia: Concurrency Control]]
- [[https://en.wikipedia.org/wiki/Concurrent_computing][Wikipedia: Concurrent Computing]]
- [[https://en.wikipedia.org/wiki/Deadlock][Wikipedia: Deadlock]]
- [[https://en.wikipedia.org/wiki/Dining_philosophers_problem][Wikipedia: Dining Philosophers Problem]]
- [[https://www.backblaze.com/blog/whats-the-diff-programs-processes-and-threads/][What’s the Diff: Programs, Processes, and Threads]]
- [[https://www.youtube.com/watch?v=8aGhZQkoFbQ&t=13s][What the heck is the event loop anyway? | Philip Roberts]]
- [[https://en.wikipedia.org/wiki/Heisenbug][Wikipedia: Heisenbug]]
- [[https://en.wikipedia.org/wiki/Interrupt][Wikipedia: Interrupt]]
- [[https://en.wikipedia.org/wiki/Libuv][Wikipedia: Libuv]]
- [[https://en.wikipedia.org/wiki/Process_(computing)][Wikipedia: Process]]
- [[https://en.wikipedia.org/wiki/Scheduling_(computing)][Wikipedia: Scheduling]]
- [[https://en.wikipedia.org/wiki/Therac-25][Wikipedia: Therac-25]]
- [[https://en.wikipedia.org/wiki/Thread_(computing)][Wikipedia: Thread]]
- [[https://github.com/danicat/pacgo][pacgo: A Pac Man clone written in Go]]
- [[https://medium.com/preezma/node-js-event-loop-architecture-go-deeper-node-core-c96b4cec7aa4][node.js event loop architecture]]