Improve performance and code quality of our JSON RPC by refactoring UniValue
Roadmap:
-
Integrate UniValue tests into BCHN test framework. -
Split boolean type into true type and false type. -
Use union to store type-dependent data, considerably reducing memory use. -
Combine key-value pairs into a single vector, instead of two separate vectors, improving locality of reference and reducing allocation overhead. Consider using a list instead of a vector for push performance.-
Support streaming JSON serialisation instead of returning string, massively reducing memory use. -
Support creating special numbers which are amounts/integers, reducing memory use and avoiding allocation overhead. -
Support creating special objects whose keys are enum instead of string, massively reducing memory use and avoiding escape overhead. -
Support creating special strings which are hexadecimal, halving memory use and avoiding escape overhead.
In preparation of a possible tagged union:
-
Offer strongly-typed UniValue::Array
separately from the weakly-typedUniValue
main class. -
Offer strongly-typed UniValue::Object
separately from the weakly-typedUniValue
main class. -
Offer strongly-typed UniValue::Number
separately from the weakly-typedUniValue
main class.
With respect to streaming JSON serialisation, we are currently in situation 1 of the suggestions below:
Serialise into string with lots of intermediate strings, then copy string into HTTP response buffer.-
Compute string length in advance, allocate string once before writing,then copy string into HTTP response buffer. -
Same as 2, but serialise characters directly into the HTTP response buffer. evbuffer_add bypass suggested here. -
Additionally, respond in chunks, instead of holding the entire HTTP response in memory simultaneously. Bitcoin SV appears to have (not open source) code to do something like this. But apparently it is difficult to do chunking right and you might end up simply concatenating all chunks and sending everything at once.
Appending key-value pairs to objects:
-
Offer code path without quadratic duplicate key check. -
Offer this code path via new method name so that old code path can be removed in the future. -
Upgrade all call sites and remove code path with duplicate key check entirely.
Modern C++:
-
Use constexpr
-
Use noexcept
-
Use [[nodiscard]]
-
Support range-based for-loops over arrays and objects -
Replace setter methods with operator=
overloads -
Replace test methods with operator==
andoperator!=
overloads -
Adopt std::string_view
-
Adopt std::to_chars()
-
Create a NullUniValue_t
type to allow convenient and efficient use ofNullUniValue
via specialised overloads
Edited by BigBlockIfTrue