mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2025-10-21 19:17:46 +08:00
skip bytes cache
This commit is contained in:
@@ -49,8 +49,6 @@ type Needle struct {
|
||||
|
||||
Checksum CRC `comment:"CRC32 to check integrity"`
|
||||
Padding []byte `comment:"Aligned to 8 bytes"`
|
||||
|
||||
rawBlock *Block // underlying supporing []byte, fetched and released into a pool
|
||||
}
|
||||
|
||||
func (n *Needle) String() (str string) {
|
||||
|
@@ -1,80 +1,11 @@
|
||||
package storage
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/hashicorp/golang-lru"
|
||||
|
||||
"github.com/chrislusf/seaweedfs/weed/util"
|
||||
)
|
||||
|
||||
var (
|
||||
EnableBytesCache = true
|
||||
bytesCache *lru.Cache
|
||||
bytesPool *util.BytesPool
|
||||
)
|
||||
|
||||
/*
|
||||
There are one level of caching, and one level of pooling.
|
||||
|
||||
In pooling, all []byte are fetched and returned to the pool bytesPool.
|
||||
|
||||
In caching, the string~[]byte mapping is cached
|
||||
*/
|
||||
func init() {
|
||||
bytesPool = util.NewBytesPool()
|
||||
bytesCache, _ = lru.NewWithEvict(512, func(key interface{}, value interface{}) {
|
||||
value.(*Block).decreaseReference()
|
||||
})
|
||||
}
|
||||
|
||||
type Block struct {
|
||||
Bytes []byte
|
||||
refCount int32
|
||||
}
|
||||
|
||||
func (block *Block) decreaseReference() {
|
||||
if atomic.AddInt32(&block.refCount, -1) == 0 {
|
||||
bytesPool.Put(block.Bytes)
|
||||
}
|
||||
}
|
||||
func (block *Block) increaseReference() {
|
||||
atomic.AddInt32(&block.refCount, 1)
|
||||
}
|
||||
|
||||
// get bytes from the LRU cache of []byte first, then from the bytes pool
|
||||
// when []byte in LRU cache is evicted, it will be put back to the bytes pool
|
||||
func getBytesForFileBlock(r *os.File, offset int64, readSize int) (dataSlice []byte, block *Block, err error) {
|
||||
// check cache, return if found
|
||||
cacheKey := fmt.Sprintf("%d:%d:%d", r.Fd(), offset>>3, readSize)
|
||||
if EnableBytesCache {
|
||||
if obj, found := bytesCache.Get(cacheKey); found {
|
||||
block = obj.(*Block)
|
||||
block.increaseReference()
|
||||
dataSlice = block.Bytes[0:readSize]
|
||||
return dataSlice, block, nil
|
||||
}
|
||||
}
|
||||
|
||||
// get the []byte from pool
|
||||
b := bytesPool.Get(readSize)
|
||||
// refCount = 2, one by the bytesCache, one by the actual needle object
|
||||
block = &Block{Bytes: b, refCount: 2}
|
||||
dataSlice = block.Bytes[0:readSize]
|
||||
func getBytesForFileBlock(r *os.File, offset int64, readSize int) (dataSlice []byte, err error) {
|
||||
dataSlice = make([]byte, readSize)
|
||||
_, err = r.ReadAt(dataSlice, offset)
|
||||
if EnableBytesCache {
|
||||
bytesCache.Add(cacheKey, block)
|
||||
}
|
||||
return dataSlice, block, err
|
||||
}
|
||||
|
||||
func (n *Needle) ReleaseMemory() {
|
||||
if n.rawBlock != nil {
|
||||
n.rawBlock.decreaseReference()
|
||||
}
|
||||
}
|
||||
func ReleaseBytes(b []byte) {
|
||||
bytesPool.Put(b)
|
||||
return dataSlice, err
|
||||
}
|
||||
|
@@ -151,16 +151,15 @@ func (n *Needle) Append(w io.Writer, version Version) (size uint32, actualSize i
|
||||
return 0, 0, fmt.Errorf("Unsupported Version! (%d)", version)
|
||||
}
|
||||
|
||||
func ReadNeedleBlob(r *os.File, offset int64, size uint32) (dataSlice []byte, block *Block, err error) {
|
||||
func ReadNeedleBlob(r *os.File, offset int64, size uint32) (dataSlice []byte, err error) {
|
||||
return getBytesForFileBlock(r, offset, int(getActualSize(size)))
|
||||
}
|
||||
|
||||
func (n *Needle) ReadData(r *os.File, offset int64, size uint32, version Version) (err error) {
|
||||
bytes, block, err := ReadNeedleBlob(r, offset, size)
|
||||
bytes, err := ReadNeedleBlob(r, offset, size)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
n.rawBlock = block
|
||||
n.ParseNeedleHeader(bytes)
|
||||
if n.Size != size {
|
||||
return fmt.Errorf("File Entry Not Found. Needle %d Memory %d", n.Size, size)
|
||||
|
@@ -25,7 +25,6 @@ func (v *Volume) isFileUnchanged(n *Needle) bool {
|
||||
glog.V(0).Infof("Failed to check updated file %v", err)
|
||||
return false
|
||||
}
|
||||
defer oldNeedle.ReleaseMemory()
|
||||
if oldNeedle.Checksum == n.Checksum && bytes.Equal(oldNeedle.Data, n.Data) {
|
||||
n.DataSize = oldNeedle.DataSize
|
||||
return true
|
||||
@@ -172,7 +171,6 @@ func (v *Volume) readNeedle(n *Needle) (int, error) {
|
||||
if uint64(time.Now().Unix()) < n.LastModified+uint64(ttlMinutes*60) {
|
||||
return bytesRead, nil
|
||||
}
|
||||
n.ReleaseMemory()
|
||||
return -1, errors.New("Not Found")
|
||||
}
|
||||
|
||||
|
@@ -178,7 +178,7 @@ func (v *Volume) makeupDiff(newDatFileName, newIdxFileName, oldDatFileName, oldI
|
||||
if incre_idx_entry.offset != 0 && incre_idx_entry.size != 0 {
|
||||
//even the needle cache in memory is hit, the need_bytes is correct
|
||||
var needle_bytes []byte
|
||||
needle_bytes, _, err = ReadNeedleBlob(oldDatFile, int64(incre_idx_entry.offset)*NeedlePaddingSize, incre_idx_entry.size)
|
||||
needle_bytes, err = ReadNeedleBlob(oldDatFile, int64(incre_idx_entry.offset)*NeedlePaddingSize, incre_idx_entry.size)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
@@ -291,7 +291,6 @@ func (v *Volume) copyDataBasedOnIndexFile(dstName, idxName string) (err error) {
|
||||
|
||||
n := new(Needle)
|
||||
n.ReadData(v.dataFile, int64(offset)*NeedlePaddingSize, size, v.Version())
|
||||
defer n.ReleaseMemory()
|
||||
|
||||
if n.HasTtl() && now >= n.LastModified+uint64(v.Ttl.Minutes()*60) {
|
||||
return nil
|
||||
|
Reference in New Issue
Block a user