mirror of
				https://github.com/ergochat/ergo.git
				synced 2025-10-30 21:37:23 +01:00 
			
		
		
		
	
		
			
				
	
	
	
		
			9.9 KiB
		
	
	
	
	
	
	
	
			
		
		
	
	
			9.9 KiB
		
	
	
	
	
	
	
	
btree
An efficient B-tree implementation in Go.
Features
- Support for Generics (Go 1.18+).
- Mapand- Settypes for ordered key-value maps and sets,
- Fast bulk loading for pre-ordered data using the Load()method.
- Copy()method with copy-on-write support.
- Thread-safe operations.
- Path hinting optimization for operations with nearby keys.
Using
To start using this package, install Go and run:
$ go get github.com/tidwall/btreeB-tree types
This package includes the following types of B-trees:
- btree.Map: A fast B-tree for storing ordered key value pairs. Go 1.18+
- btree.Set: Like- Map, but only for storing keys. Go 1.18+
- btree.BTreeG: A feature-rich B-tree for storing data using a custom comparator. Go 1.18+
- btree.BTree: Like- BTreeGbut uses the- interface{}type for data. Backwards compatible. Go 1.16+
btree.Map
// Basic
Set(key, value)    // insert or replace an item
Get(key, value)    // get an existing item
Delete(key)        // delete an item
Len()              // return the number of items in the map
// Iteration
Scan(iter)         // scan items in ascending order
Reverse(iter)      // scan items in descending order
Ascend(key, iter)  // scan items in ascending order that are >= to key
Descend(key, iter) // scan items in descending order that are <= to key.
Iter()             // returns a read-only iterator for for-loops.
// Array-like operations
GetAt(index)       // returns the item at index
DeleteAt(index)    // deletes the item at index
// Bulk-loading
Load(key, value)   // load presorted items into treeExample
package main
import (
    "fmt"
    "github.com/tidwall/btree"
)
func main() {
    // create a map
    var users btree.Map[string, string]
    // add some users
    users.Set("user:4", "Andrea")
    users.Set("user:6", "Andy")
    users.Set("user:2", "Andy")
    users.Set("user:1", "Jane")
    users.Set("user:5", "Janet")
    users.Set("user:3", "Steve")
    // Iterate over the maps and print each user
    users.Scan(func(key, value string) bool {
        fmt.Printf("%s %s\n", key, value)
        return true
    })
    fmt.Printf("\n")
    // Delete a couple
    users.Delete("user:5")
    users.Delete("user:1")
    // print the map again
    users.Scan(func(key, value string) bool {
        fmt.Printf("%s %s\n", key, value)
        return true
    })
    fmt.Printf("\n")
    // Output:
    // user:1 Jane
    // user:2 Andy
    // user:3 Steve
    // user:4 Andrea
    // user:5 Janet
    // user:6 Andy
    //
    // user:2 Andy
    // user:3 Steve
    // user:4 Andrea
    // user:6 Andy
}btree.Set
// Basic
Insert(key)        // insert an item
Contains(key)      // test if item exists
Delete(key)        // delete an item
Len()              // return the number of items in the set
// Iteration
Scan(iter)         // scan items in ascending order
Reverse(iter)      // scan items in descending order
Ascend(key, iter)  // scan items in ascending order that are >= to key
Descend(key, iter) // scan items in descending order that are <= to key.
Iter()             // returns a read-only iterator for for-loops.
// Array-like operations
GetAt(index)       // returns the item at index
DeleteAt(index)    // deletes the item at index
// Bulk-loading
Load(key)          // load presorted item into treeExample
package main
import (
    "fmt"
    "github.com/tidwall/btree"
)
func main() {
    // create a set
    var names btree.Set[string]
    // add some names
    names.Insert("Jane")
    names.Insert("Andrea")
    names.Insert("Steve")
    names.Insert("Andy")
    names.Insert("Janet")
    names.Insert("Andy")
    // Iterate over the maps and print each user
    names.Scan(func(key string) bool {
        fmt.Printf("%s\n", key)
        return true
    })
    fmt.Printf("\n")
    // Delete a couple
    names.Delete("Steve")
    names.Delete("Andy")
    // print the map again
    names.Scan(func(key string) bool {
        fmt.Printf("%s\n", key)
        return true
    })
    fmt.Printf("\n")
    // Output:
    // Andrea
    // Andy
    // Jane
    // Janet
    // Steve
    //
    // Andrea
    // Jane
    // Janet
}btree.BTreeG
// Basic
Set(item)               // insert or replace an item
Get(item)               // get an existing item
Delete(item)            // delete an item
Len()                   // return the number of items in the btree
// Iteration
Scan(iter)              // scan items in ascending order
Reverse(iter)           // scan items in descending order
Ascend(key, iter)       // scan items in ascending order that are >= to key
Descend(key, iter)      // scan items in descending order that are <= to key.
Iter()                  // returns a read-only iterator for for-loops.
// Array-like operations
GetAt(index)            // returns the item at index
DeleteAt(index)         // deletes the item at index
// Bulk-loading
Load(item)              // load presorted items into tree
// Path hinting
SetHint(item, *hint)    // insert or replace an existing item
GetHint(item, *hint)    // get an existing item
DeleteHint(item, *hint) // delete an item
// Copy-on-write
Copy()                  // copy the btreeExample
package main
import (
    "fmt"
    "github.com/tidwall/btree"
)
type Item struct {
    Key, Val string
}
// byKeys is a comparison function that compares item keys and returns true
// when a is less than b.
func byKeys(a, b Item) bool {
    return a.Key < b.Key
}
// byVals is a comparison function that compares item values and returns true
// when a is less than b.
func byVals(a, b Item) bool {
    if a.Val < b.Val {
        return true
    }
    if a.Val > b.Val {
        return false
    }
    // Both vals are equal so we should fall though
    // and let the key comparison take over.
    return byKeys(a, b)
}
func main() {
    // Create a tree for keys and a tree for values.
    // The "keys" tree will be sorted on the Keys field.
    // The "values" tree will be sorted on the Values field.
    keys := btree.NewBTreeG[Item](byKeys)
    vals := btree.NewBTreeG[Item](byVals)
    // Create some items.
    users := []Item{
        Item{Key: "user:1", Val: "Jane"},
        Item{Key: "user:2", Val: "Andy"},
        Item{Key: "user:3", Val: "Steve"},
        Item{Key: "user:4", Val: "Andrea"},
        Item{Key: "user:5", Val: "Janet"},
        Item{Key: "user:6", Val: "Andy"},
    }
    // Insert each user into both trees
    for _, user := range users {
        keys.Set(user)
        vals.Set(user)
    }
    // Iterate over each user in the key tree
    keys.Scan(func(item Item) bool {
        fmt.Printf("%s %s\n", item.Key, item.Val)
        return true
    })
    fmt.Printf("\n")
    // Iterate over each user in the val tree
    vals.Scan(func(item Item) bool {
        fmt.Printf("%s %s\n", item.Key, item.Val)
        return true
    })
    // Output:
    // user:1 Jane
    // user:2 Andy
    // user:3 Steve
    // user:4 Andrea
    // user:5 Janet
    // user:6 Andy
    //
    // user:4 Andrea
    // user:2 Andy
    // user:6 Andy
    // user:1 Jane
    // user:5 Janet
    // user:3 Steve
}btree.BTree
// Basic
Set(item)               // insert or replace an item
Get(item)               // get an existing item
Delete(item)            // delete an item
Len()                   // return the number of items in the btree
// Iteration
Scan(iter)              // scan items in ascending order
Reverse(iter)           // scan items in descending order
Ascend(key, iter)       // scan items in ascending order that are >= to key
Descend(key, iter)      // scan items in descending order that are <= to key.
Iter()                  // returns a read-only iterator for for-loops.
// Array-like operations
GetAt(index)            // returns the item at index
DeleteAt(index)         // deletes the item at index
// Bulk-loading
Load(item)              // load presorted items into tree
// Path hinting
SetHint(item, *hint)    // insert or replace an existing item
GetHint(item, *hint)    // get an existing item
DeleteHint(item, *hint) // delete an item
// Copy-on-write
Copy()                  // copy the btreeExample
package main
import (
    "fmt"
    "github.com/tidwall/btree"
)
type Item struct {
    Key, Val string
}
// byKeys is a comparison function that compares item keys and returns true
// when a is less than b.
func byKeys(a, b interface{}) bool {
    i1, i2 := a.(*Item), b.(*Item)
    return i1.Key < i2.Key
}
// byVals is a comparison function that compares item values and returns true
// when a is less than b.
func byVals(a, b interface{}) bool {
    i1, i2 := a.(*Item), b.(*Item)
    if i1.Val < i2.Val {
        return true
    }
    if i1.Val > i2.Val {
        return false
    }
    // Both vals are equal so we should fall though
    // and let the key comparison take over.
    return byKeys(a, b)
}
func main() {
    // Create a tree for keys and a tree for values.
    // The "keys" tree will be sorted on the Keys field.
    // The "values" tree will be sorted on the Values field.
    keys := btree.New(byKeys)
    vals := btree.New(byVals)
    // Create some items.
    users := []*Item{
        &Item{Key: "user:1", Val: "Jane"},
        &Item{Key: "user:2", Val: "Andy"},
        &Item{Key: "user:3", Val: "Steve"},
        &Item{Key: "user:4", Val: "Andrea"},
        &Item{Key: "user:5", Val: "Janet"},
        &Item{Key: "user:6", Val: "Andy"},
    }
    // Insert each user into both trees
    for _, user := range users {
        keys.Set(user)
        vals.Set(user)
    }
    // Iterate over each user in the key tree
    keys.Ascend(nil, func(item interface{}) bool {
        kvi := item.(*Item)
        fmt.Printf("%s %s\n", kvi.Key, kvi.Val)
        return true
    })
    fmt.Printf("\n")
    // Iterate over each user in the val tree
    vals.Ascend(nil, func(item interface{}) bool {
        kvi := item.(*Item)
        fmt.Printf("%s %s\n", kvi.Key, kvi.Val)
        return true
    })
    // Output:
    // user:1 Jane
    // user:2 Andy
    // user:3 Steve
    // user:4 Andrea
    // user:5 Janet
    // user:6 Andy
    //
    // user:4 Andrea
    // user:2 Andy
    // user:6 Andy
    // user:1 Jane
    // user:5 Janet
    // user:3 Steve
}Performance
See tidwall/btree-benchmark for benchmark numbers.
Contact
Josh Baker @tidwall
License
Source code is available under the MIT License.
