| 99 | | * we actually appear to only have one instance of this pattern in Tahoe at time of writing, in {{{allmydata.util.dictutil}}}. It has the disadvantage of cluttering up the logic with calls to {{{_assert_invariants}}}, and should probably be used sparingly. -- DavidSarah |
| | 99 | * we actually appear to only have one instance of this pattern in Tahoe at time of writing, in {{{allmydata.util.dictutil}}}. It has the disadvantage of cluttering up the logic with calls to {{{_assert_invariants}}}, and should probably be used sparingly. -- David-Sarah |
| | 100 | |
| | 101 | ==== assertion policy ==== |
| | 102 | |
| | 103 | One axis of interest is how time-consuming the checks are. Many precondition |
| | 104 | checks can cause typical runtime to explode to O(n^2^) or O(n^3^), for example |
| | 105 | {{{SortedList.__contains__}}} called {{{_assert_invariants}}} which took |
| | 106 | O(n log n) each time, when {{{__contains__}}} ought to be O(log n). A caller who |
| | 107 | was expecting {{{if b in list}}} to take O(log n) could easily wind up turning |
| | 108 | their O(n log n) routine into O(n^2^) or worse. |
| | 109 | |
| | 110 | Another axis is "who could cause it to fail": some checks are looking only at |
| | 111 | internal state. For example, if {{{SortedList._assert_invariants}}} fails, it |
| | 112 | indicates a problem in some {{{SortedList}}} method. Other checks are |
| | 113 | enforcing the external API, like those which do typechecks on input |
| | 114 | arguments. Even after the {{{SortedList}}} developer has gained confidence in |
| | 115 | the code and decides that internal checks are no longer necessary, it may be |
| | 116 | useful to retain the external checks to isolate usage problems that exist in |
| | 117 | callers. |
| | 118 | |
| | 119 | * The general rule is that nodes must be functional for light traffic even |
| | 120 | when the assertions are turned on. When assertions are turned off (-O), |
| | 121 | nodes must be functional for heavy traffic. |
| | 122 | |
| | 123 | * Time-consuming internal checks: once the code is working properly, |
| | 124 | consider removing them, but they may be left in place as long as they |
| | 125 | use {{{assert}}} (the form which gets turned off when -O is used). |
| | 126 | |
| | 127 | * Cheap internal checks: once the code is working properly, consider |
| | 128 | removing them, but it is less of a concern than the time-consuming ones. |
| | 129 | If they really are cheap, use {{{_assert}}} (the unconditional form |
| | 130 | that gets used even with -O). |
| | 131 | |
| | 132 | * Time-consuming external checks: maybe leave them in place, but always |
| | 133 | use {{{assert}}} so they will not be used with -O. |
| | 134 | |
| | 135 | * Cheap external checks: leave them in place, using the unconditional |
| | 136 | {{{_assert}}} |
| | 137 | |
| | 138 | * Production grids could run with -O (in practice, the allmydata.com production grid runs without -O, because there are no expensive checks in the current codebase). |
| | 139 | |
| | 140 | * Testing grids might run without -O in order to detect more bugs. |
| | 141 | |
| | 142 | * Local developer tests will probably not use -O, and developers should be |
| | 143 | prepared to experience the same CPU load problems if they subject their |
| | 144 | nodes to real traffic levels. Developers can use -O to turn off everyone |
| | 145 | else's checks, use {{{_assert}}} on their own code to enable their own |
| | 146 | assertions, and then subject their nodes to heavy traffic, as long as they |
| | 147 | are sure to change their checks to use {{{assert}}} (or remove them |
| | 148 | altogether) before committing. |
| | 149 | |
| 137 | | ==== assertion policy ==== |
| 138 | | |
| 139 | | One axis of interest is how time-consuming the checks are. Many precondition |
| 140 | | checks can cause typical runtime to explode to O(n^2^) or O(n^3^), for example |
| 141 | | {{{SortedList.__contains__}}} called {{{_assert_invariants}}} which took |
| 142 | | O(n log n) each time, when {{{__contains__}}} ought to be O(log n). A caller who |
| 143 | | was expecting {{{if b in list}}} to take O(log n) could easily wind up turning |
| 144 | | their O(n log n) routine into O(n^2^) or worse. |
| 145 | | |
| 146 | | Another axis is "who could cause it to fail": some checks are looking only at |
| 147 | | internal state. For example, if {{{SortedList._assert_invariants}}} fails, it |
| 148 | | indicates a problem in some {{{SortedList}}} method. Other checks are |
| 149 | | enforcing the external API, like those which do typechecks on input |
| 150 | | arguments. Even after the {{{SortedList}}} developer has gained confidence in |
| 151 | | the code and decides that internal checks are no longer necessary, it may be |
| 152 | | useful to retain the external checks to isolate usage problems that exist in |
| 153 | | callers. |
| 154 | | |
| 155 | | * The general rule is that nodes must be functional for light traffic even |
| 156 | | when the assertions are turned on. When assertions are turned off (-O), |
| 157 | | nodes must be functional for heavy traffic. |
| 158 | | |
| 159 | | * Time-consuming internal checks: once the code is working properly, |
| 160 | | consider removing them, but they may be left in place as long as they |
| 161 | | use {{{assert}}} (the form which gets turned off when -O is used). |
| 162 | | |
| 163 | | * Cheap internal checks: once the code is working properly, consider |
| 164 | | removing them, but it is less of a concern than the time-consuming ones. |
| 165 | | If they really are cheap, use {{{_assert}}} (the unconditional form |
| 166 | | that gets used even with -O). |
| 167 | | |
| 168 | | * Time-consuming external checks: maybe leave them in place, but always |
| 169 | | use {{{assert}}} so they will not be used with -O. |
| 170 | | |
| 171 | | * Cheap external checks: leave them in place, using the unconditional |
| 172 | | {{{_assert}}} |
| 173 | | |
| 174 | | * Production grids could run with -O (in practice, the allmydata.com production grid runs without -O, because there are no expensive checks in the current codebase). |
| 175 | | |
| 176 | | * Testing grids might run without -O in order to detect more bugs. |
| 177 | | |
| 178 | | * Local developer tests will probably not use -O, and developers should be |
| 179 | | prepared to experience the same CPU load problems if they subject their |
| 180 | | nodes to real traffic levels. Developers can use -O to turn off everyone |
| 181 | | else's checks, use {{{_assert}}} on their own code to enable their own |
| 182 | | assertions, and then subject their nodes to heavy traffic, as long as they |
| 183 | | are sure to change their checks to use {{{assert}}} (or remove them |
| 184 | | altogether) before committing. |
| 185 | | |
| 186 | | |