FlatlinerDOA.Rope 1.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet add package FlatlinerDOA.Rope --version 1.1.0                
NuGet\Install-Package FlatlinerDOA.Rope -Version 1.1.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="FlatlinerDOA.Rope" Version="1.1.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add FlatlinerDOA.Rope --version 1.1.0                
#r "nuget: FlatlinerDOA.Rope, 1.1.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install FlatlinerDOA.Rope as a Cake Addin
#addin nuget:?package=FlatlinerDOA.Rope&version=1.1.0

// Install FlatlinerDOA.Rope as a Cake Tool
#tool nuget:?package=FlatlinerDOA.Rope&version=1.1.0                

Rope

Build Status License

NuGet downloads Size

C# implementation of a Rope<T> immutable data structure. See the paper Ropes: an Alternative to Strings: h.-j. boehm, r. atkinson and m. plass

A Rope is an immutable sequence built using a b-tree style data structure that is useful for efficiently applying and storing edits, most commonly used with strings, but any list or sequence can be efficiently edited using the Rope data structure.

Where a b-tree has every node in the tree storing a single entry, a rope contains arrays of elements and only subdivides on the edits. The data structure then decides at edit time whether it is optimal to rebalance the tree using the following heuristic: A rope of depth n is considered balanced if its length is at least Fn+2.

Note: This implementation of Rope<T> has a hard-coded upper-bound depth of 46 added to the heuristic from the paper. As this seemed to be optimal for my workloads, your mileage may vary.

Example Usage


// Converting to a Rope<char> doesn't allocate any strings (simply points to the original memory).
Rope<char> text = "My favourite text".ToRope();

// With Rope<T>, splits don't allocate any new strings either.
IEnumerable<Rope<char>> words = text.Split(' '); 

// Calling ToString() allocates a new string at the time of conversion.
Console.WriteLine(words.First().ToString()); 

// Warning: Concatenating a string to a Rope<char> converts to a string (allocating memory).
string text2 = text + " My second favourite text";

// Better: This makes a new rope out of the other two ropes, no string allocations or copies.
Rope<char> text3 = text + " My second favourite text".ToRope();

// Value-like equivalence.
"test".ToRope() == ("te".ToRope() + "st".ToRope());
"test".ToRope().GetHashCode() == ("te".ToRope() + "st".ToRope()).GetHashCode();

Comparison with StringBuilder

A comparison could be drawn between a Rope and a StringBuilder as they use a very similar technique for efficient edits.

Feature Rope<T> StringBuilder
Efficient edits of strings (avoid double allocations)
Supports items of any type
Immutable edits
Thread safe
Copy free insertion
Copy free splitting
UTF-8 strings (Rope<byte>)
UTF-32 strings (Rope<Rune>)
Structural invariant GetHashCode
Structural invariant Equals

Performance and Memory Allocation Comparison with StringBuilder

Working with a string of length - 32644 characters. - MaxLeafLength = ~32kb, Max Depth = 46

Method Edits Mean Error StdDev Gen0 Gen1 Gen2 Allocated
StringBuilderConstructionOverhead 10 7.809 ns 0.0550 ns 0.0515 ns 0.0062 - - 104 B
RopeConstructionOverhead 10 3.859 ns 0.0901 ns 0.1073 ns 0.0033 - - 56 B
StringBuilderAppend 10 40,534.935 ns 810.3675 ns 2,148.9796 ns 42.9688 31.1890 - 721160 B
RopeAppend 10 317.650 ns 1.3256 ns 1.2399 ns 0.0367 - - 616 B
StringBuilderInsert 10 43,459.897 ns 1,221.2060 ns 3,600.7536 ns 42.9688 27.3438 - 721160 B
RopeInsert 10 781.521 ns 9.3612 ns 8.7565 ns 0.1669 - - 2800 B
StringBuilderSplitConcat 10 28,432.049 ns 416.0166 ns 324.7984 ns 23.4680 11.7188 - 393720 B
RopeSplitConcat 10 493.856 ns 4.8706 ns 4.3176 ns 0.2003 - - 3360 B
StringBuilderConstructionOverhead 100 7.938 ns 0.1647 ns 0.1540 ns 0.0062 - - 104 B
RopeConstructionOverhead 100 3.956 ns 0.0993 ns 0.1220 ns 0.0033 - - 56 B
StringBuilderAppend 100 454,065.647 ns 16,428.4540 ns 48,439.6672 ns 394.5313 382.3242 - 6621560 B
RopeAppend 100 957,533.053 ns 9,832.7415 ns 9,197.5525 ns 7.8125 - - 144816 B
StringBuilderInsert 100 515,805.869 ns 12,467.5560 ns 36,368.4461 ns 394.5313 378.9063 - 6621560 B
RopeInsert 100 50,168.761 ns 136.7082 ns 127.8769 ns 1.6479 - - 28000 B
StringBuilderSplitConcat 100 248,479.532 ns 5,598.8172 ns 16,508.2389 ns 199.7070 99.6094 - 3347160 B
RopeSplitConcat 100 5,015.996 ns 98.0012 ns 143.6490 ns 2.0065 - - 33600 B
StringBuilderConstructionOverhead 1000 8.208 ns 0.1241 ns 0.1100 ns 0.0062 - - 104 B
RopeConstructionOverhead 1000 3.755 ns 0.0921 ns 0.1983 ns 0.0033 - - 56 B
StringBuilderAppend 1000 23,822,775.472 ns 474,466.0536 ns 879,453.2527 ns 5437.5000 5406.2500 1625.0000 65637900 B
RopeAppend 1000 1,475,919,300.000 ns 2,928,700.4503 ns 2,596,216.6654 ns 1000.0000 - - 26428816 B
StringBuilderInsert 1000 24,622,036.938 ns 551,434.5412 ns 1,625,917.1864 ns 5437.5000 5406.2500 1625.0000 65627902 B
RopeInsert 1000 6,350,752.604 ns 92,691.0537 ns 86,703.2692 ns 15.6250 - - 280003 B
StringBuilderSplitConcat 1000 1,990,366.980 ns 56,738.8359 ns 167,295.7379 ns 1962.8906 494.1406 125.0000 32881603 B
RopeSplitConcat 1000 54,579.363 ns 872.4714 ns 773.4232 ns 20.0806 - - 336000 B

Performance and Memory Allocation Comparison with List<T>

Method IterationCount Mean Error StdDev Gen0 Gen1 Gen2 Allocated
ListConstructionOverhead 10 2.570 ns 0.0413 ns 0.0322 ns 0.0019 - - 32 B
RopeConstructionOverhead 10 3.666 ns 0.0952 ns 0.2542 ns 0.0033 - - 56 B
ListAppend 10 666,555.762 ns 4,598.8957 ns 4,076.8012 ns 499.0234 499.0234 499.0234 2036400 B
RopeAppend 10 309.748 ns 0.9859 ns 0.8233 ns 0.0367 - - 616 B
ListInsert 10 729,416.217 ns 9,647.9942 ns 9,024.7398 ns 499.0234 499.0234 499.0234 2036400 B
RopeInsert 10 786.769 ns 7.7350 ns 7.2353 ns 0.1669 - - 2800 B
ListSplitConcat 10 42,153.005 ns 317.5504 ns 297.0369 ns 41.6260 41.6260 41.6260 197134 B
RopeSplitConcat 10 463.818 ns 9.2630 ns 21.8339 ns 0.2007 - - 3360 B
ListConstructionOverhead 100 2.458 ns 0.0712 ns 0.1875 ns 0.0019 - - 32 B
RopeConstructionOverhead 100 4.162 ns 0.1051 ns 0.1291 ns 0.0033 - - 56 B
ListAppend 100 4,776,595.312 ns 93,894.7124 ns 100,466.2903 ns 742.1875 742.1875 742.1875 16748870 B
RopeAppend 100 951,145.150 ns 13,053.6537 ns 12,210.3958 ns 7.8125 - - 144816 B
ListInsert 100 12,654,141.074 ns 249,553.5433 ns 621,474.9219 ns 734.3750 734.3750 734.3750 16748871 B
RopeInsert 100 50,563.186 ns 249.3505 ns 233.2426 ns 1.6479 - - 28000 B
ListSplitConcat 100 131,457.101 ns 718.0832 ns 636.5620 ns 41.5039 41.5039 41.5039 197134 B
RopeSplitConcat 100 4,768.419 ns 75.9586 ns 71.0517 ns 2.0065 - - 33600 B
ListConstructionOverhead 1000 2.662 ns 0.0621 ns 0.0580 ns 0.0019 - - 32 B
RopeConstructionOverhead 1000 3.517 ns 0.0917 ns 0.1894 ns 0.0033 - - 56 B
ListAppend 1000 36,993,804.286 ns 585,521.1558 ns 547,696.8524 ns 3928.5714 3928.5714 3928.5714 134448581 B
RopeAppend 1000 1,758,050,128.571 ns 4,730,207.7541 ns 4,193,205.9665 ns 1000.0000 - - 26428816 B
ListInsert 1000 1,565,477,960.714 ns 31,084,511.1359 ns 44,580,477.0236 ns 3000.0000 3000.0000 3000.0000 134448640 B
RopeInsert 1000 6,730,104.911 ns 19,289.7019 ns 17,099.8183 ns 15.6250 - - 280003 B
ListSplitConcat 1000 1,035,593.815 ns 3,704.3848 ns 3,465.0839 ns 41.0156 41.0156 41.0156 197135 B
RopeSplitConcat 1000 50,270.998 ns 358.9689 ns 318.2166 ns 20.0806 - - 336000 B
Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • net8.0

    • No dependencies.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.4.38 77 11/6/2024
1.4.36 76 11/5/2024
1.3.0 98 7/28/2024
1.2.0 129 4/7/2024
1.1.1 119 4/2/2024
1.1.0 122 4/1/2024
1.0.0 109 3/30/2024