Skip to content

Commit 3a43516

Browse files
committed
Restore 80-columns layout for paragraphs with citations
1 parent d45fd47 commit 3a43516

File tree

1 file changed

+71
-66
lines changed

1 file changed

+71
-66
lines changed

doc/final-report/final-report.md

Lines changed: 71 additions & 66 deletions
Original file line numberDiff line numberDiff line change
@@ -140,22 +140,23 @@ meets all its performance requirements, including stretch targets.
140140

141141
[^2]: And previously on behalf of Input Output Global, Inc. (IOG).
142142

143-
The backend is implemented as a Haskell library called `lsm-tree`[@lsm-tree], which
144-
provides efficient on-disk key–value storage using log-structured merge-trees,
145-
or LSM-trees for short. An LSM-tree is a data structure for key–value mappings
146-
that is optimized for large tables with a high insertion rate, such as the
147-
UTxO set and other stake-related data. The library has a number of custom
148-
features that are primarily tailored towards use cases of the consensus layer,
149-
but the library should be useful for the broader Haskell community as well.
143+
The backend is implemented as a Haskell library called `lsm-tree`[@lsm-tree],
144+
which provides efficient on-disk key–value storage using log-structured
145+
merge-trees, or LSM-trees for short. An LSM-tree is a data structure for
146+
key–value mappings that is optimized for large tables with a high insertion
147+
rate, such as the UTxO set and other stake-related data. The library has a
148+
number of custom features that are primarily tailored towards use cases of the
149+
consensus layer, but the library should be useful for the broader Haskell
150+
community as well.
150151

151152
Currently, a UTxO-HD `cardano-node` already exists, but it is an MVP that uses
152153
off-the-shelf database software (LMDB) to store a part of the ledger state on
153-
disk[@utxo-db-api]. Though the LMDB-based solution is suitable for the current state of the
154-
Cardano blockchain, it is not suitable to achieve Cardano’s long-term business
155-
requirements[@utxo-db, Section 3], such as high throughput with limited system resources. The goal of
156-
`lsm-tree` is to pave the way for achieving said business requirements,
157-
providing the necessary foundation on which technologies like Ouroboros Leios
158-
can build.
154+
disk[@utxo-db-api]. Though the LMDB-based solution is suitable for the current
155+
state of the Cardano blockchain, it is not suitable to achieve Cardano’s
156+
long-term business requirements[@utxo-db, Section 3], such as high throughput
157+
with limited system resources. The goal of `lsm-tree` is to pave the way for
158+
achieving said business requirements, providing the necessary foundation on
159+
which technologies like Ouroboros Leios can build.
159160

160161
Prior to development, an analysis was conducted, leading to a comprehensive
161162
requirements document[@utxo-db-lsm] outlining the functional and non-functional
@@ -179,24 +180,24 @@ It should be noted that the requirements of the `lsm-tree` component were
179180
specified in isolation from the consensus layer and `cardano-node`, but these
180181
requirements were of course chosen with the larger system in mind. This report
181182
only reviews the development of `lsm-tree` as a standalone component, while
182-
integration notes are provided in an accompanying document[@integration-notes]. Integration of
183-
`lsm-tree` with the consensus layer will happen as a separate phase of the
184-
UTxO-HD project.
183+
integration notes are provided in an accompanying document[@integration-notes].
184+
Integration of `lsm-tree` with the consensus layer will happen as a separate
185+
phase of the UTxO-HD project.
185186

186187
Readers are advised to familiarise themselves with the API of the library by
187188
reading through the Haddock documentation of the public API. A version of the
188189
Haddock documentation that tracks the `main` branch of the repository is hosted
189-
using GitHub Pages[@lsm-tree-api-docs]. There are two modules that make up the public API: the
190-
`Database.LSMTree` module contains the full-featured public API, whereas the
191-
`Database.LSMTree.Simple` module offers a simplified version that is aimed at
192-
new users and use cases that do not require advanced features. Additional
193-
documentation can be found in the package description[@lsm-tree-package-desc]. This and the simple
194-
module should be good places to start at before moving on to the full-featured
195-
module.
190+
using GitHub Pages[@lsm-tree-api-docs]. There are two modules that make up the
191+
public API: the `Database.LSMTree` module contains the full-featured public API,
192+
whereas the `Database.LSMTree.Simple` module offers a simplified version that is
193+
aimed at new users and use cases that do not require advanced features.
194+
Additional documentation can be found in the package
195+
description[@lsm-tree-package-desc]. This and the simple module should be good
196+
places to start at before moving on to the full-featured module.
196197

197198
The version of the library that is used as the basis for this report is tagged
198-
`alpha` in the `lsm-tree` Git repository [@lsm-tree]. It can be checked out using the
199-
following commands:
199+
`alpha` in the `lsm-tree` Git repository [@lsm-tree]. It can be checked out
200+
using the following commands:
200201

201202
```sh
202203
git clone [email protected]:IntersectMBO/lsm-tree.git
@@ -218,7 +219,8 @@ testing. Among the prototyping and design artefacts are the following:
218219

219220
* A prototype for the incremental merge algorithm [@lsm-tree-prototype]
220221
* A library for high SSD throughput using asynchronous I/O [@blockio-uring]
221-
* Specifications of the formats of on-disk files and directories [@lsm-tree-format-docs]
222+
* Specifications of the formats of on-disk files and directories
223+
[@lsm-tree-format-docs]
222224

223225
In the spirit of test-driven development, we created a reference implementation
224226
for the library, modelling each of the basic and advanced features that the
@@ -275,9 +277,9 @@ for each completed feature.
275277

276278
In the final stages, we reviewed and improved the public API, tests, benchmarks,
277279
documentation and library packaging. We constructed the final deliverables, such
278-
as this report and additional integration notes[@integration-notes], which should guide the
279-
integration of `lsm-tree` with the consensus layer. In April 2025, we reached
280-
the final milestone.
280+
as this report and additional integration notes[@integration-notes], which
281+
should guide the integration of `lsm-tree` with the consensus layer. In
282+
April 2025, we reached the final milestone.
281283

282284
# Functional requirements
283285

@@ -329,8 +331,8 @@ The tests are written in three styles:
329331
> interface used by the existing consensus layer for its on-disk backends.
330332
331333
For the analysis of this functional requirement, we use a fixed version of the
332-
`ouroboros-consensus` repository[@ouroboros-consensus]. This version can be checked out using the
333-
following commands:
334+
`ouroboros-consensus` repository[@ouroboros-consensus]. This version can be
335+
checked out using the following commands:
334336

335337
```sh
336338
git clone [email protected]:IntersectMBO/ouroboros-consensus.git
@@ -339,25 +341,27 @@ git checkout 9d41590555954c511d5f81682ccf7bc963659708
339341
```
340342

341343
The consensus interface that has to be implemented using `lsm-tree` is given by
342-
the `LedgerTablesHandle` record type[@ouroboros-consensus-LedgerTablesHandle]. This type provides an abstract view
343-
on the table storage, so that the rest of the consensus layer does not have to
344-
concern itself with the concrete implementation of that storage, be it based on
345-
`lsm-tree` or not; `ouroboros-consensus` can freely pick any particular record
346-
as long as it constitutes a faithful implementation of the storage interface.
347-
This has advantages for initial functional integration because the integration
348-
effort is confined to the implementation of the record. To take full advantage
349-
of all of `lsm-tree`’s features, further integration efforts would be needed
350-
because changes to the interface and the rest of the consensus layer would be
351-
required. However, this is considered out of scope for the current phase of the
352-
UTxO-HD project.
344+
the `LedgerTablesHandle` record type[@ouroboros-consensus-LedgerTablesHandle].
345+
This type provides an abstract view on the table storage, so that the rest of
346+
the consensus layer does not have to concern itself with the concrete
347+
implementation of that storage, be it based on `lsm-tree` or not;
348+
`ouroboros-consensus` can freely pick any particular record as long as it
349+
constitutes a faithful implementation of the storage interface. This has
350+
advantages for initial functional integration because the integration effort is
351+
confined to the implementation of the record. To take full advantage of all of
352+
`lsm-tree`’s features, further integration efforts would be needed because
353+
changes to the interface and the rest of the consensus layer would be required.
354+
However, this is considered out of scope for the current phase of the UTxO-HD
355+
project.
353356

354357
Currently, the consensus layer has one implementation of table storage for the
355-
ledger, which stores all data in main memory[@ouroboros-consensus-InMemory]. This implementation preserves
356-
much of the behaviour of a pre-UTxO-HD node. A closer look at it shows that
357-
there are two pieces of implementation-specific functionality that are not
358-
covered by the `LedgerTablesHandle` record: creating a fresh such record and
359-
producing such a record from an on-disk snapshot. It makes sense that these are
360-
standalone functions, as they produce the records in the first place.
358+
ledger, which stores all data in main memory[@ouroboros-consensus-InMemory].
359+
This implementation preserves much of the behaviour of a pre-UTxO-HD node. A
360+
closer look at it shows that there are two pieces of implementation-specific
361+
functionality that are not covered by the `LedgerTablesHandle` record: creating
362+
a fresh such record and producing such a record from an on-disk snapshot. It
363+
makes sense that these are standalone functions, as they produce the records in
364+
the first place.
361365

362366
All in all, we are left with the following API to implement in the integration
363367
phase:
@@ -399,11 +403,11 @@ anticipated this when we defined the `LedgerTablesHandle` type and consequently
399403
accounted for it by using `Maybe Int` as the return type of `tablesSize`.
400404

401405
The analysis above offers a simplified view on how the `lsm-tree` and consensus
402-
interfaces fit together; so this report is accompanied by integration notes[@integration-notes]
403-
that provide further guidance. These notes include, for example, an explanation
404-
of the need to store a session context in the ledger database. However,
405-
implementation details like these are not considered to be blockers for the
406-
integration efforts, as there are clear paths forward.
406+
interfaces fit together; so this report is accompanied by integration
407+
notes[@integration-notes] that provide further guidance. These notes include,
408+
for example, an explanation of the need to store a session context in the ledger
409+
database. However, implementation details like these are not considered to be
410+
blockers for the integration efforts, as there are clear paths forward.
407411

408412
## Requirement 2
409413

@@ -419,11 +423,11 @@ We generally advise to prefer the bulk operations over the elementary ones. On
419423
Linux systems, lookups in particular will better utilise the storage bandwidth
420424
when the bulk version is used, especially in a concurrent setting. This is due
421425
to the method used to perform batches of I/O, which employs the `blockio-uring`
422-
package[@blockio-uring]: submitting many batches of I/O concurrently will lead to many I/O
423-
requests being in flight at once, so that the SSD bandwidth can be saturated.
424-
This is particularly relevant for the consensus layer, which will have to employ
425-
concurrent batching to meet higher performance targets, for example by using a
426-
pipelining design.
426+
package[@blockio-uring]: submitting many batches of I/O concurrently will lead
427+
to many I/O requests being in flight at once, so that the SSD bandwidth can be
428+
saturated. This is particularly relevant for the consensus layer, which will
429+
have to employ concurrent batching to meet higher performance targets, for
430+
example by using a pipelining design.
427431

428432
It is not part of the requirements but does deserve to be mentioned that there
429433
is specific support for storing blobs (binary large objects). Morally, blobs are
@@ -439,11 +443,12 @@ about as expensive as if the blobs’ contents were included in the values.
439443
A naive implementation of updates entails latency spikes due to table merging,
440444
but the `lsm-tree` library can avoid such spikes by spreading out I/O over time,
441445
using an incremental merge algorithm: the algorithm that we prototyped at the
442-
start of the `lsm-tree` project[@lsm-tree-prototype]. Avoiding latency spikes is essential for
443-
`cardano-node` because `cardano-node` is a real-time system, which has to
444-
respond to input promptly. The use of the incremental merge algorithm does not
445-
improve the time complexity of updates as such, but it turns the *amortised*
446-
time complexity of the naive solution into a *worst-case* time complexity.
446+
start of the `lsm-tree` project[@lsm-tree-prototype]. Avoiding latency spikes is
447+
essential for `cardano-node` because `cardano-node` is a real-time system, which
448+
has to respond to input promptly. The use of the incremental merge algorithm
449+
does not improve the time complexity of updates as such, but it turns the
450+
*amortised* time complexity of the naive solution into a *worst-case* time
451+
complexity.
447452

448453
## Requirement 3
449454

@@ -648,9 +653,9 @@ simulation provided by the `fs-sim` package.
648653
We made some smaller changes to `fs-api` and `fs-sim` to facilitate the
649654
development of `lsm-tree`. Furthermore, we created an extension to `HasFS`
650655
called `HasBlockIO`. It captures both the submission of batches of I/O, for
651-
example using `blockio-uring`[@blockio-uring], and some functionality unrelated to batching
652-
that is nonetheless useful for `lsm-tree`. The latter could eventually be
653-
included in `fs-api` and `fs-sim`.
656+
example using `blockio-uring`[@blockio-uring], and some functionality unrelated
657+
to batching that is nonetheless useful for `lsm-tree`. The latter could
658+
eventually be included in `fs-api` and `fs-sim`.
654659

655660
In the context of `lsm-tree`, startup or restoration means opening a table from
656661
a table snapshot. In the consensus layer, table snapshots would be part of the

0 commit comments

Comments
 (0)