mirror of
https://github.com/seaweedfs/seaweedfs.git
synced 2024-01-19 02:48:24 +00:00
Virtual lock memory pages and Set Process Working set size to hint to windows harder not to write pages to disk as much, add finalize function, minor renaming
This commit is contained in:
parent
d757ed2fe3
commit
9c9dff7386
|
@ -5,6 +5,7 @@ package memory_map
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"runtime"
|
||||||
"syscall"
|
"syscall"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
|
@ -33,32 +34,41 @@ type DWORD = uint32
|
||||||
type WORD = uint16
|
type WORD = uint16
|
||||||
|
|
||||||
var (
|
var (
|
||||||
procGetSystemInfo = syscall.NewLazyDLL("kernel32.dll").NewProc("GetSystemInfo")
|
modkernel32 = syscall.NewLazyDLL("kernel32.dll")
|
||||||
|
|
||||||
|
procGetSystemInfo = modkernel32.NewProc("GetSystemInfo")
|
||||||
|
procGetProcessWorkingSetSize = modkernel32.NewProc("GetProcessWorkingSetSize")
|
||||||
|
procSetProcessWorkingSetSize = modkernel32.NewProc("SetProcessWorkingSetSize")
|
||||||
)
|
)
|
||||||
|
|
||||||
var system_info, err = getSystemInfo()
|
var currentProcess, _ = windows.GetCurrentProcess()
|
||||||
|
var currentMinWorkingSet uint64 = 0
|
||||||
|
var currentMaxWorkingSet uint64 = 0
|
||||||
|
var _ = getProcessWorkingSetSize(uintptr(currentProcess), ¤tMinWorkingSet, ¤tMaxWorkingSet)
|
||||||
|
|
||||||
var chunk_size = uint64(system_info.dwAllocationGranularity) * 256
|
var systemInfo, _ = getSystemInfo()
|
||||||
|
var chunkSize = uint64(systemInfo.dwAllocationGranularity) * 256
|
||||||
|
|
||||||
func (mMap *MemoryMap) CreateMemoryMap(file *os.File, maxlength uint64) {
|
func (mMap *MemoryMap) CreateMemoryMap(file *os.File, maxLength uint64) {
|
||||||
|
|
||||||
chunks := (maxlength / chunk_size)
|
chunks := (maxLength / chunkSize)
|
||||||
if chunks*chunk_size < maxlength {
|
if chunks*chunkSize < maxLength {
|
||||||
chunks = chunks + 1
|
chunks = chunks + 1
|
||||||
}
|
}
|
||||||
|
|
||||||
alignedMaxLength := chunks * chunk_size
|
alignedMaxLength := chunks * chunkSize
|
||||||
|
|
||||||
maxlength_high := uint32(alignedMaxLength >> 32)
|
maxLength_high := uint32(alignedMaxLength >> 32)
|
||||||
maxlength_low := uint32(alignedMaxLength & 0xFFFFFFFF)
|
maxLength_low := uint32(alignedMaxLength & 0xFFFFFFFF)
|
||||||
file_memory_map_handle, err := windows.CreateFileMapping(windows.Handle(file.Fd()), nil, windows.PAGE_READWRITE, maxlength_high, maxlength_low, nil)
|
file_memory_map_handle, err := windows.CreateFileMapping(windows.Handle(file.Fd()), nil, windows.PAGE_READWRITE, maxLength_high, maxLength_low, nil)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
mMap.File = file
|
mMap.File = file
|
||||||
mMap.file_memory_map_handle = uintptr(file_memory_map_handle)
|
mMap.file_memory_map_handle = uintptr(file_memory_map_handle)
|
||||||
mMap.write_map_views = make([]MemoryBuffer, 0, alignedMaxLength/chunk_size)
|
mMap.write_map_views = make([]MemoryBuffer, 0, alignedMaxLength/chunkSize)
|
||||||
mMap.max_length = alignedMaxLength
|
mMap.max_length = alignedMaxLength
|
||||||
mMap.End_of_file = -1
|
mMap.End_of_file = -1
|
||||||
|
runtime.SetFinalizer(mMap, mMap.DeleteFileAndMemoryMap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,7 +94,7 @@ func min(x, y uint64) uint64 {
|
||||||
func (mMap *MemoryMap) WriteMemory(offset uint64, length uint64, data []byte) {
|
func (mMap *MemoryMap) WriteMemory(offset uint64, length uint64, data []byte) {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if ((offset+length)/chunk_size)+1 > uint64(len(mMap.write_map_views)) {
|
if ((offset+length)/chunkSize)+1 > uint64(len(mMap.write_map_views)) {
|
||||||
allocateChunk(mMap)
|
allocateChunk(mMap)
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
|
@ -92,19 +102,19 @@ func (mMap *MemoryMap) WriteMemory(offset uint64, length uint64, data []byte) {
|
||||||
}
|
}
|
||||||
|
|
||||||
remaining_length := length
|
remaining_length := length
|
||||||
slice_index := offset / chunk_size
|
sliceIndex := offset / chunkSize
|
||||||
slice_offset := offset - (slice_index * chunk_size)
|
sliceOffset := offset - (sliceIndex * chunkSize)
|
||||||
data_offset := uint64(0)
|
dataOffset := uint64(0)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
write_end := min((remaining_length + slice_offset), chunk_size)
|
writeEnd := min((remaining_length + sliceOffset), chunkSize)
|
||||||
copy(mMap.write_map_views[slice_index].Buffer[slice_offset:write_end], data[data_offset:])
|
copy(mMap.write_map_views[sliceIndex].Buffer[sliceOffset:writeEnd], data[dataOffset:])
|
||||||
remaining_length -= (write_end - slice_offset)
|
remaining_length -= (writeEnd - sliceOffset)
|
||||||
data_offset += (write_end - slice_offset)
|
dataOffset += (writeEnd - sliceOffset)
|
||||||
|
|
||||||
if remaining_length > 0 {
|
if remaining_length > 0 {
|
||||||
slice_index += 1
|
sliceIndex += 1
|
||||||
slice_offset = 0
|
sliceOffset = 0
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -120,8 +130,15 @@ func (mMap *MemoryMap) ReadMemory(offset uint64, length uint64) (MemoryBuffer, e
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mBuffer *MemoryBuffer) ReleaseMemory() {
|
func (mBuffer *MemoryBuffer) ReleaseMemory() {
|
||||||
|
|
||||||
|
currentMinWorkingSet = currentMinWorkingSet - mBuffer.aligned_length
|
||||||
|
currentMaxWorkingSet = currentMaxWorkingSet - mBuffer.aligned_length
|
||||||
|
|
||||||
|
windows.VirtualUnlock(mBuffer.aligned_ptr, uintptr(mBuffer.aligned_length))
|
||||||
windows.UnmapViewOfFile(mBuffer.aligned_ptr)
|
windows.UnmapViewOfFile(mBuffer.aligned_ptr)
|
||||||
|
|
||||||
|
var _ = setProcessWorkingSetSize(uintptr(currentProcess), uintptr(currentMinWorkingSet), uintptr(currentMaxWorkingSet))
|
||||||
|
|
||||||
mBuffer.ptr = 0
|
mBuffer.ptr = 0
|
||||||
mBuffer.aligned_ptr = 0
|
mBuffer.aligned_ptr = 0
|
||||||
mBuffer.length = 0
|
mBuffer.length = 0
|
||||||
|
@ -131,11 +148,12 @@ func (mBuffer *MemoryBuffer) ReleaseMemory() {
|
||||||
|
|
||||||
func allocateChunk(mMap *MemoryMap) {
|
func allocateChunk(mMap *MemoryMap) {
|
||||||
|
|
||||||
start := uint64(len(mMap.write_map_views)) * chunk_size
|
start := uint64(len(mMap.write_map_views)) * chunkSize
|
||||||
mBuffer, err := allocate(windows.Handle(mMap.file_memory_map_handle), start, chunk_size, true)
|
mBuffer, err := allocate(windows.Handle(mMap.file_memory_map_handle), start, chunkSize, true)
|
||||||
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
mMap.write_map_views = append(mMap.write_map_views, mBuffer)
|
mMap.write_map_views = append(mMap.write_map_views, mBuffer)
|
||||||
|
windows.VirtualLock(mBuffer.aligned_ptr, uintptr(mBuffer.aligned_length))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,7 +161,7 @@ func allocate(hMapFile windows.Handle, offset uint64, length uint64, write bool)
|
||||||
|
|
||||||
mBuffer := MemoryBuffer{}
|
mBuffer := MemoryBuffer{}
|
||||||
|
|
||||||
dwSysGran := system_info.dwAllocationGranularity
|
dwSysGran := systemInfo.dwAllocationGranularity
|
||||||
|
|
||||||
start := (offset / uint64(dwSysGran)) * uint64(dwSysGran)
|
start := (offset / uint64(dwSysGran)) * uint64(dwSysGran)
|
||||||
diff := offset - start
|
diff := offset - start
|
||||||
|
@ -158,6 +176,11 @@ func allocate(hMapFile windows.Handle, offset uint64, length uint64, write bool)
|
||||||
access = windows.FILE_MAP_WRITE
|
access = windows.FILE_MAP_WRITE
|
||||||
}
|
}
|
||||||
|
|
||||||
|
currentMinWorkingSet = currentMinWorkingSet + aligned_length
|
||||||
|
currentMaxWorkingSet = currentMaxWorkingSet + aligned_length
|
||||||
|
|
||||||
|
var _ = setProcessWorkingSetSize(uintptr(currentProcess), uintptr(currentMinWorkingSet), uintptr(currentMaxWorkingSet))
|
||||||
|
|
||||||
addr_ptr, errno := windows.MapViewOfFile(hMapFile,
|
addr_ptr, errno := windows.MapViewOfFile(hMapFile,
|
||||||
uint32(access), // read/write permission
|
uint32(access), // read/write permission
|
||||||
offset_high,
|
offset_high,
|
||||||
|
@ -227,3 +250,35 @@ func getSystemInfo() (_SYSTEM_INFO, error) {
|
||||||
}
|
}
|
||||||
return si, nil
|
return si, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BOOL GetProcessWorkingSetSize(
|
||||||
|
// HANDLE hProcess,
|
||||||
|
// PSIZE_T lpMinimumWorkingSetSize,
|
||||||
|
// PSIZE_T lpMaximumWorkingSetSize
|
||||||
|
// );
|
||||||
|
|
||||||
|
func getProcessWorkingSetSize(process uintptr, dwMinWorkingSet *uint64, dwMaxWorkingSet *uint64) error {
|
||||||
|
r1, _, err := syscall.Syscall(procGetProcessWorkingSetSize.Addr(), 3, process, uintptr(unsafe.Pointer(dwMinWorkingSet)), uintptr(unsafe.Pointer(dwMaxWorkingSet)))
|
||||||
|
if r1 == 0 {
|
||||||
|
if err != syscall.Errno(0) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// BOOL SetProcessWorkingSetSize(
|
||||||
|
// HANDLE hProcess,
|
||||||
|
// SIZE_T dwMinimumWorkingSetSize,
|
||||||
|
// SIZE_T dwMaximumWorkingSetSize
|
||||||
|
// );
|
||||||
|
|
||||||
|
func setProcessWorkingSetSize(process uintptr, dwMinWorkingSet uintptr, dwMaxWorkingSet uintptr) error {
|
||||||
|
r1, _, err := syscall.Syscall(procSetProcessWorkingSetSize.Addr(), 3, process, (dwMinWorkingSet), (dwMaxWorkingSet))
|
||||||
|
if r1 == 0 {
|
||||||
|
if err != syscall.Errno(0) {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue