Skip to content
This repository was archived by the owner on Feb 20, 2023. It is now read-only.

Commit 5cc1a42

Browse files
jkosh44mbutrovich
andauthored
Add event loop docs (#1420)
Co-authored-by: Matt Butrovich <[email protected]>
1 parent 7807449 commit 5cc1a42

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

docs/discussion_event_loop.md

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
# Discussion Doc: Event Loop
2+
3+
## Overview
4+
5+
We use an event loop to handle various types of events in the network layer. This is a very common design pattern for
6+
handling asynchronous event. If you'd like to learn more about it some good keywords to search for are: "Event Loop", "
7+
Event Based Programming", "Event Driven Programming".
8+
9+
## I/O Events
10+
11+
- **Connection Requests**: The main thread will check for incoming connections requests and dispatch them a worker
12+
thread.
13+
- **Handling Connections**: The worker threads will listen for incoming queries over the connection, execute them, and
14+
respond back to the client. There is also a timeout event that will close these connections if there's been no
15+
activity for a certain amount of time.
16+
17+
## Signal Events
18+
19+
- **SIGHUP**: a SIGHUP signal will terminate the server process.
20+
21+
## Timeout Events
22+
23+
- **Handling Connections**: Idle connections will be terminated after a certain amount of time. This is tightly coupled
24+
with the I/O event related to handling connections.
25+
26+
## Manual/Async Events
27+
28+
These events are manually triggered by our code.
29+
30+
- **Terminate Conection**: When connections are terminated a manual event is triggered to close the connection and clean
31+
up all associated resources.
32+
33+
## Libevent vs Libev
34+
35+
**Libevent**: https://libevent.org/
36+
37+
**Libev**: http://software.schmorp.de/pkg/libev.html
38+
39+
Currently we use Libevent as our Event Loop implementation. We have also looked into using Libev and may transition to
40+
Libev in the future. Below is a comparison between the two libraries.
41+
42+
### Language
43+
44+
Libevent is implemented in C. Libev is implemented in C, but has wrapper C++ classes and APIs.
45+
46+
### Usage
47+
48+
Libevent is more "one size fits all" compared to libev. There is a single event type that can watch for any kind of
49+
event. There is also a single event loop type that you can start and stop on a per thread basis. Libev on the other hand
50+
has a different event type for every kind of event. So if you want a single event to watch for two things (like an I/O
51+
event and a timer event) at the same time, then you'll have to create your own custom composite event. Additionally
52+
Libev has two different event loop types. One "default" event loop, which there can only ever be one of, and another
53+
"non-default" event loop, which there can be any number of. In practice this isn't such a huge deal, for example in
54+
NoisePage the connection dispatcher thread would be the default event loop while all the connection handling threads
55+
would be non-default event loops.
56+
57+
This makes libevent easier to use than libev, however it ends up using more memory and according the designer of libev
58+
it makes libevent
59+
slower. [This Stack Overflow post](https://stackoverflow.com/questions/9433864/whats-the-difference-between-libev-and-libevent)
60+
was answered by the creator of libev and describes the differences in design philosophy.
61+
62+
### Performance
63+
64+
Running the tpcc and noop oltpbenchmarks against the current master of NoisePage and an implementation that switches
65+
from libevent to libev for 60 seconds, we get the following results (Note: each benchmark was run twice):
66+
67+
| Libev vs Libevent | Benchmark | Mean Latency (milliseconds) | Throughput (requests/second)
68+
| --- | --- | --- | --- |
69+
| Libev | NoOp | 50.1565409803912 | 3398.930926973485 |
70+
| Libev | NoOp | 50.15175110158765 | 3173.42297782733 |
71+
| Libevent | NoOp | 50.14538746950166 | 3231.0416656357247 |
72+
| Libevent | NoOp | 50.294910261202624 | 3254.812815029675 |
73+
| Libev | TPCC | 1.325 | 753.367 |
74+
| Libev | TPCC | 1.396 | 714.883 |
75+
| Libevent | TPCC | 1.295 | 770.867 |
76+
| Libevent | TPCC | 1.344 | 743.033 |
77+
78+
These were run on dev8.db.pdl.local.cmu.edu. There doesn't seem to be a clear winner between the two from these results.
79+
80+
Libev has it done it's own benchmarking comparing itself against libevent that can be found
81+
[here](http://libev.schmorp.de/bench.html). According to these result Libev only starts being noticeably faster when
82+
there are 10s of thousands of watched file descriptors, and the difference is measure in microseconds and nanoseconds.
83+
So it makes sense that we didn't notice a difference in the OLTP Benchmarks which is measured in milliseconds and don't
84+
have enough file descriptors.
85+
86+
### NoisePage POC Implementation
87+
[Joe Koshakow's Libev Implementation](https://github.com/jkosh44/noisepage/tree/libev-666)

0 commit comments

Comments
 (0)