// +build !appengine,!windows package fastcache import ( "fmt" "sync" "unsafe" "golang.org/x/sys/unix" ) const chunksPerAlloc = 1024 var ( freeChunks []*[chunkSize]byte freeChunksLock sync.Mutex ) func getChunk() []byte { freeChunksLock.Lock() if len(freeChunks) == 0 { // Allocate offheap memory, so GOGC won't take into account cache size. // This should reduce free memory waste. data, err := unix.Mmap(-1, 0, chunkSize*chunksPerAlloc, unix.PROT_READ|unix.PROT_WRITE, unix.MAP_ANON|unix.MAP_PRIVATE) if err != nil { panic(fmt.Errorf("cannot allocate %d bytes via mmap: %s", chunkSize*chunksPerAlloc, err)) } for len(data) > 0 { p := (*[chunkSize]byte)(unsafe.Pointer(&data[0])) freeChunks = append(freeChunks, p) data = data[chunkSize:] } } n := len(freeChunks) - 1 p := freeChunks[n] freeChunks[n] = nil freeChunks = freeChunks[:n] freeChunksLock.Unlock() return p[:] } func putChunk(chunk []byte) { if chunk == nil { return } chunk = chunk[:chunkSize] p := (*[chunkSize]byte)(unsafe.Pointer(&chunk[0])) freeChunksLock.Lock() freeChunks = append(freeChunks, p) freeChunksLock.Unlock() }