Add vendored deps for tracer.

This commit is contained in:
Tom Wilkie
2016-01-31 17:51:55 -08:00
parent c16f0d7f40
commit 394bc88f2a
5 changed files with 779 additions and 0 deletions

View File

@@ -0,0 +1,22 @@
The MIT License (MIT)
Copyright (c) 2015 Matthew Sackman
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.

View File

@@ -0,0 +1,2 @@
Skiplist implementation for Go. Comes with tests. Currently no docs,
but it's pretty obvious stuff.

View File

@@ -0,0 +1,429 @@
package skiplist
import (
"fmt"
"math"
"math/rand"
"strings"
)
const (
p = 0.3
defaultDepth = 2
)
type Comparable interface {
LessThan(Comparable) bool
Equal(Comparable) bool
}
type SkipList struct {
length uint
terminus *Node
levelProbabilities []float32
curCapacity uint
curDepth uint
nodes []Node
localRand *rand.Rand
}
type Node struct {
Key Comparable
Value interface{}
heightRand float32
prev *Node
nexts []*Node
skiplist *SkipList
}
func New(rng *rand.Rand) *SkipList {
depth := defaultDepth
terminus := &Node{
heightRand: 0,
nexts: make([]*Node, depth),
}
terminus.prev = terminus
for idx := 0; idx < len(terminus.nexts); idx++ {
terminus.nexts[idx] = terminus
}
s := &SkipList{
length: 0,
terminus: terminus,
curDepth: uint(depth),
localRand: rng,
}
s.levelProbabilities = []float32{p}
terminus.skiplist = s
s.determineCapacity()
// s.validate()
return s
}
func (s *SkipList) determineCapacity() {
base := float64(1.0) / p
capacity := math.Pow(base, float64(s.curDepth))
s.curCapacity = uint(math.Floor(capacity))
}
func (s *SkipList) chooseNumLevels() (float32, int) {
r := s.localRand.Float32()
max := len(s.levelProbabilities)
for idx := 0; idx < max; idx++ {
if r > s.levelProbabilities[idx] {
return r, idx + 1
}
}
return r, max + 1
}
func (s *SkipList) ensureCapacity() {
// defer s.validate()
if s.length < s.curCapacity {
return
}
threshold := p * s.levelProbabilities[s.curDepth-2]
s.curDepth++
s.levelProbabilities = append(s.levelProbabilities, threshold)
s.determineCapacity()
// cur and next are just used to walk through the list at lvl. prev
// records the last node that made it up to the new level.
cur := s.terminus
lvl := len(cur.nexts) - 1
prev := cur
for {
next := cur.nexts[lvl]
if cur.heightRand <= threshold {
cur.nexts = append(cur.nexts, s.terminus)
prev.nexts[lvl+1] = cur
prev = cur
}
if next == s.terminus {
break
} else {
cur = next
}
}
}
func (s *SkipList) getNode() *Node {
l := len(s.nodes)
if l == 0 {
l = int(s.curCapacity)
s.nodes = make([]Node, l)
}
l--
n := &s.nodes[l]
s.nodes = s.nodes[:l]
return n
}
func (s *SkipList) getEqOrLessThan(cur *Node, k Comparable, captureDescent bool) (*Node, []*Node) {
// defer s.validate()
if s.length == 0 {
return s.terminus, nil
}
if cur != s.terminus {
if k.Equal(cur.Key) {
return cur, nil
}
if k.LessThan(cur.Key) {
return s.getEqOrLessThan(s.terminus, k, captureDescent)
}
}
// 1. Travel, not-descending, as far as possible
lvl := len(cur.nexts) - 1
for {
n := cur.nexts[lvl]
if n == s.terminus {
break
}
if n.Key.LessThan(k) {
cur = n
lvl = len(cur.nexts) - 1
} else if n.Key.Equal(k) {
return n, nil
} else {
break
}
}
// 2. Now descend as needed
var descent []*Node
if captureDescent {
descent = make([]*Node, lvl+1)
descent[lvl] = cur
}
for lvl--; lvl >= 0; lvl-- {
for {
n := cur.nexts[lvl]
if n == s.terminus {
break
}
if n.Key.LessThan(k) {
cur = n
} else if n.Key.Equal(k) {
return n, descent
} else {
break
}
}
if captureDescent {
descent[lvl] = cur
}
}
return cur, descent
}
func (s *SkipList) insert(cur *Node, k Comparable, v interface{}, n *Node) *Node {
// defer s.validate()
// do this first even though we may not need to - if we do it after
// the getEqOrLessThan call, we may break descent.
s.ensureCapacity()
cur, descent := s.getEqOrLessThan(cur, k, true)
if cur != s.terminus && cur.Key.Equal(k) {
cur.Value = v
return cur
}
// We didn't find k, so cur will be the node immediately prior to
// where k should go.
heightRand, height := s.chooseNumLevels()
if n == nil {
n = s.getNode()
}
n.Key = k
n.Value = v
n.heightRand = heightRand
n.nexts = make([]*Node, height)
n.prev = cur
n.skiplist = s
if len(cur.nexts) >= len(n.nexts) {
for idx := 0; idx < len(n.nexts); idx++ {
n.nexts[idx] = cur.nexts[idx]
cur.nexts[idx] = n
}
} else {
// Descent may capture only part of the path: it may be shorter
// than levels (in the case where the original cur is !=
// s.terminus) and we reached the correct location without
// travelling up very far. However, because we didn't find k, we
// know that all the "lower" levels of descent will be populated
// (where "lower" is "closer to [0]"), so we just need to fill in
// the "top".
if len(n.nexts) > len(descent) {
_, extra := s.getEqOrLessThan(s.terminus, descent[len(descent)-1].Key, true)
// Aside: because we know we'll find that Key, all the lower
// indices of extra will be nil.
descent = append(descent, extra[len(descent):]...)
}
for idx := 0; idx < len(n.nexts); idx++ {
n.nexts[idx] = descent[idx].nexts[idx]
descent[idx].nexts[idx] = n
}
}
n._next().prev = n
s.length++
return n
}
func (s *SkipList) remove(cur *Node, k Comparable) interface{} {
// defer s.validate()
n, _ := s.getEqOrLessThan(cur, k, false)
if n == s.terminus || !n.Key.Equal(k) {
return nil
}
s.removeNode(n)
n.nullify()
return n.Value
}
func (s *SkipList) removeNode(n *Node) {
// defer s.validate()
p := n.prev
n._next().prev = p
s.length--
for idx := 0; idx < len(p.nexts) && idx < len(n.nexts); idx++ {
p.nexts[idx] = n.nexts[idx]
}
if len(p.nexts) < len(n.nexts) {
_, descent := s.getEqOrLessThan(s.terminus, p.Key, true)
// because we know we're going to find Key, the lower indices
// of descent will be nil. But we know p == n.prev, so all of
// those pointers will be to n anyway, which we've already
// dealt with in the previous loop.
for idx := len(p.nexts); idx < len(n.nexts); idx++ {
descent[idx].nexts[idx] = n.nexts[idx]
}
}
}
func (s *SkipList) reposition(cur *Node, k Comparable) {
// defer s.validate()
needsMove := false
if cur != s.terminus {
if cur.prev != s.terminus && !cur.prev.Key.LessThan(k) {
needsMove = true
} else if n := cur._next(); n != s.terminus && !k.LessThan(n.Key) {
needsMove = true
}
}
if needsMove {
s.removeNode(cur)
cur.Key = k
s.insert(cur.prev, cur.Key, cur.Value, cur)
}
}
func (s *SkipList) First() *Node {
return s.terminus.Next()
}
func (s *SkipList) Last() *Node {
return s.terminus.Prev()
}
func (s *SkipList) Insert(k Comparable, v interface{}) *Node {
return s.insert(s.terminus, k, v, nil)
}
func (s *SkipList) Get(k Comparable) *Node {
return s.terminus.Get(k)
}
func (s *SkipList) Remove(k Comparable) interface{} {
return s.remove(s.terminus, k)
}
func (s *SkipList) Len() uint {
return s.length
}
// NB: this destroys t. Do not use t after this.
func (s *SkipList) Merge(t *SkipList) {
// defer s.validate()
cur := s.terminus
for n := t.First(); n != nil; {
m := n.Next() // need to save this out before we destroy it in the insert
cur = s.insert(cur, n.Key, n.Value, n)
n = m
}
}
func (s *SkipList) validate() {
visited := make(map[*Node]bool, int(s.length))
cur := s.terminus
visited[cur] = true
l := uint(0)
for {
if cur != s.terminus {
l++
}
if cur._next().prev != cur {
panic(fmt.Sprintf("Node (%v) has next pointer to %v, which has prev pointer to %v", cur, cur._next(), cur._next().prev))
}
if cur.prev._next() != cur {
panic(fmt.Sprintf("Node (%v) has prev pointer to %v, which has next pointer to %v", cur, cur.prev, cur.prev._next()))
}
for h, n := range cur.nexts {
if h >= len(n.nexts) {
panic(fmt.Sprintf("Node (%v) has next pointer at level %v pointing down to node (%v) which has %v height", cur, h, n, len(n.nexts)))
}
}
n := cur._next()
if n == s.terminus {
break
}
if visited[n] {
panic(fmt.Sprintf("Node (%v) has next as %v which is already visited!", cur, n))
}
if cur != s.terminus && !cur.Key.LessThan(n.Key) {
panic(fmt.Sprintf("Node keys in wrong order: expecting %v < %v", cur.Key, n.Key))
}
if n.prev != cur {
panic(fmt.Sprintf("Node (%v) has next (%v) which does not point back correctly", cur, n))
}
cur = n
}
if l != s.length {
panic(fmt.Sprintf("length is wrong: counted %v but length is %v", l, s.length))
}
}
func (n *Node) Get(k Comparable) *Node {
m, _ := n.skiplist.getEqOrLessThan(n, k, false)
if m != n.skiplist.terminus && m.Key.Equal(k) {
return m
} else {
return nil
}
}
func (n *Node) Insert(k Comparable, v interface{}) *Node {
return n.skiplist.insert(n, k, v, nil)
}
func (n *Node) Remove() interface{} {
return n.skiplist.remove(n, n.Key)
}
func (n *Node) _next() *Node {
return n.nexts[0]
}
func (n *Node) Next() *Node {
if m := n.nexts[0]; m != n.skiplist.terminus {
return m
} else {
return nil
}
}
func (n *Node) Prev() *Node {
if m := n.prev; m != n.skiplist.terminus {
return m
} else {
return nil
}
}
func (n *Node) Reposition(k Comparable) {
n.skiplist.reposition(n, k)
}
func (n *Node) nullify() {
// this is called when n is removed from the skiplist. It's really
// just to ensure that if someone has a reference to n lying
// around, they can't use it.
n.prev = nil
n.nexts = nil
n.skiplist = nil
}
func (s *SkipList) String() string {
strs := make([]string, 1, s.length+1)
strs[0] = fmt.Sprint(s.terminus)
for cur := s.terminus._next(); cur != s.terminus; cur = cur._next() {
strs = append(strs, fmt.Sprint(cur))
}
return fmt.Sprintf("Skiplist of length %v (counted: %v), levelProbabilities %v, and nodes:\n\t[%v]",
s.length, len(strs)-1, s.levelProbabilities, strings.Join(strs, ",\n\t "))
}
func (n *Node) String() string {
strs := make([]string, len(n.nexts))
for idx := 0; idx < len(strs); idx++ {
strs[idx] = fmt.Sprint(n.nexts[idx].Key)
}
return fmt.Sprintf("%v -> %v (nexts: [%v])", n.Key, n.Value, strings.Join(strs, ", "))
}

View File

@@ -0,0 +1,315 @@
package skiplist
import (
"math/rand"
"os"
"strconv"
"testing"
)
type intKey int
func (sk intKey) LessThan(b Comparable) bool {
return sk < b.(intKey)
}
func (sk intKey) Equal(b Comparable) bool {
return sk == b.(intKey)
}
const (
keyValsLen = 1000000
)
var (
rng = rand.New(rand.NewSource(0))
keyVals = make(map[intKey]string)
indices = make([]intKey, keyValsLen)
)
func TestAddFromEmptyRoot(t *testing.T) {
for idx := 0; idx < 10; idx++ {
s := New(rng)
for idy := 0; idy < idx; idy++ {
k := indices[idy]
v := keyVals[k]
n := s.Insert(k, v)
if n.Key != k || n.Value != v {
t.Fatal("Key or Value of inserted pair changed!", k, v, n)
}
if m := s.Get(k); n != m {
t.Fatal("Node changed for just inserted value:", n, m)
}
if s.Len() != uint(idy+1) {
t.Fatal("Incorrect length")
}
}
}
}
func TestAddFromEmptyRel(t *testing.T) {
for idx := 0; idx < 10; idx++ {
s := New(rng)
var n *Node
for idy := 0; idy < idx; idy++ {
k := indices[idy]
v := keyVals[k]
if n == nil {
n = s.Insert(k, v)
} else {
n = n.Insert(k, v)
}
if n.Key != k || n.Value != v {
t.Fatal("Key or Value of inserted pair changed!", k, v, n)
}
if m := n.Get(k); n != m {
t.Fatal("Node changed for just inserted value:", n, m)
}
if p := n.Prev(); p != nil {
if m := p.Get(k); n != m {
t.Fatal("Node changed for just inserted value:", n, m)
}
}
if s.Len() != uint(idy+1) {
t.Fatal("Incorrect length")
}
}
}
}
func TestDupInsert(t *testing.T) {
s := New(rng)
for idx := 0; idx < 10; idx++ {
for idy := 0; idy < idx; idy++ {
k := indices[idy]
v := keyVals[k]
if n := s.Insert(k, v); n.Key != k || n.Value != v {
t.Fatal("Key or Value of inserted pair changed!", k, v, n)
}
}
}
}
func TestGetMissingEmpty(t *testing.T) {
s := New(rng)
for idx := 0; idx < 10; idx++ {
k := indices[idx]
if n := s.Get(k); n != nil {
t.Fatal("Expected not to find elem")
}
}
}
func TestGetMissingNonEmpty(t *testing.T) {
s := New(rng)
for idx := 0; idx < 20; idx++ {
k := indices[idx]
v := keyVals[k]
if idx%2 == 0 {
s.Insert(k, v)
} else {
if n := s.Get(k); n != nil {
t.Fatal("Expected not to find elem")
}
}
}
}
func TestRemoveRoot(t *testing.T) {
s := New(rng)
for idx := 0; idx < 20; idx++ {
k := indices[idx]
v := keyVals[k]
s.Insert(k, v)
}
for idx := 0; idx < 20; idx++ {
k := indices[idx]
v := keyVals[k]
if u := s.Remove(k); u != v {
t.Fatal("Wrong value returned:", u, v)
}
if int(s.Len()) != 19-idx {
t.Fatal("Wrong length")
}
}
}
func TestRemoveSelf(t *testing.T) {
s := New(rng)
ns := []*Node{}
for idx := 0; idx < 20; idx++ {
k := indices[idx]
v := keyVals[k]
ns = append(ns, s.Insert(k, v))
}
for idx, n := range ns {
k := indices[idx]
v := keyVals[k]
if u := n.Remove(); u != v {
t.Fatal("Wrong value returned:", u, v)
}
if int(s.Len()) != len(ns)-idx-1 {
t.Fatal("Wrong length")
}
}
}
func TestRemoveMissing(t *testing.T) {
s := New(rng)
for idx := 0; idx < 20; idx++ {
k := indices[idx]
v := keyVals[k]
s.Insert(k, v)
}
for idx := 0; idx < 20; idx++ {
for idy := 0; idy < idx; idy++ {
k := indices[idy]
v := keyVals[k]
u := s.Remove(k)
if idy+1 == idx {
if u != v {
t.Fatal("Wrong value returned:", u, v)
}
} else {
if u != nil {
t.Fatal("Wrong value returned - expected nil:", u)
}
}
}
}
if s.Len() != 1 {
t.Fatal("Wrong length")
}
}
func TestFirstLast(t *testing.T) {
s := New(rng)
if s.First() != nil || s.Last() != nil {
t.Fatal("Expected nil for First and Last on empty list")
}
var min, max intKey
for idx := 0; idx < 200; idx++ {
k := indices[idx]
v := keyVals[k]
s.Insert(k, v)
if idx == 0 {
min, max = k, k
} else {
if k < min {
min = k
}
if k > max {
max = k
}
}
}
if f := s.First(); f.Key != min {
t.Fatal("Did not get minimum key back for first", min, f)
}
if l := s.Last(); l.Key != max {
t.Fatal("Did not get maximum key back for last", max, l)
}
}
func TestMerge(t *testing.T) {
s0 := New(rng)
s1 := New(rng)
lim := 1000
for idx := 0; idx < lim; idx++ {
if idx%2 == 0 {
s0.Insert(intKey(idx), idx)
} else {
s1.Insert(intKey(idx), idx)
}
}
s0.Merge(s1)
if int(s0.Len()) != lim {
t.Fatal("Wrong len after merge", s0.Len())
}
cur := s0.First()
for idx := 0; idx < lim; idx++ {
if cur.Value.(int) != idx {
t.Fatal("Wrong value: ", cur.Value)
}
if cur != s0.Get(cur.Key) {
t.Fatal("Internal failure: ", cur)
}
cur = cur.Next()
}
}
func TestReposition(t *testing.T) {
s := New(rng)
lim := 200
for idx := 0; idx < lim; idx++ {
s.Insert(intKey(idx*5), idx)
}
for idx := lim - 1; idx >= 0; idx-- {
n := s.Get(intKey(idx * 5))
if n == nil {
t.Fatal("Unable to find node")
}
n.Reposition(intKey((idx * 5) - 11))
}
n := s.First()
for idx := 0; idx < lim; idx++ {
if n.Value != idx {
t.Fatal("Wrong value", idx, n)
}
n = n.Next()
}
if n != nil {
t.Fatal("Too many values!")
}
}
func BenchmarkAdd08192(b *testing.B) { benchmarkAdd(8192, b) }
func BenchmarkAdd16384(b *testing.B) { benchmarkAdd(16384, b) }
func BenchmarkAdd32768(b *testing.B) { benchmarkAdd(32768, b) }
func BenchmarkAdd65536(b *testing.B) { benchmarkAdd(65536, b) }
func benchmarkAdd(initial int, b *testing.B) {
s := populate(New(rng), 0, initial)
b.ResetTimer()
populateFast(s, initial, b.N)
}
func BenchmarkGet08192(b *testing.B) { benchmarkGet(8192, b) }
func BenchmarkGet16384(b *testing.B) { benchmarkGet(16384, b) }
func BenchmarkGet32768(b *testing.B) { benchmarkGet(32768, b) }
func BenchmarkGet65536(b *testing.B) { benchmarkGet(65536, b) }
func benchmarkGet(initial int, b *testing.B) {
s := populate(New(rng), 0, initial)
b.ResetTimer()
for idx := 0; idx < b.N; idx++ {
s.Get(indices[idx%initial])
}
}
func populate(s *SkipList, offset, lim int) *SkipList {
for idx := 0; idx < lim; idx++ {
k := indices[(offset+idx)%len(indices)]
v := keyVals[k]
s.Insert(k, v)
}
return s
}
func populateFast(s *SkipList, offset, lim int) *SkipList {
for idx := 0; idx < lim; idx++ {
n := idx + offset
s.Insert(intKey(n), n)
}
return s
}
func TestMain(m *testing.M) {
for idx := 0; idx < keyValsLen; idx++ {
keyVals[intKey(idx)] = strconv.FormatInt(int64(idx), 3)
}
for idx, k := range rand.Perm(keyValsLen) {
indices[idx] = intKey(k)
}
os.Exit(m.Run())
}

11
experimental/tracer/vendor/manifest vendored Normal file
View File

@@ -0,0 +1,11 @@
{
"version": 0,
"dependencies": [
{
"importpath": "github.com/msackman/skiplist",
"repository": "https://github.com/msackman/skiplist",
"revision": "57733164b18444c51f63e9a80f1693961dde8036",
"branch": "master"
}
]
}