You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: doc/modules/ROOT/pages/sans_io_philosophy.adoc
+56-13
Original file line number
Diff line number
Diff line change
@@ -13,29 +13,50 @@
13
13
14
14
== What is Sans-I/O?
15
15
16
-
Sans-I/O is a design philosophy for developing network protocol libraries in which the library itself does not perform any I/O operations or asynchronous flow control. Instead, it provides interfaces for consuming and producing buffers of data and events. This simple change not only facilitates the development of such libraries but also enables their use with any asynchronous or synchronous I/O runtime.
16
+
Sans-I/O is a design philosophy for developing network protocol libraries in
17
+
which the library itself does not perform any I/O operations or asynchronous
18
+
flow control. Instead, it provides interfaces for consuming and producing
19
+
buffers of data and events. This simple change not only facilitates the
20
+
evelopment of such libraries but also enables their use with any asynchronous
21
+
or synchronous I/O runtime.
17
22
18
23
19
24
== Why a Sans-I/O approach?
20
25
21
26
22
27
=== Reusability
23
28
24
-
Developing high-quality network protocol libraries is a challenging and time-consuming task. Furthermore, most of the time, such libraries need extensive usage and feedback from users to refine their optimal API. Consequently, we aim to facilitate the reusability of such valuable code. A sans-I/O design approach eliminates all I/O-related code from the protocol stack. This enables the reuse of protocol stack code for developing I/O-based network libraries on top of different I/O runtimes.
29
+
Developing high-quality network protocol libraries is a challenging and
30
+
time-consuming task. Furthermore, most of the time, such libraries need
31
+
extensive usage and feedback from users to refine their optimal API.
32
+
Consequently, we aim to facilitate the reusability of such valuable code. A
33
+
sans-I/O design approach eliminates all I/O-related code from the protocol
34
+
stack. This enables the reuse of protocol stack code for developing I/O-based
35
+
network libraries on top of different I/O runtimes.
25
36
26
37
27
38
=== Testability
28
39
29
-
Using a sans-I/O approach improves the testability of the library by enabling the creation of simpler, more reliable, and faster tests, as they no longer need to be written against I/O interfaces.
40
+
Using a sans-I/O approach improves the testability of the library by enabling
41
+
the creation of simpler, more reliable, and faster tests, as they no longer
42
+
need to be written against I/O interfaces.
30
43
31
-
The following outlines how a sans-I/O approach can enhance the testability of a library implementation:
44
+
The following outlines how a sans-I/O approach can enhance the testability of
45
+
a library implementation:
32
46
33
47
34
48
==== Lower cognitive complexity
35
49
36
-
One of the limiting factors in writing high-quality tests is the cognitive complexity of the tests themselves. For example, if we have to deal with I/O operations in the test, we have to set up connections, timers, and an I/O scheduler, which increases the cognitive load for both the writer and reader of the tests. Using a sans-I/O design approach eliminates all of these unnecessary setups and teardowns from the tests, making it possible to write simpler and cleaner tests.
50
+
One of the limiting factors in writing high-quality tests is the cognitive
51
+
complexity of the tests themselves. For example, if we have to deal with I/O
52
+
operations in the test, we have to set up connections, timers, and an I/O
53
+
scheduler, which increases the cognitive load for both the writer and reader of
54
+
the tests. Using a sans-I/O design approach eliminates all of these unnecessary
55
+
setups and teardowns from the tests, making it possible to write simpler and
56
+
cleaner tests.
37
57
38
-
The following example demonstrates the additional setup required in an I/O-coupled design:
58
+
The following example demonstrates the additional setup required in an
Covering all the corner cases in network-facing libraries is limited by how we can actually reproduce them in the tests. We might not be able to reproduce some error conditions or create conditions for interleaving events to cover all the possibilities. A sans-I/O design eliminates the coupling to I/O interfaces and instead provides us with synchronous interfaces that we can use to test all possible combinations of events and data arrivals.
72
+
Covering all the corner cases in network-facing libraries is limited by how we
73
+
can actually reproduce them in the tests. We might not be able to reproduce some
74
+
error conditions or create conditions for interleaving events to cover all the
75
+
possibilities. A sans-I/O design eliminates the coupling to I/O interfaces and
76
+
instead provides us with synchronous interfaces that we can use to test all
77
+
possible combinations of events and data arrivals.
52
78
53
79
54
80
==== Faster execution times
55
81
56
-
Most of the time, I/O operations and system calls are the slowest part of a test. A sans-I/O design allows for writing tests with virtually no I/O operations or system calls at all. Consequently, we can execute thousands of tests within seconds, instead of minutes or even hours if we have to deal with real socket or pipe operations.
82
+
Most of the time, I/O operations and system calls are the slowest part of a
83
+
test. A sans-I/O design allows for writing tests with virtually no I/O
84
+
operations or system calls at all. Consequently, we can execute thousands of
85
+
tests within seconds, instead of minutes or even hours if we have to deal with
86
+
real socket or pipe operations.
57
87
58
-
Moreover, testing time-sensitive logic with an I/O-coupled library requires realistic delays to cover all possibilities, which can quickly add up to a significant number (even if they are in orders of milliseconds individually). By using a sans-I/O approach, we can cover all of these combinations using synchronous interfaces, which require no delay at all.
88
+
Moreover, testing time-sensitive logic with an I/O-coupled library requires
89
+
realistic delays to cover all possibilities, which can quickly add up to a
90
+
significant number (even if they are in orders of milliseconds individually).
91
+
By using a sans-I/O approach, we can cover all of these combinations using
92
+
synchronous interfaces, which require no delay at all.
59
93
60
-
The following example demonstrates the necessity of adding delays to tests for I/O-coupled functionalities:
94
+
The following example demonstrates the necessity of adding delays to tests for
95
+
I/O-coupled functionalities:
61
96
62
97
[source,cpp]
63
98
----
@@ -70,9 +105,17 @@ BEAST_EXPECT(got_timeout);
70
105
71
106
==== Deterministic test results
72
107
73
-
Relying on I/O operations and system calls can lead to flaky tests since we depend on resources and conditions controlled by the operating system. This issue becomes more pronounced when incorporating time-sensitive test cases, as they may fail due to the operating system scheduling other processes between tests or delaying network operations. A sans-I/O designed library can be thoroughly tested without any I/O operation, relying solely on simple function calls. In fact, a sans-I/O implementation resembles a giant state machine, allowing for deterministic and self-contained testing.
74
-
75
-
The following example demonstrates the ease of testing within a sans-I/O design, without any reliance on I/O operations or system calls:
108
+
Relying on I/O operations and system calls can lead to flaky tests since we
109
+
depend on resources and conditions controlled by the operating system. This
110
+
issue becomes more pronounced when incorporating time-sensitive test cases, as
111
+
they may fail due to the operating system scheduling other processes between
112
+
tests or delaying network operations. A sans-I/O designed library can be
113
+
thoroughly tested without any I/O operation, relying solely on simple function
114
+
calls. In fact, a sans-I/O implementation resembles a giant state machine,
115
+
allowing for deterministic and self-contained testing.
116
+
117
+
The following example demonstrates the ease of testing within a sans-I/O
118
+
design, without any reliance on I/O operations or system calls:
0 commit comments