mirror of
https://bitbucket.org/s_l_teichmann/mtsatellite
synced 2024-12-23 16:50:18 +01:00
Re-worked memory management of blocks loaded from redis client to avoid
unnecessary copying them around.
This commit is contained in:
parent
4a3fa1f568
commit
91959685f5
@ -105,14 +105,21 @@ func main() {
|
|||||||
|
|
||||||
renderer := common.NewRenderer(width, height, transparent)
|
renderer := common.NewRenderer(width, height, transparent)
|
||||||
renderer.SetPos(q1x, q1z)
|
renderer.SetPos(q1x, q1z)
|
||||||
yOrder := common.NewYOrder(renderer, 512)
|
|
||||||
|
renderFn := func(block *common.Block) error {
|
||||||
|
return renderer.RenderBlock(block, colors)
|
||||||
|
}
|
||||||
|
|
||||||
|
yOrder := common.NewYOrder(renderFn, 512)
|
||||||
|
|
||||||
numBlocks := 0
|
numBlocks := 0
|
||||||
drawBlock := func(block *common.Block) {
|
drawBlock := func(block *common.Block) *common.Block {
|
||||||
if err := yOrder.RenderBlock(block, colors); err != nil {
|
block, err := yOrder.RenderBlock(block)
|
||||||
|
if err != nil {
|
||||||
log.Printf("WARN: rendering block failed: %s\n", err)
|
log.Printf("WARN: rendering block failed: %s\n", err)
|
||||||
}
|
}
|
||||||
numBlocks++
|
numBlocks++
|
||||||
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
c1 := common.Coord{X: q1x, Z: q1z}
|
c1 := common.Coord{X: q1x, Z: q1z}
|
||||||
@ -126,7 +133,7 @@ func main() {
|
|||||||
if _, err = client.QueryCuboid(cuboid, drawBlock); err != nil {
|
if _, err = client.QueryCuboid(cuboid, drawBlock); err != nil {
|
||||||
log.Fatalf("query failed: %s", err)
|
log.Fatalf("query failed: %s", err)
|
||||||
}
|
}
|
||||||
if err = yOrder.Drain(colors); err != nil {
|
if err = yOrder.Drain(); err != nil {
|
||||||
log.Printf("WARN: rendering block failed: %s\n", err)
|
log.Printf("WARN: rendering block failed: %s\n", err)
|
||||||
}
|
}
|
||||||
if renderer.IsFilled() {
|
if renderer.IsFilled() {
|
||||||
|
@ -97,10 +97,12 @@ func (btc *BaseTileCreator) renderBlock(block *Block) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// blockLoaded is a callback for RedisClient.QueryCuboid.
|
// blockLoaded is a callback for RedisClient.QueryCuboid.
|
||||||
func (btc *BaseTileCreator) blockLoaded(block *Block) {
|
func (btc *BaseTileCreator) blockLoaded(block *Block) *Block {
|
||||||
if err := btc.yOrder.RenderBlock(block); err != nil {
|
block, err := btc.yOrder.RenderBlock(block)
|
||||||
|
if err != nil {
|
||||||
log.Printf("WARN: rendering block failed: %s\n", err)
|
log.Printf("WARN: rendering block failed: %s\n", err)
|
||||||
}
|
}
|
||||||
|
return block
|
||||||
}
|
}
|
||||||
|
|
||||||
func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) (bool, error) {
|
func (btc *BaseTileCreator) CreateTile(x, z int16, i, j int) (bool, error) {
|
||||||
|
@ -11,13 +11,13 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
|
||||||
"unicode"
|
"unicode"
|
||||||
)
|
)
|
||||||
|
|
||||||
type RedisClient struct {
|
type RedisClient struct {
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
reader *bufio.Reader
|
reader *bufio.Reader
|
||||||
|
arena []byte
|
||||||
scratch [80]byte
|
scratch [80]byte
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,6 +89,16 @@ func parseSize(line []byte) (int, error) {
|
|||||||
return int(v), err
|
return int(v), err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (client *RedisClient) alloc(size int) []byte {
|
||||||
|
a := client.arena
|
||||||
|
if len(a) < size {
|
||||||
|
a = make([]byte, Max(size, 16*1024))
|
||||||
|
}
|
||||||
|
x := a[:size:size]
|
||||||
|
client.arena = a[size:]
|
||||||
|
return x
|
||||||
|
}
|
||||||
|
|
||||||
func (client *RedisClient) readBulkString(data *[]byte) (size int, err error) {
|
func (client *RedisClient) readBulkString(data *[]byte) (size int, err error) {
|
||||||
var line []byte
|
var line []byte
|
||||||
if line, err = client.reader.ReadBytes('\n'); err != nil {
|
if line, err = client.reader.ReadBytes('\n'); err != nil {
|
||||||
@ -101,7 +111,9 @@ func (client *RedisClient) readBulkString(data *[]byte) (size int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if cap(*data) < size {
|
if cap(*data) < size {
|
||||||
*data = make([]byte, size)
|
*data = client.alloc(size)
|
||||||
|
} else {
|
||||||
|
*data = (*data)[:size]
|
||||||
}
|
}
|
||||||
for rest := size; rest > 0; {
|
for rest := size; rest > 0; {
|
||||||
var n int
|
var n int
|
||||||
@ -114,26 +126,18 @@ func (client *RedisClient) readBulkString(data *[]byte) (size int, err error) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var dataPool = sync.Pool{
|
func (client *RedisClient) QueryCuboid(cuboid Cuboid, fn func(*Block) *Block) (count int, err error) {
|
||||||
New: func() interface{} {
|
|
||||||
return make([]byte, 8*1024)
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func (client *RedisClient) QueryCuboid(cuboid Cuboid, fn func(*Block)) (count int, err error) {
|
|
||||||
p1 := CoordToPlain(cuboid.P1)
|
p1 := CoordToPlain(cuboid.P1)
|
||||||
p2 := CoordToPlain(cuboid.P2)
|
p2 := CoordToPlain(cuboid.P2)
|
||||||
if err = client.writeHSpatial(p1, p2); err != nil {
|
if err = client.writeHSpatial(p1, p2); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
data := dataPool.Get().([]byte)
|
|
||||||
defer dataPool.Put(data[:0])
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
block = Block{}
|
block *Block
|
||||||
size int
|
size int
|
||||||
key int64
|
key int64
|
||||||
|
data []byte
|
||||||
)
|
)
|
||||||
|
|
||||||
for s := client.scratch[:]; ; count++ {
|
for s := client.scratch[:]; ; count++ {
|
||||||
@ -144,15 +148,22 @@ func (client *RedisClient) QueryCuboid(cuboid Cuboid, fn func(*Block)) (count in
|
|||||||
if size <= 0 {
|
if size <= 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if key, err = DecodeStringFromBytes((*p)[:size]); err != nil {
|
if key, err = DecodeStringFromBytes(*p); err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
block.Coord = PlainToCoord(key)
|
|
||||||
if size, err = client.readBulkString(&data); err != nil || size < 0 {
|
if size, err = client.readBulkString(&data); err != nil || size < 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
block.Data = data[:size]
|
if block == nil {
|
||||||
fn(&block)
|
block = &Block{Coord: PlainToCoord(key), Data: data}
|
||||||
|
} else {
|
||||||
|
*block = Block{Coord: PlainToCoord(key), Data: data}
|
||||||
|
}
|
||||||
|
if block = fn(block); block != nil {
|
||||||
|
data = block.Data[:0]
|
||||||
|
} else {
|
||||||
|
data = nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return
|
return
|
||||||
|
@ -43,40 +43,23 @@ func (yo *YOrder) Reset() {
|
|||||||
yo.blocks = blocks[:0]
|
yo.blocks = blocks[:0]
|
||||||
}
|
}
|
||||||
|
|
||||||
func copyData(data []byte) []byte {
|
func (yo *YOrder) RenderBlock(block *Block) (*Block, error) {
|
||||||
l := len(data)
|
|
||||||
ndata := make([]byte, l, Max(l, 8*1024))
|
|
||||||
copy(ndata, data)
|
|
||||||
return ndata
|
|
||||||
}
|
|
||||||
|
|
||||||
func (yo *YOrder) RenderBlock(block *Block) (err error) {
|
|
||||||
var nblock *Block
|
|
||||||
if len(yo.blocks) == yo.capacity {
|
if len(yo.blocks) == yo.capacity {
|
||||||
oblock := yo.blocks[0]
|
oblock := yo.blocks[0]
|
||||||
if oblock.Coord.Y < block.Coord.Y {
|
if oblock.Coord.Y < block.Coord.Y {
|
||||||
// New one is above highest old. Directly render new.
|
// New one is above highest old. Directly render new.
|
||||||
err = yo.RenderFn(block)
|
err := yo.RenderFn(block)
|
||||||
return
|
return block, err
|
||||||
}
|
}
|
||||||
// Render old one. Store copy of new in heap.
|
// Render old one. Store copy of new in heap.
|
||||||
heap.Pop(yo)
|
heap.Pop(yo)
|
||||||
err = yo.RenderFn(oblock)
|
heap.Push(yo, block)
|
||||||
l := len(block.Data)
|
err := yo.RenderFn(oblock)
|
||||||
if cap(oblock.Data) < l {
|
return oblock, err
|
||||||
oblock.Data = make([]byte, l, Max(l, 8*1024))
|
|
||||||
} else {
|
|
||||||
oblock.Data = oblock.Data[:l]
|
|
||||||
}
|
|
||||||
copy(oblock.Data, block.Data)
|
|
||||||
oblock.Coord = block.Coord
|
|
||||||
nblock = oblock
|
|
||||||
} else {
|
|
||||||
nblock = &Block{Coord: block.Coord, Data: copyData(block.Data)}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
heap.Push(yo, nblock)
|
heap.Push(yo, block)
|
||||||
return
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (yo *YOrder) Drain() error {
|
func (yo *YOrder) Drain() error {
|
||||||
|
Loading…
Reference in New Issue
Block a user