Skip to content

Commit 9c0d93e

Browse files
committed
Use storage.Inuse in compaction and minor fixes in README.md
1 parent 3a74547 commit 9c0d93e

File tree

5 files changed

+25
-28
lines changed

5 files changed

+25
-28
lines changed

README.md

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@
55
Distributed, eventually consistent and in-memory key/value data store and cache. It can be used both as an embedded Go
66
library and as a language-independent service.
77

8+
With Olric, you can instantly create a fast, scalable, shared pool of RAM across a cluster of computers.
9+
810
## At a glance
911

1012
* Designed to share some transient, approximate, fast-changing data between servers,
@@ -88,6 +90,7 @@ Olric is in early stages of development. The package API and client protocol may
8890
* Implements a fast and simple binary protocol,
8991
* Embeddable but can be used as a language-independent service with olricd,
9092
* GC-friendly storage engine,
93+
* O(1) running time for lookups,
9194
* Supports atomic operations,
9295
* Provides a lock implementation which can be used for non-critical purposes,
9396
* Different eviction policies: LRU, MaxIdleDuration and Time-To-Live(TTL),
@@ -96,20 +99,22 @@ Olric is in early stages of development. The package API and client protocol may
9699
* Provides best-effort consistency guarantees without being a complete CP solution,
97100
* Distributes load fairly among cluster members with a [consistent hash function](https://github.com/buraksezer/consistent),
98101
* Supports replication by default(with sync and async options),
102+
* Quorum-based voting for replica control,
103+
* Repairs itself after a network partitioning,
99104
* Thread-safe by default,
100105
* Provides a command-line-interface to access the cluster directly from the terminal,
101-
* Very simple package API,
102-
* Offers a built-in Go client,
103-
* Gob, JSON and MessagePack are supportted by default as serialization format,
104-
* Simplicity as a key concept with a small set of features.
106+
* Supports different serialization formats. Gob, JSON and MessagePack are supported out of the box,
107+
* Provides a locking primitive which inspired by [SETNX of Redis](https://redis.io/commands/setnx#design-pattern-locking-with-codesetnxcode).
108+
109+
See [Architecture](#architecture) section to see details.
105110

106111
## Planned Features
107112

108113
* On-disk persistence mode to work beyond RAM,
109114
* Anti-entropy system to repair inconsistencies in DMaps,
110115
* Publish/Subscribe for messaging,
111116
* Eviction listeners by using Publish/Subscribe,
112-
* Memcache interface,
117+
* Memcached interface,
113118
* Client implementations for different languages: Java, Python and JavaScript,
114119
* REST API.
115120

dmap_eviction.go

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"math/rand"
2020
"runtime"
2121
"sort"
22-
"sync"
2322
"time"
2423

2524
"github.com/buraksezer/olric/internal/storage"
@@ -60,32 +59,22 @@ func (db *Olric) evictKeysAtBackground() {
6059
}
6160

6261
func (db *Olric) evictKeys() {
63-
dmCount := 0
6462
partID := uint64(rand.Intn(int(db.config.PartitionCount)))
6563
part := db.partitions[partID]
66-
var wg sync.WaitGroup
6764
part.m.Range(func(name, tmp interface{}) bool {
6865
dm := tmp.(*dmap)
69-
// Picks 20 dmap instances randomly to check out expired keys. Then waits until all the goroutines done.
70-
dmCount++
71-
if dmCount >= 20 {
72-
return false
73-
}
74-
wg.Add(1)
75-
go db.scanDMapForEviction(partID, name.(string), dm, &wg)
66+
db.scanDMapForEviction(partID, name.(string), dm)
7667
return true
7768
})
78-
wg.Wait()
7969
}
8070

81-
func (db *Olric) scanDMapForEviction(partID uint64, name string, dm *dmap, wg *sync.WaitGroup) {
71+
func (db *Olric) scanDMapForEviction(partID uint64, name string, dm *dmap) {
8272
/*
8373
From Redis Docs:
8474
1- Test 20 random keys from the set of keys with an associated expire.
8575
2- Delete all the keys found expired.
8676
3- If more than 25% of keys were expired, start again from step 1.
8777
*/
88-
defer wg.Done()
8978

9079
// We need limits to prevent CPU starvation. delKeyVal does some network operation
9180
// to delete keys from the backup nodes and the previous owners.

internal/storage/compaction.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ func (s *Storage) CompactTables() bool {
3232
err := fresh.putRaw(hkey, vdata)
3333
if err == errNotEnoughSpace {
3434
// Create a new table and put the new k/v pair in it.
35-
nt := newTable(fresh.allocated * 2)
35+
nt := newTable(s.Inuse() * 2)
3636
s.tables = append(s.tables, nt)
3737
return false
3838
}

internal/storage/storage.go

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (s *Storage) PutRaw(hkey uint64, value []byte) error {
7373
err := t.putRaw(hkey, value)
7474
if err == errNotEnoughSpace {
7575
// Create a new table and put the new k/v pair in it.
76-
nt := newTable(t.inuse * 2)
76+
nt := newTable(s.Inuse() * 2)
7777
s.tables = append(s.tables, nt)
7878
res = ErrFragmented
7979
// try again
@@ -102,7 +102,7 @@ func (s *Storage) Put(hkey uint64, value *VData) error {
102102
err := t.put(hkey, value)
103103
if err == errNotEnoughSpace {
104104
// Create a new table and put the new k/v pair in it.
105-
nt := newTable(t.inuse * 2)
105+
nt := newTable(s.Inuse() * 2)
106106
s.tables = append(s.tables, nt)
107107
res = ErrFragmented
108108
// try again
@@ -229,12 +229,7 @@ func (s *Storage) Delete(hkey uint64) error {
229229
t := s.tables[0]
230230
if float64(t.allocated)*maxGarbageRatio <= float64(t.garbage) {
231231
// Create a new table here.
232-
newSize := t.inuse * 2
233-
if newSize > t.allocated {
234-
// Don't grow up.
235-
newSize = t.allocated
236-
}
237-
nt := newTable(newSize)
232+
nt := newTable(s.Inuse() * 2)
238233
s.tables = append(s.tables, nt)
239234
return ErrFragmented
240235
}

internal/storage/table.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,14 @@ func newTable(size int) *table {
5252
hkeys: make(map[uint64]int),
5353
allocated: size,
5454
}
55+
// From builtin.go:
56+
//
57+
// The size specifies the length. The capacity of the slice is
58+
// equal to its length. A second integer argument may be provided to
59+
// specify a different capacity; it must be no smaller than the
60+
// length. For example, make([]int, 0, 10) allocates an underlying array
61+
// of size 10 and returns a slice of length 0 and capacity 10 that is
62+
// backed by this underlying array.
5563
t.memory = make([]byte, size)
5664
return t
5765
}
@@ -127,7 +135,7 @@ func (t *table) getRaw(hkey uint64) ([]byte, bool) {
127135

128136
// In-memory structure:
129137
// 1 | klen | 8 | 8 | 4 | vlen
130-
// KEY-LENGTH(uint8) | KEY(bytes) | TTL(uint64) | Timestamp(uint64) | VALUE-LENGTH(uint32) | VALUE(bytes)
138+
// KEY-LENGTH(uint8) | KEY(bytes) | TTL(uint64) | Timestamp(uint64) | VALUE-LENGTH(uint32) | VALUE(bytes)
131139
klen := int(uint8(t.memory[end]))
132140
end++ // One byte to keep key length
133141
end += klen // Key length

0 commit comments

Comments
 (0)