Skip to content

Commit 59788d5

Browse files
Merge pull request #64 from alexandercampbell-wf/misc_readme
Misc readme
2 parents 9782481 + 5b19f5e commit 59788d5

File tree

2 files changed

+150
-56
lines changed

2 files changed

+150
-56
lines changed

README.md

+140-50
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,145 @@
1-
go-datastructure
2-
================
31

4-
Package containing some useful datastructures when writing code in Go.
2+
go-datastructures
3+
=================
54

6-
### NOTE: only tested with Go 1.3+.
7-
8-
#### Augmented Tree:
9-
Interval tree for collision in n-dimensional ranges. Implemented via a red-black augmented tree. Extra dimensions are handled in simultaneous inserts/queries to save space although this may result in suboptimal time complexity. Intersection determined using bit arrays. In a single dimension, inserts, deletes, and queries should be in O(log n) time.
10-
11-
#### Bitarray:
12-
Bitarray used to detect existence without having to resort to hashing with hashmaps. Requires entities have a uint64 unique identifier. Two implementations exist, regular and sparse. Sparse saves a great deal of space but insertions are O(log n). There are some useful functions on the BitArray interface to detect intersection between two bitarrays.
13-
14-
#### Futures:
15-
A helpful tool to send a "broadcast" message to listeners. Channels have the issue that once one listener takes a message from a channel the other listeners aren't notified. There were many cases when I wanted to notify many listeners of a single event and this package helps.
16-
17-
#### Queue:
18-
Package contains both a normal and priority queue. Both implementations never block on send and grow as much as necessary. Both also only return errors if you attempt to push to a disposed queue and will not panic like sending a message on a closed channel. The priority queue also allows you to place items in priority order inside the queue. If you give a useful hint to the regular queue, it is actually faster than a channel. The priority queue is somewhat slow currently and targeted for an update to a Fibonacci heap.
19-
20-
Also included in the queue package is a MPMC threadsafe ring buffer. This is a block full/empty queue, but will return a blocked thread if the queue is disposed while a thread is blocked. This can be used to synchronize goroutines and ensure goroutines quit so objects can be GC'd. Threadsafety is acheived using only CAS operations making this queue quite fast. Benchmarks can be found in that package.
21-
22-
#### Range Tree:
23-
Useful to determine if n-dimensional points fall within an n-dimensional range. Not a typical range tree however, as we are actually using an n-dimensional sorted list of points as this proved to be simpler and faster than attempting a traditional range tree while saving space on any dimension greater than one. Inserts are typical BBST times at O(log n^d) where d is the number of dimensions.
24-
25-
#### Set:
26-
Self explanatory. Could be further optimized by getting the uintptr of the generic interface{} used and using that as the key as Golang maps handle that much better than the generic struct type.
5+
Go-datastructures is a collection of useful, performant, and threadsafe Go
6+
datastructures.
277

28-
#### Threadsafe:
29-
A package that is meant to contain some commonly used items but in a threadsafe way. Example: there's a threadsafe error in there as I commonly found myself wanting to set an error in many threads at the same time (yes, I know, but channels are slow).
30-
31-
#### AVL Tree:
32-
This is an example of a branch copy immutable AVL BBST. Any operation on a node makes a copy of that node's branch. Because of this, this tree is inherently threadsafe although the writes will likely still need to be serialized. This structure is good if your use case is a large number of reads and infrequent writes as reads will be highly available but writes somewhat slow due to the copying. This structure serves as a basis for a large number of functional data structures.
33-
34-
#### X-Fast Trie:
35-
An interesting design that treats integers as words and uses a trie structure to reduce time complexities by matching prefixes. This structure is really fast for finding values or making predecessor/successor types of queries, but also results in greater than linear space consumption. The exact time complexities can be found in that package.
36-
37-
#### Y-Fast Trie:
38-
An extension of the X-Fast trie in which an X-Fast trie is combined with some other ordered data structure to reduce space consumption and improve CRUD types of operations. These secondary structures are often BSTs, but our implemention uses a simple ordered list as I believe this improves cache locality. We also use fixed size buckets to aid in parallelization of operations. Exact time complexities are in that package.
39-
40-
#### Fast integer hashmap:
41-
A datastructure used for checking existence but without knowing the bounds of your data. If you have a limited small bounds, the bitarray package might be a better choice. This implementation uses a fairly simple hashing alogrithm combined with linear probing and a flat datastructure to provide optimal performance up to a few million integers (faster than the native Golang implementation). Beyond that, the native implementation is faster (I believe they are using a large -ary B-tree). In the future, this will be implemented with a B-tree for scale.
42-
43-
#### Skiplist:
44-
An ordered structure that provides amoritized logarithmic operations but without the complication of rotations that are required by BSTs. In testing, however, the performance of the skip list is often far worse than the guaranteed log n time of a BBST. Tall nodes tend to "cast shadows", especially when large bitsizes are required as the optimum maximum height for a node is often based on this. More detailed performance characteristics are provided in that package.
45-
46-
#### Sort:
47-
The sort package implements a multithreaded bucket sort that can be up to 3x faster than the native Golang sort package. These buckets are then merged using a symmetrical merge, similar to the stable sort in the Golang package. However, our algorithm is modified so that two sorted lists can be merged by using symmetrical decomposition.
48-
49-
#### Numerics:
50-
Early work on some nonlinear optimization problems. The initial implementation allows a simple use case with either linear or nonlinear constraints. You can find min/max or target an optimal value. The package currently employs a probablistic global restart system in an attempt to avoid local critical points. More details can be found in that package.
8+
### NOTE: only tested with Go 1.3+.
519

52-
#### B+ Tree:
53-
Initial implementation of a B+ tree. Delete method still needs added as well as some performance optimization. Specific performance characteristics can be found in that package. Despite the theoretical superiority of BSTs, the B-tree often has better all around performance due to cache locality. The current implementation is mutable, but the immutable AVL tree can be used to build an immutable version. Unfortunately, to make the B-tree generic we require an interface and the most expensive operation in CPU profiling is the interface method which in turn calls into runtime.assertI2T. We need generics.
10+
#### Augmented Tree
11+
12+
Interval tree for collision in n-dimensional ranges. Implemented via a
13+
red-black augmented tree. Extra dimensions are handled in simultaneous
14+
inserts/queries to save space although this may result in suboptimal time
15+
complexity. Intersection determined using bit arrays. In a single dimension,
16+
inserts, deletes, and queries should be in O(log n) time.
17+
18+
#### Bitarray
19+
20+
Bitarray used to detect existence without having to resort to hashing with
21+
hashmaps. Requires entities have a uint64 unique identifier. Two
22+
implementations exist, regular and sparse. Sparse saves a great deal of space
23+
but insertions are O(log n). There are some useful functions on the BitArray
24+
interface to detect intersection between two bitarrays.
25+
26+
#### Futures
27+
28+
A helpful tool to send a "broadcast" message to listeners. Channels have the
29+
issue that once one listener takes a message from a channel the other listeners
30+
aren't notified. There were many cases when I wanted to notify many listeners
31+
of a single event and this package helps.
32+
33+
#### Queue
34+
35+
Package contains both a normal and priority queue. Both implementations never
36+
block on send and grow as much as necessary. Both also only return errors if
37+
you attempt to push to a disposed queue and will not panic like sending a
38+
message on a closed channel. The priority queue also allows you to place items
39+
in priority order inside the queue. If you give a useful hint to the regular
40+
queue, it is actually faster than a channel. The priority queue is somewhat
41+
slow currently and targeted for an update to a Fibonacci heap.
42+
43+
Also included in the queue package is a MPMC threadsafe ring buffer. This is a
44+
block full/empty queue, but will return a blocked thread if the queue is
45+
disposed while a thread is blocked. This can be used to synchronize goroutines
46+
and ensure goroutines quit so objects can be GC'd. Threadsafety is acheived
47+
using only CAS operations making this queue quite fast. Benchmarks can be found
48+
in that package.
49+
50+
#### Range Tree
51+
52+
Useful to determine if n-dimensional points fall within an n-dimensional range.
53+
Not a typical range tree however, as we are actually using an n-dimensional
54+
sorted list of points as this proved to be simpler and faster than attempting a
55+
traditional range tree while saving space on any dimension greater than one.
56+
Inserts are typical BBST times at O(log n^d) where d is the number of
57+
dimensions.
58+
59+
#### Set
60+
Self explanatory. Could be further optimized by getting the uintptr of the
61+
generic interface{} used and using that as the key as Golang maps handle that
62+
much better than the generic struct type.
63+
64+
#### Threadsafe
65+
A package that is meant to contain some commonly used items but in a threadsafe
66+
way. Example: there's a threadsafe error in there as I commonly found myself
67+
wanting to set an error in many threads at the same time (yes, I know, but
68+
channels are slow).
69+
70+
#### AVL Tree
71+
72+
This is an example of a branch copy immutable AVL BBST. Any operation on a node
73+
makes a copy of that node's branch. Because of this, this tree is inherently
74+
threadsafe although the writes will likely still need to be serialized. This
75+
structure is good if your use case is a large number of reads and infrequent
76+
writes as reads will be highly available but writes somewhat slow due to the
77+
copying. This structure serves as a basis for a large number of functional data
78+
structures.
79+
80+
#### X-Fast Trie
81+
82+
An interesting design that treats integers as words and uses a trie structure to
83+
reduce time complexities by matching prefixes. This structure is really fast
84+
for finding values or making predecessor/successor types of queries, but also
85+
results in greater than linear space consumption. The exact time complexities
86+
can be found in that package.
87+
88+
#### Y-Fast Trie
89+
90+
An extension of the X-Fast trie in which an X-Fast trie is combined with some
91+
other ordered data structure to reduce space consumption and improve CRUD types
92+
of operations. These secondary structures are often BSTs, but our implemention
93+
uses a simple ordered list as I believe this improves cache locality. We also
94+
use fixed size buckets to aid in parallelization of operations. Exact time
95+
complexities are in that package.
96+
97+
#### Fast integer hashmap
98+
99+
A datastructure used for checking existence but without knowing the bounds of
100+
your data. If you have a limited small bounds, the bitarray package might be a
101+
better choice. This implementation uses a fairly simple hashing alogrithm
102+
combined with linear probing and a flat datastructure to provide optimal
103+
performance up to a few million integers (faster than the native Golang
104+
implementation). Beyond that, the native implementation is faster (I believe
105+
they are using a large -ary B-tree). In the future, this will be implemented
106+
with a B-tree for scale.
107+
108+
#### Skiplist
109+
110+
An ordered structure that provides amoritized logarithmic operations but without
111+
the complication of rotations that are required by BSTs. In testing, however,
112+
the performance of the skip list is often far worse than the guaranteed log n
113+
time of a BBST. Tall nodes tend to "cast shadows", especially when large
114+
bitsizes are required as the optimum maximum height for a node is often based on
115+
this. More detailed performance characteristics are provided in that package.
116+
117+
#### Sort
118+
119+
The sort package implements a multithreaded bucket sort that can be up to 3x
120+
faster than the native Golang sort package. These buckets are then merged using
121+
a symmetrical merge, similar to the stable sort in the Golang package. However,
122+
our algorithm is modified so that two sorted lists can be merged by using
123+
symmetrical decomposition.
124+
125+
#### Numerics
126+
127+
Early work on some nonlinear optimization problems. The initial implementation
128+
allows a simple use case with either linear or nonlinear constraints. You can
129+
find min/max or target an optimal value. The package currently employs a
130+
probablistic global restart system in an attempt to avoid local critical points.
131+
More details can be found in that package.
132+
133+
#### B+ Tree
134+
135+
Initial implementation of a B+ tree. Delete method still needs added as well as
136+
some performance optimization. Specific performance characteristics can be
137+
found in that package. Despite the theoretical superiority of BSTs, the B-tree
138+
often has better all around performance due to cache locality. The current
139+
implementation is mutable, but the immutable AVL tree can be used to build an
140+
immutable version. Unfortunately, to make the B-tree generic we require an
141+
interface and the most expensive operation in CPU profiling is the interface
142+
method which in turn calls into runtime.assertI2T. We need generics.
54143

55144
### Installation
56145

@@ -78,10 +167,11 @@ Once you've done this once, you can simply use this command to run all unit test
78167
go test ./...
79168

80169

81-
### Notice
170+
### Contributing
82171

83172
Requirements to commit here:
84173

174+
- Branch off master, PR back to master.
85175
- `gofmt`'d code.
86176
- Compliance with [these guidelines](https://code.google.com/p/go-wiki/wiki/CodeReviewComments)
87177
- Unit test coverage

datastructures.go

+10-6
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1-
package datastructures
2-
31
/*
4-
Package datastructures exists solely to aid consumers of the
5-
go-datastructures library when using dependency managers. Depman,
6-
for instance, will work correctly with any datastructure by simply
7-
importing this package instead of each subpackage individually.
2+
Package datastructures exists solely to aid consumers of the go-datastructures
3+
library when using dependency managers. Depman, for instance, will work
4+
correctly with any datastructure by simply importing this package instead of
5+
each subpackage individually.
6+
7+
For more information about the datastructures package, see the README at
8+
9+
http://github.com/Workiva/go-datastructures
10+
811
*/
12+
package datastructures
913

1014
import (
1115
_ "github.com/Workiva/go-datastructures/augmentedtree"

0 commit comments

Comments
 (0)