Implemented a simple LRU cache with max 256 entries for base tile hasing. TODO: Improve test.

This commit is contained in:
Sascha L. Teichmann 2016-05-10 18:57:14 +02:00
parent 5d1be98ae5
commit 69ee5af388
3 changed files with 89 additions and 8 deletions

View File

@ -48,7 +48,7 @@
<script type="text/javascript" src="js/leaflet.awesome-markers.js"></script> <script type="text/javascript" src="js/leaflet.awesome-markers.js"></script>
<script> <script>
var useWebsocket = false; // Set to true if you want websocket support var useWebsocket = true; // Set to true if you want websocket support
L.Projection.NoWrap = { L.Projection.NoWrap = {
project: function (latlng) { project: function (latlng) {

View File

@ -9,27 +9,81 @@ import (
"sync" "sync"
) )
const btMaxEntries = 256
type btKey struct {
x int
y int
}
type btHashEntry struct {
prev *btHashEntry
next *btHashEntry
hash []byte
btKey
}
type BaseTileHash struct { type BaseTileHash struct {
// XXX: Maybe use some kind of LRU cache instead? hashes map[btKey]*btHashEntry
hashes map[struct{ x, y int }][]byte root btHashEntry
sync.Mutex sync.Mutex
} }
func NewBaseTileHash() *BaseTileHash { func NewBaseTileHash() *BaseTileHash {
return &BaseTileHash{hashes: map[struct{ x, y int }][]byte{}} bth := &BaseTileHash{
hashes: map[btKey]*btHashEntry{}}
bth.root.next = &bth.root
bth.root.prev = &bth.root
return bth
}
func (bth *BaseTileHash) toFront(entry *btHashEntry) {
if bth.root.next == entry {
return
}
entry.prev.next = entry.next
entry.next.prev = entry.prev
entry.next = bth.root.next
entry.prev = &bth.root
bth.root.next = entry
}
func (bth *BaseTileHash) removeLast() *btHashEntry {
last := bth.root.prev
bth.root.prev = last.prev
last.prev.next = &bth.root
delete(bth.hashes, last.btKey)
return last
}
func (bth *BaseTileHash) insertFront(entry *btHashEntry) {
entry.next = bth.root.next
entry.prev = &bth.root
bth.root.next.prev = entry
bth.root.next = entry
} }
func (bth *BaseTileHash) Update(x, y int, hash []byte) bool { func (bth *BaseTileHash) Update(x, y int, hash []byte) bool {
key := struct{ x, y int }{x, y}
bth.Lock() bth.Lock()
defer bth.Unlock() defer bth.Unlock()
key := btKey{x, y}
if old, found := bth.hashes[key]; found { if old, found := bth.hashes[key]; found {
if !bytes.Equal(old, hash) { if !bytes.Equal(old.hash, hash) {
bth.hashes[key] = hash old.hash = hash
bth.toFront(old)
return true return true
} }
return false return false
} }
bth.hashes[key] = hash var entry *btHashEntry
if len(bth.hashes) >= btMaxEntries {
entry = bth.removeLast()
} else {
entry = new(btHashEntry)
}
entry.btKey = key
entry.hash = hash
bth.hashes[key] = entry
bth.insertFront(entry)
return true return true
} }

View File

@ -0,0 +1,27 @@
// Copyright 2016 by Sascha L. Teichmann
// Use of this source code is governed by the MIT license
// that can be found in the LICENSE file.
package common
import "testing"
func TestBaseTileHash(t *testing.T) {
bth := NewBaseTileHash()
h1 := []byte{1}
h2 := []byte{2}
for i := 0; i < 600; i++ {
x := i % 200
for j := 0; j < 600; j++ {
y := j % 200
var h []byte
if j%2 == 0 {
h = h1
} else {
h = h2
}
_ = bth.Update(x, y, h)
}
}
t.Logf("size: %d\n", len(bth.hashes))
}