snapshot of https://github.com/cortezaproject/corteza.git (2024.9.x, 2026-09-18; blobs > 131072B omitted)
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
Some checks failed
SonarQube / SonarQube (push) Failing after 5m28s
E2e test on main branch push / server and client test (map[name:admin port:8080]) (push) Failing after 3m33s
Server and lib tests / Library test (js) (push) Failing after 1m36s
Server and lib tests / Library test (vue) (push) Successful in 2m24s
Server and lib tests / Web client test (admin) (push) Successful in 2m52s
Server and lib tests / Web client test (compose) (push) Successful in 3m23s
Server and lib tests / Web client test (discovery) (push) Successful in 2m49s
Server and lib tests / Web client test (one) (push) Successful in 2m52s
Server and lib tests / Web client test (privacy) (push) Successful in 2m44s
Server and lib tests / Web client test (reporter) (push) Successful in 2m56s
Server and lib tests / Web client test (workflow) (push) Successful in 3m0s
Server and lib tests / Server tests (push) Failing after 4m55s
E2e test on main branch push / notify-failure (push) Failing after 9s
Server and lib tests / Send matrix testing notification (push) Successful in 2s
Mark stale issues and pull requests / stale (push) Successful in 40s
This commit is contained in:
18
server/vendor/github.com/tidwall/btree/LICENSE
generated
vendored
Normal file
18
server/vendor/github.com/tidwall/btree/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
Copyright (c) 2020 Josh Baker
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
45
server/vendor/github.com/tidwall/btree/PATH_HINT.md
generated
vendored
Normal file
45
server/vendor/github.com/tidwall/btree/PATH_HINT.md
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
# B-tree Path Hints
|
||||
|
||||
I use a thing I call path hints in my B-tree [C](https://github.com/tidwall/btree.c) and [Go](https://github.com/tidwall/btree) implementations. It's a search optimization.
|
||||
|
||||
## The B-tree
|
||||
|
||||
A standard [B-tree](https://en.wikipedia.org/wiki/B-tree) is an ordered tree-based data structure that stores its items in nodes. The B-tree has a single root node, which may have children nodes, and those children nodes may also have children nodes.
|
||||
|
||||
<img width="322" alt="image" src="https://user-images.githubusercontent.com/1156077/127664015-14ca38bb-1a3b-4d2f-80ff-27be0bd3d886.png">
|
||||
|
||||
Searching for items in a B-tree is fast. [O(log N)](https://en.wikipedia.org/wiki/Big_O_notation) to be exact.
|
||||
This is because the [binary search algorithm](https://en.wikipedia.org/wiki/Binary_search_algorithm) is used.
|
||||
|
||||
A binary search works by first comparing the item at the middle-most index of the root node with the target item.
|
||||
If the middle item is greater than the target item, then it divides the node in two and does the binary search on the left part of the node. If the middle is less, it searches the right part. And so on. If the target item is found, then the search stop. If the item is not found, then the search is passed to the child node at the appropriate index. This traversal terminates when item is found or there are no more child nodes.
|
||||
|
||||
<img width="600" alt="image" src="https://user-images.githubusercontent.com/1156077/127664822-6ab4f8f6-8ab5-477e-8e17-f52346f02819.png">
|
||||
|
||||
## The Path
|
||||
|
||||
Each index is a component of the path to the item (or where the item should be stored, if it does not exist in the tree).
|
||||
|
||||
Take the first example image. The item 9 is at path “1/0”. The item 16 is at path “1”. The item 21 is at path “2/1”. The item 5 is at path “0/2”.
|
||||
|
||||
## The Path Hint
|
||||
|
||||
A Path Hint is a predefined path that is provided to B-tree operations. It’s just a hint that says, “Hey B-tree, instead of starting your binary search with the middle index, start with what I provide you. My path may be wrong, and if so please provide me with the correct path so I get it right the next time.”
|
||||
|
||||
I’ve found using path hints can lead to a little performance increase of 150% - 300%. This is because in real-world cases the items that I’m working with are usually nearby each other in the tree.
|
||||
|
||||
Take for example inserting a group of timeseries points. They may often be received as chucks of near-contiguous items.
|
||||
Or, I'm sequentially inserting an ordered group of rows somewhere in the middle of a table.
|
||||
Or, I have a Redis-style key/value store, where the keys look have the common structure “user:98512:name”, “user:98512:email”, and I want to update a bunch of values for specified user.
|
||||
Using a path hint may help to avoid the unnecessary binary searching in each of these examples.
|
||||
|
||||
While I may see a 3x boost in when the path hint is right on, I'll only see around 5% decrease when the path hint is totally wrong.
|
||||
|
||||
## Using a Path Hint
|
||||
|
||||
All of the functions that take in a path hint argument mutate the path hint argument.
|
||||
|
||||
For single-threaded programs, it’s possible to use one shared path hint per B-tree for the life of the program.
|
||||
For multi-threaded programs, I find it best to use one path hint per B-tree , per thread.
|
||||
For server-client programs, one path hint per B-tree, per client should suffice.
|
||||
|
||||
514
server/vendor/github.com/tidwall/btree/README.md
generated
vendored
Normal file
514
server/vendor/github.com/tidwall/btree/README.md
generated
vendored
Normal file
@@ -0,0 +1,514 @@
|
||||
# btree
|
||||
|
||||
[](https://godoc.org/github.com/tidwall/btree)
|
||||
|
||||
An efficient [B-tree](https://en.wikipedia.org/wiki/B-tree) implementation in Go.
|
||||
|
||||
## Features
|
||||
|
||||
- Support for [Generics](#generics) (Go 1.18+).
|
||||
- `Map` and `Set` types 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](PATH_HINT.md) optimization for operations with nearby keys.
|
||||
|
||||
## Using
|
||||
|
||||
To start using this package, install Go and run:
|
||||
|
||||
```sh
|
||||
$ go get github.com/tidwall/btree
|
||||
```
|
||||
|
||||
## B-tree types
|
||||
|
||||
This package includes the following types of B-trees:
|
||||
|
||||
- [`btree.Map`](#btreemap):
|
||||
A fast B-tree for storing ordered key value pairs.
|
||||
Go 1.18+
|
||||
- [`btree.Set`](#btreeset):
|
||||
Like `Map`, but only for storing keys.
|
||||
Go 1.18+
|
||||
- [`btree.Generic`](#btreegeneric):
|
||||
A feature-rich B-tree for storing data using a custom comparator.
|
||||
Go 1.18+
|
||||
- [`btree.BTree`](#btreebtree):
|
||||
Like `Generic` but uses the `interface{}` type for data. Backwards compatible.
|
||||
Go 1.16+
|
||||
|
||||
### btree.Map
|
||||
|
||||
```go
|
||||
// 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 tree
|
||||
```
|
||||
|
||||
#### Example
|
||||
|
||||
```go
|
||||
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
|
||||
|
||||
```go
|
||||
// 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 tree
|
||||
```
|
||||
|
||||
#### Example
|
||||
|
||||
```go
|
||||
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.Generic
|
||||
|
||||
```go
|
||||
// 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 btree
|
||||
```
|
||||
|
||||
#### Example
|
||||
|
||||
```go
|
||||
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.NewGeneric[Item](byKeys)
|
||||
vals := btree.NewGeneric[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
|
||||
|
||||
```go
|
||||
// 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 btree
|
||||
```
|
||||
|
||||
#### Example
|
||||
|
||||
```go
|
||||
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
|
||||
|
||||
This implementation was designed with performance in mind.
|
||||
|
||||
- `google`: The [google/btree](https://github.com/google/btree) package (without generics)
|
||||
- `tidwall`: The [tidwall/btree](https://github.com/tidwall/btree) package (without generics)
|
||||
- `tidwall(G)`: The [tidwall/btree](https://github.com/tidwall/btree) package (generics using the `btree.Generic` type)
|
||||
- `tidwall(M)`: The [tidwall/btree](https://github.com/tidwall/btree) package (generics using the `btree.Map` type)
|
||||
- `go-arr`: A simple Go array
|
||||
|
||||
The following benchmarks were run on my 2019 Macbook Pro (2.4 GHz 8-Core Intel Core i9)
|
||||
using Go Development version 1.18 (beta1).
|
||||
The items are simple 8-byte ints.
|
||||
|
||||
```
|
||||
** sequential set **
|
||||
google: set-seq 1,000,000 ops in 156ms, 6,426,724/sec, 155 ns/op, 39.0 MB, 40 bytes/op
|
||||
tidwall: set-seq 1,000,000 ops in 135ms, 7,380,627/sec, 135 ns/op, 23.5 MB, 24 bytes/op
|
||||
tidwall(G): set-seq 1,000,000 ops in 78ms, 12,881,995/sec, 77 ns/op, 8.2 MB, 8 bytes/op
|
||||
tidwall(M): set-seq 1,000,000 ops in 46ms, 21,892,141/sec, 45 ns/op, 8.2 MB, 8 bytes/op
|
||||
tidwall: set-seq-hint 1,000,000 ops in 73ms, 13,789,017/sec, 72 ns/op, 23.5 MB, 24 bytes/op
|
||||
tidwall(G): set-seq-hint 1,000,000 ops in 48ms, 20,969,431/sec, 47 ns/op, 8.2 MB, 8 bytes/op
|
||||
tidwall: load-seq 1,000,000 ops in 45ms, 22,452,523/sec, 44 ns/op, 23.5 MB, 24 bytes/op
|
||||
tidwall(G): load-seq 1,000,000 ops in 22ms, 46,242,274/sec, 21 ns/op, 8.2 MB, 8 bytes/op
|
||||
tidwall(M): load-seq 1,000,000 ops in 13ms, 74,371,903/sec, 13 ns/op, 8.2 MB, 8 bytes/op
|
||||
go-arr: append 1,000,000 ops in 21ms, 47,141,875/sec, 21 ns/op, 8.1 MB, 8 bytes/op
|
||||
|
||||
** sequential get **
|
||||
google: get-seq 1,000,000 ops in 119ms, 8,389,459/sec, 119 ns/op
|
||||
tidwall: get-seq 1,000,000 ops in 110ms, 9,068,759/sec, 110 ns/op
|
||||
tidwall(G): get-seq 1,000,000 ops in 78ms, 12,813,135/sec, 78 ns/op
|
||||
tidwall(M): get-seq 1,000,000 ops in 62ms, 16,053,728/sec, 62 ns/op
|
||||
tidwall: get-seq-hint 1,000,000 ops in 64ms, 15,509,696/sec, 64 ns/op
|
||||
tidwall(G): get-seq-hint 1,000,000 ops in 41ms, 24,144,951/sec, 41 ns/op
|
||||
|
||||
** random set **
|
||||
google: set-rand 1,000,000 ops in 563ms, 1,777,592/sec, 562 ns/op, 29.7 MB, 31 bytes/op
|
||||
tidwall: set-rand 1,000,000 ops in 542ms, 1,844,397/sec, 542 ns/op, 29.6 MB, 31 bytes/op
|
||||
tidwall(G): set-rand 1,000,000 ops in 234ms, 4,271,764/sec, 234 ns/op, 11.2 MB, 11 bytes/op
|
||||
tidwall(M): set-rand 1,000,000 ops in 189ms, 5,292,236/sec, 188 ns/op, 11.2 MB, 11 bytes/op
|
||||
tidwall: set-rand-hint 1,000,000 ops in 602ms, 1,659,852/sec, 602 ns/op, 29.6 MB, 31 bytes/op
|
||||
tidwall(G): set-rand-hint 1,000,000 ops in 278ms, 3,595,435/sec, 278 ns/op, 11.2 MB, 11 bytes/op
|
||||
tidwall: set-after-copy 1,000,000 ops in 679ms, 1,471,954/sec, 679 ns/op
|
||||
tidwall(G): set-after-copy 1,000,000 ops in 238ms, 4,196,854/sec, 238 ns/op
|
||||
tidwall: load-rand 1,000,000 ops in 532ms, 1,880,877/sec, 531 ns/op, 29.6 MB, 31 bytes/op
|
||||
tidwall(G): load-rand 1,000,000 ops in 232ms, 4,316,475/sec, 231 ns/op, 11.2 MB, 11 bytes/op
|
||||
tidwall(M): load-rand 1,000,000 ops in 209ms, 4,790,169/sec, 208 ns/op, 11.2 MB, 11 bytes/op
|
||||
|
||||
** random get **
|
||||
google: get-rand 1,000,000 ops in 807ms, 1,238,703/sec, 807 ns/op
|
||||
tidwall: get-rand 1,000,000 ops in 812ms, 1,231,551/sec, 811 ns/op
|
||||
tidwall(G): get-rand 1,000,000 ops in 255ms, 3,914,819/sec, 255 ns/op
|
||||
tidwall(M): get-rand 1,000,000 ops in 190ms, 5,249,966/sec, 190 ns/op
|
||||
tidwall: get-rand-hint 1,000,000 ops in 876ms, 1,141,313/sec, 876 ns/op
|
||||
tidwall(G): get-rand-hint 1,000,000 ops in 258ms, 3,877,775/sec, 257 ns/op
|
||||
|
||||
** range **
|
||||
google: ascend 1,000,000 ops in 26ms, 39,101,882/sec, 25 ns/op
|
||||
tidwall: ascend 1,000,000 ops in 20ms, 50,223,988/sec, 19 ns/op
|
||||
tidwall(G): iter 1,000,000 ops in 8ms, 119,155,937/sec, 8 ns/op
|
||||
tidwall(G): scan 1,000,000 ops in 6ms, 168,275,407/sec, 5 ns/op
|
||||
tidwall(G): walk 1,000,000 ops in 5ms, 186,941,046/sec, 5 ns/op
|
||||
go-arr: for-loop 1,000,000 ops in 4ms, 272,234,997/sec, 3 ns/op
|
||||
```
|
||||
|
||||
*You can find the benchmark utility at [tidwall/btree-benchmark](https://github.com/tidwall/btree-benchmark)*
|
||||
|
||||
## Contact
|
||||
|
||||
Josh Baker [@tidwall](http://twitter.com/tidwall)
|
||||
|
||||
## License
|
||||
|
||||
Source code is available under the MIT [License](/LICENSE).
|
||||
273
server/vendor/github.com/tidwall/btree/btree.go
generated
vendored
Normal file
273
server/vendor/github.com/tidwall/btree/btree.go
generated
vendored
Normal file
@@ -0,0 +1,273 @@
|
||||
// Copyright 2020 Joshua J Baker. All rights reserved.
|
||||
// Use of this source code is governed by an MIT-style
|
||||
// license that can be found in the LICENSE file.
|
||||
package btree
|
||||
|
||||
type BTree struct {
|
||||
base *Generic[any]
|
||||
}
|
||||
|
||||
// New returns a new BTree
|
||||
func New(less func(a, b any) bool) *BTree {
|
||||
if less == nil {
|
||||
panic("nil less")
|
||||
}
|
||||
return &BTree{
|
||||
base: NewGeneric(less),
|
||||
}
|
||||
}
|
||||
|
||||
// NewNonConcurrent returns a new BTree which is not safe for concurrent
|
||||
// write operations by multiple goroutines.
|
||||
//
|
||||
// This is useful for when you do not need the BTree to manage the locking,
|
||||
// but would rather do it yourself.
|
||||
func NewNonConcurrent(less func(a, b any) bool) *BTree {
|
||||
if less == nil {
|
||||
panic("nil less")
|
||||
}
|
||||
return &BTree{
|
||||
base: NewGenericOptions(less,
|
||||
Options{
|
||||
NoLocks: true,
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
// Less is a convenience function that performs a comparison of two items
|
||||
// using the same "less" function provided to New.
|
||||
func (tr *BTree) Less(a, b any) bool {
|
||||
return tr.base.Less(a, b)
|
||||
}
|
||||
|
||||
// Set or replace a value for a key
|
||||
// Returns the value for the replaced item or nil if the key was not found.
|
||||
func (tr *BTree) Set(item any) (prev any) {
|
||||
return tr.SetHint(item, nil)
|
||||
}
|
||||
|
||||
// SetHint sets or replace a value for a key using a path hint
|
||||
// Returns the value for the replaced item or nil if the key was not found.
|
||||
func (tr *BTree) SetHint(item any, hint *PathHint) (prev any) {
|
||||
if item == nil {
|
||||
panic("nil item")
|
||||
}
|
||||
v, ok := tr.base.SetHint(item, hint)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Get a value for key.
|
||||
// Returns nil if the key was not found.
|
||||
func (tr *BTree) Get(key any) any {
|
||||
return tr.GetHint(key, nil)
|
||||
}
|
||||
|
||||
// GetHint gets a value for key using a path hint.
|
||||
// Returns nil if the item was not found.
|
||||
func (tr *BTree) GetHint(key any, hint *PathHint) (value any) {
|
||||
if key == nil {
|
||||
return nil
|
||||
}
|
||||
v, ok := tr.base.GetHint(key, hint)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Len returns the number of items in the tree
|
||||
func (tr *BTree) Len() int {
|
||||
return tr.base.Len()
|
||||
}
|
||||
|
||||
// Delete an item for a key.
|
||||
// Returns the deleted value or nil if the key was not found.
|
||||
func (tr *BTree) Delete(key any) (prev any) {
|
||||
return tr.DeleteHint(key, nil)
|
||||
}
|
||||
|
||||
// DeleteHint deletes a value for a key using a path hint
|
||||
// Returns the deleted value or nil if the key was not found.
|
||||
func (tr *BTree) DeleteHint(key any, hint *PathHint) (prev any) {
|
||||
if key == nil {
|
||||
return nil
|
||||
}
|
||||
v, ok := tr.base.DeleteHint(key, nil)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Ascend the tree within the range [pivot, last]
|
||||
// Pass nil for pivot to scan all item in ascending order
|
||||
// Return false to stop iterating
|
||||
func (tr *BTree) Ascend(pivot any, iter func(item any) bool) {
|
||||
if pivot == nil {
|
||||
tr.base.Scan(iter)
|
||||
} else {
|
||||
tr.base.Ascend(pivot, iter)
|
||||
}
|
||||
}
|
||||
|
||||
// Descend the tree within the range [pivot, first]
|
||||
// Pass nil for pivot to scan all item in descending order
|
||||
// Return false to stop iterating
|
||||
func (tr *BTree) Descend(pivot any, iter func(item any) bool) {
|
||||
if pivot == nil {
|
||||
tr.base.Reverse(iter)
|
||||
} else {
|
||||
tr.base.Descend(pivot, iter)
|
||||
}
|
||||
}
|
||||
|
||||
// Load is for bulk loading pre-sorted items
|
||||
// If the load replaces and existing item then the value for the replaced item
|
||||
// is returned.
|
||||
func (tr *BTree) Load(item any) (prev any) {
|
||||
if item == nil {
|
||||
panic("nil item")
|
||||
}
|
||||
v, ok := tr.base.Load(item)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Min returns the minimum item in tree.
|
||||
// Returns nil if the tree has no items.
|
||||
func (tr *BTree) Min() any {
|
||||
v, ok := tr.base.Min()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Max returns the maximum item in tree.
|
||||
// Returns nil if the tree has no items.
|
||||
func (tr *BTree) Max() any {
|
||||
v, ok := tr.base.Max()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// PopMin removes the minimum item in tree and returns it.
|
||||
// Returns nil if the tree has no items.
|
||||
func (tr *BTree) PopMin() any {
|
||||
v, ok := tr.base.PopMin()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// PopMax removes the minimum item in tree and returns it.
|
||||
// Returns nil if the tree has no items.
|
||||
func (tr *BTree) PopMax() any {
|
||||
v, ok := tr.base.PopMax()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// GetAt returns the value at index.
|
||||
// Return nil if the tree is empty or the index is out of bounds.
|
||||
func (tr *BTree) GetAt(index int) any {
|
||||
v, ok := tr.base.GetAt(index)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// DeleteAt deletes the item at index.
|
||||
// Return nil if the tree is empty or the index is out of bounds.
|
||||
func (tr *BTree) DeleteAt(index int) any {
|
||||
v, ok := tr.base.DeleteAt(index)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return v
|
||||
}
|
||||
|
||||
// Height returns the height of the tree.
|
||||
// Returns zero if tree has no items.
|
||||
func (tr *BTree) Height() int {
|
||||
return tr.base.Height()
|
||||
}
|
||||
|
||||
// Walk iterates over all items in tree, in order.
|
||||
// The items param will contain one or more items.
|
||||
func (tr *BTree) Walk(iter func(items []any)) {
|
||||
tr.base.Walk(func(items []any) bool {
|
||||
iter(items)
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// Copy the tree. This is a copy-on-write operation and is very fast because
|
||||
// it only performs a shadowed copy.
|
||||
func (tr *BTree) Copy() *BTree {
|
||||
return &BTree{base: tr.base.Copy()}
|
||||
}
|
||||
|
||||
type Iter struct {
|
||||
base GenericIter[any]
|
||||
}
|
||||
|
||||
// Iter returns a read-only iterator.
|
||||
// The Release method must be called finished with iterator.
|
||||
func (tr *BTree) Iter() Iter {
|
||||
return Iter{tr.base.Iter()}
|
||||
}
|
||||
|
||||
// Seek to item greater-or-equal-to key.
|
||||
// Returns false if there was no item found.
|
||||
func (iter *Iter) Seek(key any) bool {
|
||||
return iter.base.Seek(key)
|
||||
}
|
||||
|
||||
// First moves iterator to first item in tree.
|
||||
// Returns false if the tree is empty.
|
||||
func (iter *Iter) First() bool {
|
||||
return iter.base.First()
|
||||
}
|
||||
|
||||
// Last moves iterator to last item in tree.
|
||||
// Returns false if the tree is empty.
|
||||
func (iter *Iter) Last() bool {
|
||||
return iter.base.Last()
|
||||
}
|
||||
|
||||
// First moves iterator to first item in tree.
|
||||
// Returns false if the tree is empty.
|
||||
func (iter *Iter) Release() {
|
||||
iter.base.Release()
|
||||
}
|
||||
|
||||
// Next moves iterator to the next item in iterator.
|
||||
// Returns false if the tree is empty or the iterator is at the end of
|
||||
// the tree.
|
||||
func (iter *Iter) Next() bool {
|
||||
return iter.base.Next()
|
||||
}
|
||||
|
||||
// Prev moves iterator to the previous item in iterator.
|
||||
// Returns false if the tree is empty or the iterator is at the beginning of
|
||||
// the tree.
|
||||
func (iter *Iter) Prev() bool {
|
||||
return iter.base.Prev()
|
||||
}
|
||||
|
||||
// Item returns the current iterator item.
|
||||
func (iter *Iter) Item() any {
|
||||
return iter.base.Item()
|
||||
}
|
||||
1220
server/vendor/github.com/tidwall/btree/generic.go
generated
vendored
Normal file
1220
server/vendor/github.com/tidwall/btree/generic.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
1043
server/vendor/github.com/tidwall/btree/map.go
generated
vendored
Normal file
1043
server/vendor/github.com/tidwall/btree/map.go
generated
vendored
Normal file
File diff suppressed because it is too large
Load Diff
170
server/vendor/github.com/tidwall/btree/set.go
generated
vendored
Normal file
170
server/vendor/github.com/tidwall/btree/set.go
generated
vendored
Normal file
@@ -0,0 +1,170 @@
|
||||
package btree
|
||||
|
||||
type Set[K ordered] struct {
|
||||
base Map[K, struct{}]
|
||||
}
|
||||
|
||||
// Copy
|
||||
func (tr *Set[K]) Copy() *Set[K] {
|
||||
tr2 := new(Set[K])
|
||||
tr2.base = *tr.base.Copy()
|
||||
return tr2
|
||||
}
|
||||
|
||||
// Insert an item
|
||||
func (tr *Set[K]) Insert(key K) {
|
||||
tr.base.Set(key, struct{}{})
|
||||
}
|
||||
|
||||
func (tr *Set[K]) Scan(iter func(key K) bool) {
|
||||
tr.base.Scan(func(key K, value struct{}) bool {
|
||||
return iter(key)
|
||||
})
|
||||
}
|
||||
|
||||
// Get a value for key
|
||||
func (tr *Set[K]) Contains(key K) bool {
|
||||
_, ok := tr.base.Get(key)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Len returns the number of items in the tree
|
||||
func (tr *Set[K]) Len() int {
|
||||
return tr.base.Len()
|
||||
}
|
||||
|
||||
// Delete an item
|
||||
func (tr *Set[K]) Delete(key K) {
|
||||
tr.base.Delete(key)
|
||||
}
|
||||
|
||||
// Ascend the tree within the range [pivot, last]
|
||||
// Pass nil for pivot to scan all item in ascending order
|
||||
// Return false to stop iterating
|
||||
func (tr *Set[K]) Ascend(pivot K, iter func(key K) bool) {
|
||||
tr.base.Ascend(pivot, func(key K, value struct{}) bool {
|
||||
return iter(key)
|
||||
})
|
||||
}
|
||||
|
||||
func (tr *Set[K]) Reverse(iter func(key K) bool) {
|
||||
tr.base.Reverse(func(key K, value struct{}) bool {
|
||||
return iter(key)
|
||||
})
|
||||
}
|
||||
|
||||
// Descend the tree within the range [pivot, first]
|
||||
// Pass nil for pivot to scan all item in descending order
|
||||
// Return false to stop iterating
|
||||
func (tr *Set[K]) Descend(pivot K, iter func(key K) bool) {
|
||||
tr.base.Descend(pivot, func(key K, value struct{}) bool {
|
||||
return iter(key)
|
||||
})
|
||||
}
|
||||
|
||||
// Load is for bulk loading pre-sorted items
|
||||
func (tr *Set[K]) Load(key K) {
|
||||
tr.base.Load(key, struct{}{})
|
||||
}
|
||||
|
||||
// Min returns the minimum item in tree.
|
||||
// Returns nil if the treex has no items.
|
||||
func (tr *Set[K]) Min() (K, bool) {
|
||||
key, _, ok := tr.base.Min()
|
||||
return key, ok
|
||||
}
|
||||
|
||||
// Max returns the maximum item in tree.
|
||||
// Returns nil if the tree has no items.
|
||||
func (tr *Set[K]) Max() (K, bool) {
|
||||
key, _, ok := tr.base.Max()
|
||||
return key, ok
|
||||
}
|
||||
|
||||
// PopMin removes the minimum item in tree and returns it.
|
||||
// Returns nil if the tree has no items.
|
||||
func (tr *Set[K]) PopMin() (K, bool) {
|
||||
key, _, ok := tr.base.PopMin()
|
||||
return key, ok
|
||||
|
||||
}
|
||||
|
||||
// PopMax removes the minimum item in tree and returns it.
|
||||
// Returns nil if the tree has no items.
|
||||
func (tr *Set[K]) PopMax() (K, bool) {
|
||||
key, _, ok := tr.base.PopMax()
|
||||
return key, ok
|
||||
|
||||
}
|
||||
|
||||
// GetAt returns the value at index.
|
||||
// Return nil if the tree is empty or the index is out of bounds.
|
||||
func (tr *Set[K]) GetAt(index int) (K, bool) {
|
||||
key, _, ok := tr.base.GetAt(index)
|
||||
return key, ok
|
||||
}
|
||||
|
||||
// DeleteAt deletes the item at index.
|
||||
// Return nil if the tree is empty or the index is out of bounds.
|
||||
func (tr *Set[K]) DeleteAt(index int) (K, bool) {
|
||||
key, _, ok := tr.base.DeleteAt(index)
|
||||
return key, ok
|
||||
}
|
||||
|
||||
// Height returns the height of the tree.
|
||||
// Returns zero if tree has no items.
|
||||
func (tr *Set[K]) Height() int {
|
||||
return tr.base.Height()
|
||||
}
|
||||
|
||||
// SetIter represents an iterator for btree.Set
|
||||
type SetIter[K ordered] struct {
|
||||
base MapIter[K, struct{}]
|
||||
}
|
||||
|
||||
// Iter returns a read-only iterator.
|
||||
func (tr *Set[K]) Iter() SetIter[K] {
|
||||
return SetIter[K]{tr.base.Iter()}
|
||||
}
|
||||
|
||||
// Seek to item greater-or-equal-to key.
|
||||
// Returns false if there was no item found.
|
||||
func (iter *SetIter[K]) Seek(key K) bool {
|
||||
return iter.base.Seek(key)
|
||||
}
|
||||
|
||||
// First moves iterator to first item in tree.
|
||||
// Returns false if the tree is empty.
|
||||
func (iter *SetIter[K]) First() bool {
|
||||
return iter.base.First()
|
||||
}
|
||||
|
||||
// Last moves iterator to last item in tree.
|
||||
// Returns false if the tree is empty.
|
||||
func (iter *SetIter[K]) Last() bool {
|
||||
return iter.base.Last()
|
||||
}
|
||||
|
||||
// Next moves iterator to the next item in iterator.
|
||||
// Returns false if the tree is empty or the iterator is at the end of
|
||||
// the tree.
|
||||
func (iter *SetIter[K]) Next() bool {
|
||||
return iter.base.Next()
|
||||
}
|
||||
|
||||
// Prev moves iterator to the previous item in iterator.
|
||||
// Returns false if the tree is empty or the iterator is at the beginning of
|
||||
// the tree.
|
||||
func (iter *SetIter[K]) Prev() bool {
|
||||
return iter.base.Prev()
|
||||
}
|
||||
|
||||
// Key returns the current iterator item key.
|
||||
func (iter *SetIter[K]) Key() K {
|
||||
return iter.base.Key()
|
||||
}
|
||||
|
||||
// Keys returns all the keys in order.
|
||||
func (tr *Set[K]) Keys() []K {
|
||||
return tr.base.Keys()
|
||||
}
|
||||
Reference in New Issue
Block a user