Development of an internal social media platform with personalised dashboards for students
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Development.txt 17KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. =====================
  2. Developer Information
  3. =====================
  4. This document provides information for developers who maintain or extend
  5. `BTrees`.
  6. Macros
  7. ======
  8. `BTrees` are defined using a "template", roughly akin to a C++ template. To
  9. create a new family of `BTrees`, create a source file that defines macros used
  10. to handle differences in key and value types:
  11. Configuration Macros
  12. --------------------
  13. ``MASTER_ID``
  14. A string to hold an RCS/CVS Id key to be included in compiled binaries.
  15. ``MOD_NAME_PREFIX``
  16. A string (like "IO" or "OO") that provides the prefix used for the module.
  17. This gets used to generate type names and the internal module name string.
  18. ``DEFAULT_MAX_BUCKET_SIZE``
  19. An int giving the maximum bucket size (number of key/value pairs). When a
  20. bucket gets larger than this due to an insertion *into a BTREE*, it
  21. splits. Inserting into a bucket directly doesn't split, and functions
  22. that produce a bucket output (e.g., ``union()``) also have no bound on how
  23. large a bucket may get. Someday this will be tunable on `BTree`.
  24. instances.
  25. ``DEFAULT_MAX_BTREE_SIZE``
  26. An ``int`` giving the maximum size (number of children) of an internal
  27. btree node. Someday this will be tunable on ``BTree`` instances.
  28. Macros for Keys
  29. ---------------
  30. ``KEY_TYPE``
  31. The C type declaration for keys (e.g., ``int`` or ``PyObject*``).
  32. ``KEY_TYPE_IS_PYOBJECT``
  33. Define if ``KEY_TYPE`` is a ``PyObject*`, else ``undef``.
  34. ``KEY_CHECK(K)``
  35. Tests whether the ``PyObject* K`` can be converted to the (``C``) key type
  36. (``KEY_TYPE``). The macro should return a boolean (zero for false,
  37. non-zero for true). When it returns false, its caller should probably set
  38. a ``TypeError`` exception.
  39. ``KEY_CHECK_ON_SET(K)``
  40. Like ``KEY_CHECK``, but only checked during ``__setitem__``.
  41. ``TEST_KEY_SET_OR(V, K, T)``
  42. Like Python's ``cmp()``. Compares K(ey) to T(arget), where ``K``
  43. and ``T`` are ``C`` values of type `KEY_TYPE`. ``V`` is assigned an `int`
  44. value depending on the outcome::
  45. < 0 if K < T
  46. == 0 if K == T
  47. > 0 if K > T
  48. This macro acts like an ``if``, where the following statement is executed
  49. only if a Python exception has been raised because the values could not be
  50. compared.
  51. ``DECREF_KEY(K)``
  52. ``K`` is a value of ``KEY_TYPE``. If ``KEY_TYPE`` is a flavor of
  53. ``PyObject*``, write this to do ``Py_DECREF(K)``. Else (e.g.,
  54. ``KEY_TYPE`` is ``int``) make it a nop.
  55. ``INCREF_KEY(K)``
  56. ``K`` is a value of `KEY_TYPE`. If `KEY_TYPE` is a flavor of
  57. ``PyObject*``, write this to do ``Py_INCREF(K)``. Else (e.g., `KEY_TYPE`
  58. is ``int``) make it a nop.
  59. ``COPY_KEY(K, E)``
  60. Like ``K=E``. Copy a key from ``E`` to ``K``, both of ``KEY_TYPE``. Note
  61. that this doesn't ``decref K`` or ``incref E`` when ``KEY_TYPE`` is a
  62. ``PyObject*``; the caller is responsible for keeping refcounts straight.
  63. ``COPY_KEY_TO_OBJECT(O, K)``
  64. Roughly like ``O=K``. ``O`` is a ``PyObject*``, and the macro must build
  65. a Python object form of ``K``, assign it to ``O``, and ensure that ``O``
  66. owns the reference to its new value. It may do this by creating a new
  67. Python object based on ``K`` (e.g., ``PyInt_FromLong(K)`` when
  68. ``KEY_TYPE`` is ``int``), or simply by doing ``Py_INCREF(K)`` if
  69. ``KEY_TYPE`` is a ``PyObject*``.
  70. ``COPY_KEY_FROM_ARG(TARGET, ARG, STATUS)``
  71. Copy an argument to the target without creating a new reference to
  72. ``ARG``. ``ARG`` is a ``PyObject*``, and ``TARGET`` is of type
  73. ``KEY_TYPE``. If this can't be done (for example, ``KEY_CHECK(ARG)``
  74. returns false), set a Python error and set status to ``0``. If there is
  75. no error, leave status alone.
  76. Macros for Values
  77. -----------------
  78. ``VALUE_TYPE``
  79. The C type declaration for values (e.g., ``int`` or ``PyObject*``).
  80. ``VALUE_TYPE_IS_PYOBJECT``
  81. Define if ``VALUE_TYPE`` is a ``PyObject*``, else ``undef``.
  82. ``TEST_VALUE(X, Y)``
  83. Like Python's ``cmp()``. Compares ``X`` to ``Y``, where ``X`` & ``Y`` are
  84. ``C`` values of type ``VALUE_TYPE``. The macro returns an ``int``, with
  85. value::
  86. < 0 if X < Y
  87. == 0 if X == Y
  88. > 0 if X > Y
  89. Bug: There is no provision for determining whether the comparison attempt
  90. failed (set a Python exception).
  91. ``DECREF_VALUE(K)``
  92. Like ``DECREF_KEY``, except applied to values of ``VALUE_TYPE``.
  93. ``INCREF_VALUE(K)``
  94. Like ``INCREF_KEY``, except applied to values of ``VALUE_TYPE``.
  95. ``COPY_VALUE(K, E)``
  96. Like ``COPY_KEY``, except applied to values of ``VALUE_TYPE``.
  97. ``COPY_VALUE_TO_OBJECT(O, K)``
  98. Like ``COPY_KEY_TO_OBJECT``, except applied to values of ``VALUE_TYPE``.
  99. ``COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS)``
  100. Like ``COPY_KEY_FROM_ARG``, except applied to values of ``VALUE_TYPE``.
  101. ``NORMALIZE_VALUE(V, MIN)``
  102. Normalize the value, ``V``, using the parameter ``MIN``. This is almost
  103. certainly a YAGNI. It is a no-op for most types. For integers, ``V`` is
  104. replaced by ``V/MIN`` only if ``MIN > 0``.
  105. Macros for Set Operations
  106. -------------------------
  107. ``MERGE_DEFAULT``
  108. A value of ``VALUE_TYPE`` specifying the value to associate with set
  109. elements when sets are merged with mappings via weighed union or weighted
  110. intersection.
  111. ``MERGE(O1, w1, O2, w2)``
  112. Performs a weighted merge of two values, ``O1`` and ``O2``, using weights
  113. ``w1`` and ``w2``. The result must be of ``VALUE_TYPE``. Note that
  114. weighted unions and weighted intersections are not enabled if this macro
  115. is left undefined.
  116. ``MERGE_WEIGHT(O, w)``
  117. Computes a weighted value for ``O``. The result must be of
  118. ``VALUE_TYPE``. This is used for "filling out" weighted unions, i.e. to
  119. compute a weighted value for keys that appear in only one of the input
  120. mappings. If left undefined, ``MERGE_WEIGHT`` defaults to::
  121. #define MERGE_WEIGHT(O, w) (O)
  122. ``MULTI_INT_UNION``
  123. The value doesn't matter. If defined, `SetOpTemplate.c` compiles code for
  124. a ``multiunion()`` function (compute a union of many input sets at high
  125. speed). This currently makes sense only for structures with integer keys.
  126. BTree Clues
  127. ===========
  128. More or less random bits of helpful info.
  129. + In papers and textbooks, this flavor of BTree is usually called a B+-Tree,
  130. where "+" is a superscript.
  131. + All keys and all values live in the bucket leaf nodes. Keys in interior
  132. (BTree) nodes merely serve to guide a search efficiently toward the correct
  133. leaf.
  134. + When a key is deleted, it's physically removed from the bucket it's in, but
  135. this doesn't propagate back up the tree: since keys in interior nodes only
  136. serve to guide searches, it's OK-- and saves time --to leave "stale" keys in
  137. interior nodes.
  138. + No attempt is made to rebalance the tree after a deletion, unless a bucket
  139. thereby becomes entirely empty. "Classic BTrees" do rebalance, keeping all
  140. buckets at least half full (provided there are enough keys in the entire
  141. tree to fill half a bucket). The tradeoffs are murky. Pathological cases
  142. in the presence of deletion do exist. Pathologies include trees tending
  143. toward only one key per bucket, and buckets at differing depths (all buckets
  144. are at the same depth in a classic BTree).
  145. + ``DEFAULT_MAX_BUCKET_SIZE`` and ``DEFAULT_MAX_BTREE_SIZE`` are chosen mostly
  146. to "even out" pickle sizes in storage. That's why, e.g., an `IIBTree` has
  147. larger values than an `OOBTree`: pickles store ints more efficiently than
  148. they can store arbitrary Python objects.
  149. + In a non-empty BTree, every bucket node contains at least one key, and every
  150. BTree node contains at least one child and a non-NULL firstbucket pointer.
  151. However, a BTree node may not contain any keys.
  152. + An empty BTree consists solely of a BTree node with ``len==0`` and
  153. ``firstbucket==NULL``.
  154. + Although a BTree can become unbalanced under a mix of inserts and deletes
  155. (meaning both that there's nothing stronger that can be said about buckets
  156. than that they're not empty, and that buckets can appear at different
  157. depths), a BTree node always has children of the same kind: they're all
  158. buckets, or they're all BTree nodes.
  159. The ``BTREE_SEARCH`` Macro
  160. ==========================
  161. For notational ease, consider a fixed BTree node ``x``, and let
  162. ::
  163. K(i) mean x->data.key[i]
  164. C(i) mean all the keys reachable from x->data.child[i]
  165. For each ``i`` in ``0`` to ``x->len-1`` inclusive,
  166. ::
  167. K(i) <= C(i) < K(i+1)
  168. is a BTree node invariant, where we pretend that ``K(0)`` holds a key smaller
  169. than any possible key, and ``K(x->len)`` holds a key larger than any possible
  170. key. (Note that ``K(x->len)`` doesn't actually exist, and ``K(0)`` is never
  171. used although space for it exists in non-empty BTree nodes.)
  172. When searching for a key ``k``, then, the child pointer we want to follow is
  173. the one at index ``i`` such that ``K(i) <= k < K(i+1)``. There can be at most
  174. one such ``i``, since the ``K(i)`` are strictly increasing. And there is at
  175. least one such ``i`` provided the tree isn't empty (so that ``0 < len``). For
  176. the moment, assume the tree isn't empty (we'll get back to that later).
  177. The macro's chief loop invariant is
  178. ::
  179. K(lo) < k < K(hi)
  180. This holds trivially at the start, since ``lo`` is set to ``0``, and ``hi`` to
  181. ``x->len``, and we pretend ``K(0)`` is minus infinity and ``K(len)`` is plus
  182. infinity. Inside the loop, if ``K(i) < k`` we set ``lo`` to ``i``, and if
  183. ``K(i) > k`` we set ``hi`` to ``i``. These obviously preserve the invariant.
  184. If ``K(i) == k``, the loop breaks and sets the result to ``i``, and since
  185. ``K(i) == k`` in that case ``i`` is obviously the correct result.
  186. Other cases depend on how ``i = floor((lo + hi)/2)`` works, exactly. Suppose
  187. ``lo + d = hi`` for some ``d >= 0``. Then ``i = floor((lo + lo + d)/2) =
  188. floor(lo + d/2) = lo + floor(d/2)``. So:
  189. a. ``[d == 0] (lo == i == hi)`` if and only if ``(lo == hi)``.
  190. b. ``[d == 1] (lo == i < hi)`` if and only if ``(lo+1 == hi)``.
  191. c. ``[d > 1] (lo < i < hi)`` if and only if ``(lo+1 < hi)``.
  192. If the node is empty ``(x->len == 0)``, then ``lo==i==hi==0`` at the start,
  193. and the loop exits immediately (the first ``i > lo`` test fails), without
  194. entering the body.
  195. Else ``lo < hi`` at the start, and the invariant ``K(lo) < k < K(hi)`` holds.
  196. If ``lo+1 < hi``, we're in case (c): ``i`` is strictly between ``lo`` and
  197. ``hi``, so the loop body is entered, and regardless of whether the body sets
  198. the new ``lo`` or the new ``hi`` to ``i``, the new ``lo`` is strictly less
  199. than the new ``hi``, and the difference between the new ``lo`` and new ``hi``
  200. is strictly less than the difference between the old ``lo`` and old ``hi``.
  201. So long as the new ``lo + 1`` remains < the new ``hi``, we stay in this case.
  202. We can't stay in this case forever, though: because ``hi-lo`` decreases on
  203. each trip but remains > ``0``, ``lo+1 == hi`` must eventually become true.
  204. (In fact, it becomes true quickly, in about ``log2(x->len)`` trips; the point
  205. is more that ``lo`` doesn't equal ``hi`` when the loop ends, it has to end
  206. with ``lo+1==hi`` and ``i==lo``).
  207. Then we're in case (b): ``i==lo==hi-1`` then, and the loop exits. The
  208. invariant still holds, with ``lo==i`` and ``hi==lo+1==i+1``::
  209. K(i) < k < K(i+1)
  210. so ``i`` is again the correct answer.
  211. Optimization points:
  212. --------------------
  213. + Division by 2 is done via shift rather via "/2". These are signed ints, and
  214. almost all C compilers treat signed int division as truncating, and shifting
  215. is not the same as truncation for signed int division. The compiler has no
  216. way to know these values aren't negative, so has to generate longer-winded
  217. code for "/2". But we know these values aren't negative, and exploit it.
  218. + The order of _cmp comparisons matters. We're in an interior BTree node, and
  219. are looking at only a tiny fraction of all the keys that exist. So finding
  220. the key exactly in this node is unlikely, and checking ``_cmp == 0`` is a
  221. waste of time to the same extent. It doesn't matter whether we check for
  222. ``_cmp < 0`` or ``_cmp > 0`` first, so long as we do both before worrying
  223. about equality.
  224. + At the start of a routine, it's better to run this macro even if ``x->len``
  225. is ``0`` (check for that afterwards). We just called a function and so
  226. probably drained the pipeline. If the first thing we do then is read up
  227. ``self->len`` and check it against ``0``, we just sit there waiting for the
  228. data to get read up, and then another immediate test-and-branch, and for a
  229. very unlikely case (BTree nodes are rarely empty). It's better to get into
  230. the loop right away so the normal case makes progress ASAP.
  231. The ``BUCKET_SEARCH`` Macro
  232. ===========================
  233. This has a different job than ``BTREE_SEARCH``: the key ``0`` slot is
  234. legitimate in a bucket, and we want to find the index at which the key
  235. belongs. If the key is larger than the bucket's largest key, a new slot at
  236. index len is where it belongs, else it belongs at the smallest ``i`` with
  237. ``keys[i]`` >= the key we're looking for. We also need to know whether or not
  238. the key is present (``BTREE_SEARCH`` didn't care; it only wanted to find the
  239. next node to search).
  240. The mechanics of the search are quite similar, though. The primary
  241. loop invariant changes to (say we're searching for key ``k``)::
  242. K(lo-1) < k < K(hi)
  243. where ``K(i)`` means ``keys[i]``, and we pretend ``K(-1)`` is minus infinity
  244. and ``K(len)`` is plus infinity.
  245. If the bucket is empty, ``lo=hi=i=0`` at the start, the loop body is never
  246. entered, and the macro sets ``INDEX`` to 0 and ``ABSENT`` to true. That's why
  247. ``_cmp`` is initialized to 1 (``_cmp`` becomes ``ABSENT``).
  248. Else the bucket is not empty, lo<hi at the start, and the loop body is
  249. entered. The invariant is obviously satisfied then, as ``lo=0`` and
  250. ``hi=len``.
  251. If ``K[i]<k``, ``lo`` is set to ``i+1``, preserving that ``K(lo-1) = K[i] <
  252. k``.
  253. If ``K[i]>k``, ``hi`` is set to ``i``, preserving that ``K[hi] = K[i] > k``.
  254. If the loop exits after either of those, ``_cmp != 0``, so ``ABSENT`` becomes
  255. true.
  256. If ``K[i]=k``, the loop breaks, so that ``INDEX`` becomes ``i``, and
  257. ``ABSENT`` becomes false (``_cmp=0`` in this case).
  258. The same case analysis for ``BTREE_SEARCH`` on ``lo`` and ``hi`` holds here:
  259. a. ``(lo == i == hi)`` if and only if ``(lo == hi)``.
  260. b. ``(lo == i < hi)`` if and only if ``(lo+1 == hi)``.
  261. c. ``(lo < i < hi)`` if and only if ``(lo+1 < hi)``.
  262. So long as ``lo+1 < hi``, we're in case (c), and either break with equality
  263. (in which case the right results are obviously computed) or narrow the range.
  264. If equality doesn't obtain, the range eventually narrows to cases (a) or (b).
  265. To go from (c) to (a), we must have ``lo+2==hi`` at the start, and
  266. ``K[i]=K[lo+1]<k``. Then the new lo gets set to ``i+1 = lo+2 = hi``, and the
  267. loop exits with ``lo=hi=i`` and ``_cmp<0``. This is correct, because we know
  268. that ``k != K(i)`` (loop invariant! we actually know something stronger, that
  269. ``k < K(hi)``; since ``i=hi``, this implies ``k != K(i)``).
  270. Else (c) eventually falls into case (b), ``lo+1==hi`` and ``i==lo``. The
  271. invariant tells us ``K(lo-1) < k < K(hi) = K(lo+1)``, so if the key is present
  272. it must be at ``K(lo)``. ``i==lo`` in this case, so we test ``K(lo)`` against
  273. ``k``. As always, if equality obtains we do the right thing, else case #b
  274. becomes case (a).
  275. When (b) becomes (a), the last comparison was non-equal, so ``_cmp`` is
  276. non-zero, and the loop exits because ``lo==hi==i`` in case (a). The invariant
  277. then tells us ``K(lo-1) < k < K(lo)``, so the key is in fact not present, it's
  278. correct to exit with ``_cmp`` non-zero, and ``i==lo`` is again the index at
  279. which ``k`` belongs.
  280. Optimization points:
  281. --------------------
  282. + As for ``BTREE_SEARCH``, shifting of signed ints is cheaper than division.
  283. + Unlike as for ``BTREE_SEARCH``, there's nothing special about searching an
  284. empty bucket, and the macro computes thoroughly sensible results in that
  285. case.
  286. + The order of ``_cmp`` comparisons differs from ``BTREE_SEARCH``. When
  287. searching a bucket, it's much more likely (than when searching a BTree node)
  288. that the key is present, so testing ``__cmp==0`` isn't a systematic waste of
  289. cycles. At the extreme, if all searches are successful (key present), on
  290. average this saves one comparison per search, against leaving the
  291. determination of ``_cmp==0`` implicit (as ``BTREE_SEARCH`` does). But even
  292. on successful searches, ``__cmp != 0`` is a more popular outcome than
  293. ``__cmp == 0`` across iterations (unless the bucket has only a few keys), so
  294. it's important to check one of the inequality cases first. It turns out
  295. it's better on average to check ``K(i) < key`` (than to check ``K(i) >
  296. key``), because when it pays it narrows the range more (we get a little
  297. boost from setting ``lo=i+1`` in this case; the other case sets ``hi=i``,
  298. which isn't as much of a narrowing).