public override void MaybePrefetchMemory(List <long> pagesToPrefetch) { if (PlatformDetails.CanPrefetch == false) { return; // not supported } if (pagesToPrefetch.Count == 0) { return; } var entries = new Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY[pagesToPrefetch.Count]; for (int i = 0; i < entries.Length; i++) { entries[i].NumberOfBytes = (IntPtr)(4 * Constants.Storage.PageSize); entries[i].VirtualAddress = AcquirePagePointer(null, pagesToPrefetch[i]); } fixed(Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY *entriesPtr = entries) { Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32Helper.CurrentProcess, (UIntPtr)PagerState.AllocationInfos.Length, entriesPtr, 0); } }
private bool TryAllocateMoreContinuousPages(long allocationSize) { Debug.Assert(PagerState != null); Debug.Assert(PagerState.AllocationInfos != null); Debug.Assert(PagerState.Files != null && PagerState.Files.Any()); var allocationInfo = RemapViewOfFileAtAddress(allocationSize, (ulong)_totalAllocationSize, PagerState.MapBase + _totalAllocationSize); if (allocationInfo == null) { return(false); } PagerState.Files = PagerState.Files.Concat(allocationInfo.MappedFile); PagerState.AllocationInfos = PagerState.AllocationInfos.Concat(allocationInfo); if (PlatformDetails.CanPrefetch) { // We are asking to allocate pages. It is a good idea that they should be already in memory to only cause a single page fault (as they are continuous). Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY entry; entry.VirtualAddress = allocationInfo.BaseAddress; entry.NumberOfBytes = (IntPtr)allocationInfo.Size; Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32Helper.CurrentProcess, (UIntPtr)1, &entry, 0); } return(true); }
public override void TryPrefetchingWholeFile() { if (CanPrefetch == false) { return; // not supported } var entries = stackalloc Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY[PagerState.AllocationInfos.Length]; for (int i = 0; i < PagerState.AllocationInfos.Length; i++) { entries[i].VirtualAddress = PagerState.AllocationInfos[i].BaseAddress; entries[i].NumberOfBytes = (IntPtr)PagerState.AllocationInfos[i].Size; } // We're deliberately ignoring the return value here and not throwing an exception if it returns false. // // This call is merely an optimization that can fail in low-memory conditions. // See https://msdn.microsoft.com/en-us/library/windows/desktop/hh780543(v=vs.85).aspx // // Because of that, and because this call regularly fails on Windows Azure Web Apps (http://issues.hibernatingrhinos.com/issue/RavenDB-4670), // we ignore the return value and don't throw if it fails. Win32MemoryMapNativeMethods.PrefetchVirtualMemory( Win32NativeMethods.GetCurrentProcess(), (UIntPtr)PagerState.AllocationInfos.Length, entries, 0); }
public override void MaybePrefetchMemory(List <long> pagesToPrefetch) { if (CanPrefetch == false) { return; // not supported } if (pagesToPrefetch.Count == 0) { return; } var entries = new Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY[pagesToPrefetch.Count]; for (int i = 0; i < entries.Length; i++) { // We are prefetching 4 pages that with 4Kb pages is 32Kb but the idea is to really get a few consecutive pages to // exploit locality regardless of the page size. entries[i].NumberOfBytes = (IntPtr)(4 * PageSize); entries[i].VirtualAddress = AcquirePagePointer(null, pagesToPrefetch[i]); } fixed(Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY *entriesPtr = entries) { Win32MemoryMapNativeMethods.PrefetchVirtualMemory(_currentProcess, (UIntPtr)PagerState.AllocationInfos.Length, entriesPtr, 0); } }
public override byte *AcquirePagePointer(IPagerLevelTransactionState tx, long pageNumber, PagerState pagerState = null) { // We need to decide what pager we are going to use right now or risk inconsistencies when performing prefetches from disk. var state = pagerState ?? _pagerState; if (PlatformDetails.CanPrefetch) { if (this._pagerState.ShouldPrefetchSegment(pageNumber, out void *virtualAddress, out long bytes)) { Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY entry; entry.NumberOfBytes = (IntPtr)bytes; entry.VirtualAddress = virtualAddress; Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32Helper.CurrentProcess, (UIntPtr)1, &entry, 0); } } return(base.AcquirePagePointer(tx, pageNumber, state)); }
public override void MaybePrefetchMemory(List <TreePage> sortedPages) { if (Sparrow.Platform.CanPrefetch == false) { return; // not supported } if (sortedPages.Count == 0) { return; } var ranges = SortedPagesToList(sortedPages); fixed(Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY *entries = ranges.ToArray()) { Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32Helper.CurrentProcess, (UIntPtr)ranges.Count, entries, 0); } }
public override void TryPrefetchingWholeFile() { if (CanPrefetch == false) { return; // not supported } var entries = stackalloc Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY[PagerState.AllocationInfos.Length]; for (int i = 0; i < PagerState.AllocationInfos.Length; i++) { entries[i].VirtualAddress = PagerState.AllocationInfos[i].BaseAddress; entries[i].NumberOfBytes = (IntPtr)PagerState.AllocationInfos[i].Size; } if (Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32NativeMethods.GetCurrentProcess(), (UIntPtr)PagerState.AllocationInfos.Length, entries, 0) == false) { throw new Win32Exception(); } }
public override void TryPrefetchingWholeFile() { if (PlatformDetails.CanPrefetch == false) { return; // not supported } var pagerState = PagerState; var entries = stackalloc Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY[pagerState.AllocationInfos.Length]; for (var i = 0; i < pagerState.AllocationInfos.Length; i++) { entries[i].VirtualAddress = pagerState.AllocationInfos[i].BaseAddress; entries[i].NumberOfBytes = (IntPtr)pagerState.AllocationInfos[i].Size; } if (Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32Helper.CurrentProcess, (UIntPtr)pagerState.AllocationInfos.Length, entries, 0) == false) { throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to Prefetch Vitrual Memory of file " + FileName); } }
protected internal override unsafe void PrefetchRanges(Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY *list, int count) { Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32Helper.CurrentProcess, (UIntPtr)count, list, 0); }
public override void MaybePrefetchMemory(List <Page> sortedPages) { if (sortedPages.Count == 0) { return; } if (IsWindows8OrNewer() == false) { return; // not supported } var list = new List <Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY>(); long lastPage = -1; const int numberOfPagesInBatch = 8; int sizeInPages = numberOfPagesInBatch; // OS uses 32K when you touch a page, let us reuse this foreach (var page in sortedPages) { if (lastPage == -1) { lastPage = page.PageNumber; } var numberOfPagesInLastPage = page.IsOverflow == false ? 1 : GetNumberOfOverflowPages(page.OverflowSize); var endPage = page.PageNumber + numberOfPagesInLastPage - 1; if (endPage <= lastPage + sizeInPages) { continue; // already within the allocation granularity we have } if (page.PageNumber <= lastPage + sizeInPages + numberOfPagesInBatch) { while (endPage > lastPage + sizeInPages) { sizeInPages += numberOfPagesInBatch; } continue; } list.Add(new Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY { NumberOfBytes = (IntPtr)(sizeInPages * AbstractPager.PageSize), VirtualAddress = AcquirePagePointer(lastPage) }); lastPage = page.PageNumber; sizeInPages = numberOfPagesInBatch; while (endPage > lastPage + sizeInPages) { sizeInPages += numberOfPagesInBatch; } } list.Add(new Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY { NumberOfBytes = (IntPtr)(sizeInPages * PageSize), VirtualAddress = AcquirePagePointer(lastPage) }); fixed(Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY *entries = list.ToArray()) { Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32NativeMethods.GetCurrentProcess(), (UIntPtr)list.Count, entries, 0); } }