예제 #1
0
        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);
            }
        }
예제 #2
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);
        }
예제 #3
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;
            }

            // 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);
        }
예제 #4
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);
            }
        }
예제 #5
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();
            }
        }
예제 #8
0
        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);
            }
        }
예제 #9
0
 protected internal override unsafe void PrefetchRanges(Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY *list, int count)
 {
     Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32Helper.CurrentProcess, (UIntPtr)count, list, 0);
 }
예제 #10
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);
            }
        }