Skip to content

Commit

Permalink
add v2, a new version built with generics
Browse files Browse the repository at this point in the history
  • Loading branch information
edwingeng committed Jun 3, 2022
1 parent b699e78 commit 6e0b66e
Show file tree
Hide file tree
Showing 10 changed files with 1,391 additions and 11 deletions.
20 changes: 11 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
# Overview
Deque is a highly optimized double-ended queue.

**Please use [v2](v2/README.md), the generic version, if you have golang 1.18 or above.**

# Benchmark
```
PushBack/Deque<harden> 100000000 10.3 ns/op 9 B/op 0 allocs/op
PushBack/Deque 20000000 81.3 ns/op 24 B/op 1 allocs/op
PushBack/list.List 5000000 281 ns/op 56 B/op 2 allocs/op
PushBack/Deque<harden> 100000000 12.0 ns/op 8 B/op 0 allocs/op
PushBack/Deque 20000000 55.5 ns/op 24 B/op 1 allocs/op
PushBack/list.List 5000000 158.7 ns/op 56 B/op 1 allocs/op
PushFront/Deque<harden> 195840157 8.0 ns/op 9 B/op 0 allocs/op
PushFront/Deque 30000000 70.6 ns/op 24 B/op 1 allocs/op
PushFront/list.List 5000000 276 ns/op 56 B/op 2 allocs/op
PushFront/Deque<harden> 195840157 9.2 ns/op 8 B/op 0 allocs/op
PushFront/Deque 30000000 49.2 ns/op 24 B/op 1 allocs/op
PushFront/list.List 5000000 159.2 ns/op 56 B/op 1 allocs/op
Random/Deque<harden> 65623633 17.3 ns/op 0 B/op 0 allocs/op
Random/Deque 50000000 32.1 ns/op 4 B/op 0 allocs/op
Random/list.List 30000000 123 ns/op 28 B/op 1 allocs/op
Random/Deque<harden> 65623633 15.1 ns/op 0 B/op 0 allocs/op
Random/Deque 50000000 24.7 ns/op 4 B/op 0 allocs/op
Random/list.List 30000000 46.9 ns/op 28 B/op 1 allocs/op
```

# Usage
Expand Down
6 changes: 6 additions & 0 deletions deque.go
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,9 @@ func (dq *deque) Range(f func(i int, v Elem) bool) {
func (dq *deque) Peek(idx int) Elem {
i := idx
for _, c := range dq.chunks {
if i < 0 {
break
}
n := c.e - c.s
if i < n {
return c.data[c.s+i]
Expand All @@ -323,6 +326,9 @@ func (dq *deque) Peek(idx int) Elem {
func (dq *deque) Replace(idx int, v Elem) {
i := idx
for _, c := range dq.chunks {
if i < 0 {
break
}
n := c.e - c.s
if i < n {
c.data[c.s+i] = v
Expand Down
4 changes: 2 additions & 2 deletions interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ type Deque interface {
// Range iterates all the values in Deque.
Range(f func(i int, v Elem) bool)

// Peek returns the value at idx
// Peek returns the value at idx.
Peek(idx int) Elem
// Replace replaces the value at idx
// Replace replaces the value at idx.
Replace(idx int, v Elem)
}
42 changes: 42 additions & 0 deletions v2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Overview
Deque is a highly optimized double-ended queue.

# Benchmark
```
PushBack/Deque 20000000 13.6 ns/op 8 B/op 0 allocs/op
PushBack/list.List 5000000 158.7 ns/op 56 B/op 1 allocs/op
PushFront/Deque 30000000 9.8 ns/op 8 B/op 0 allocs/op
PushFront/list.List 5000000 159.2 ns/op 56 B/op 1 allocs/op
Random/Deque 50000000 13.9 ns/op 0 B/op 0 allocs/op
Random/list.List 30000000 46.9 ns/op 28 B/op 1 allocs/op
```

# Usage
``` go
import "github.com/edwingeng/deque/v2"

dq := NewDeque[int]()
dq.PushBack(100)
dq.PushBack(200)
dq.PushBack(300)
for !dq.IsEmpty() {
fmt.Println(dq.PopFront())
}

dq.PushFront(100)
dq.PushFront(200)
dq.PushFront(300)
for i, n := 0, dq.Len(); i < n; i++ {
fmt.Println(dq.PopFront())
}

// Output:
// 100
// 200
// 300
// 300
// 200
// 100
```
80 changes: 80 additions & 0 deletions v2/benchmark_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package deque

import (
"container/list"
"math/rand"
"testing"
)

func BenchmarkPushBack(b *testing.B) {
b.Run("Deque", func(b *testing.B) {
dq := NewDeque[int]()
for i := 0; i < b.N; i++ {
dq.PushBack(i)
}
})
b.Run("list.List", func(b *testing.B) {
lst := list.New()
for i := 0; i < b.N; i++ {
lst.PushBack(i)
}
})
}

func BenchmarkPushFront(b *testing.B) {
b.Run("Deque", func(b *testing.B) {
dq := NewDeque[int]()
for i := 0; i < b.N; i++ {
dq.PushFront(i)
}
})
b.Run("list.List", func(b *testing.B) {
lst := list.New()
for i := 0; i < b.N; i++ {
lst.PushFront(i)
}
})
}

func BenchmarkRandom(b *testing.B) {
const nn = 10000
a := make([]int, nn)
for i := 0; i < nn; i++ {
a[i] = rand.Int()
}

b.Run("Deque", func(b *testing.B) {
dq := NewDeque[int]()
for i := 0; i < b.N; i++ {
switch a[i%nn] % 4 {
case 0:
dq.PushBack(i)
case 1:
dq.PushFront(i)
case 2:
dq.TryPopBack()
case 3:
dq.TryPopFront()
}
}
})
b.Run("list.List", func(b *testing.B) {
lst := list.New()
for i := 0; i < b.N; i++ {
switch a[i%nn] % 4 {
case 0:
lst.PushBack(i)
case 1:
lst.PushFront(i)
case 2:
if v := lst.Back(); v != nil {
lst.Remove(v)
}
case 3:
if v := lst.Front(); v != nil {
lst.Remove(v)
}
}
}
})
}
35 changes: 35 additions & 0 deletions v2/coverage.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
#!/usr/bin/env bash

[[ "$TRACE" ]] && set -x
pushd `dirname "$0"` > /dev/null
trap __EXIT EXIT

colorful=false
tput setaf 7 > /dev/null 2>&1
if [[ $? -eq 0 ]]; then
colorful=true
fi

function __EXIT() {
popd > /dev/null
}

function printError() {
$colorful && tput setaf 1
>&2 echo "Error: $@"
$colorful && tput setaf 7
}

function printImportantMessage() {
$colorful && tput setaf 3
>&2 echo "$@"
$colorful && tput setaf 7
}

function printUsage() {
$colorful && tput setaf 3
>&2 echo "$@"
$colorful && tput setaf 7
}

go test -cover -coverprofile=c.out -v "$@" && go tool cover -html=c.out
Loading

0 comments on commit 6e0b66e

Please sign in to comment.