Ejemplo n.º 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);
            }
        }
Ejemplo n.º 2
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);
            }
        }
Ejemplo n.º 3
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);
        }
Ejemplo n.º 4
0
 public override void ReleaseAllocationInfo(byte *baseAddress, long size)
 {
     if (Win32MemoryMapNativeMethods.UnmapViewOfFile(baseAddress) == false)
     {
         throw new Win32Exception();
     }
 }
Ejemplo n.º 5
0
        public override void Sync()
        {
            if (Disposed)
            {
                ThrowAlreadyDisposedException();
            }

            var currentState = GetPagerStateAndAddRefAtomically();

            try
            {
                using (var metric = Options.IoMetrics.MeterIoRate(FileName, IoMetrics.MeterType.DataSync, 0))
                {
                    foreach (var allocationInfo in currentState.AllocationInfos)
                    {
                        metric.IncrementSize(allocationInfo.Size);
                        if (
                            Win32MemoryMapNativeMethods.FlushViewOfFile(allocationInfo.BaseAddress,
                                                                        new IntPtr(allocationInfo.Size)) == false)
                        {
                            throw new Win32Exception();
                        }
                    }

                    if (Win32MemoryMapNativeMethods.FlushFileBuffers(_handle) == false)
                    {
                        throw new Win32Exception();
                    }
                }
            }
            finally
            {
                currentState.Release();
            }
        }
        private PagerState.AllocationInfo TryCreateNewFileMappingAtAddress(long allocationSize, byte *baseAddress)
        {
            var newMemoryMappedFile   = MemoryMappedFile.CreateNew(null, allocationSize);
            var newFileMappingHandle  = newMemoryMappedFile.SafeMemoryMappedFileHandle.DangerousGetHandle();
            var newMappingBaseAddress = Win32MemoryMapNativeMethods.MapViewOfFileEx(newFileMappingHandle,
                                                                                    Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read |
                                                                                    Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write,
                                                                                    0, 0,
                                                                                    UIntPtr.Zero,
                                                                                    baseAddress);

            var hasMappingSucceeded = newMappingBaseAddress != null && newMappingBaseAddress != (byte *)0;

            if (!hasMappingSucceeded)
            {
                newMemoryMappedFile.Dispose();
                return(null);
            }

            return(new PagerState.AllocationInfo
            {
                BaseAddress = newMappingBaseAddress,
                Size = allocationSize,
                MappedFile = newMemoryMappedFile
            });
        }
Ejemplo n.º 7
0
        private PagerState.AllocationInfo RemapViewOfFileAtAddress(long allocationSize, ulong offsetInFile, byte *baseAddress)
        {
            var offset = new SplitValue {
                Value = offsetInFile
            };

            var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length,
                                                      _memoryMappedFileAccess,
                                                      null, HandleInheritability.None, true);

            var newMappingBaseAddress = Win32MemoryMapNativeMethods.MapViewOfFileEx(mmf.SafeMemoryMappedFileHandle.DangerousGetHandle(),
                                                                                    Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read | Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write,
                                                                                    offset.High, offset.Low,
                                                                                    new UIntPtr((ulong)allocationSize),
                                                                                    baseAddress);

            var hasMappingSucceeded = newMappingBaseAddress != null && newMappingBaseAddress != (byte *)0;

            if (!hasMappingSucceeded)
            {
                mmf.Dispose();
                return(null);
            }

            return(new PagerState.AllocationInfo
            {
                BaseAddress = newMappingBaseAddress,
                Size = allocationSize,
                MappedFile = mmf
            });
        }
 private static void UndoMappings(IEnumerable <PagerState.AllocationInfo> newAllocationInfos)
 {
     foreach (var newAllocationInfo in newAllocationInfos)
     {
         Win32MemoryMapNativeMethods.UnmapViewOfFile(newAllocationInfo.BaseAddress);
     }
 }
Ejemplo n.º 9
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);
        }
Ejemplo n.º 10
0
        private PagerState CreatePagerState()
        {
            var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length,
                                                      _memoryMappedFileAccess,
                                                      HandleInheritability.None, true);

            var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle();

            Win32MemoryMapNativeMethods.NativeFileMapAccessType mmFileAccessType;
            if (_copyOnWriteMode)
            {
                mmFileAccessType = Win32MemoryMapNativeMethods.NativeFileMapAccessType.Copy;
            }
            else
            {
                mmFileAccessType = _access == Win32NativeFileAccess.GenericRead
                    ? Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read
                    : Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read |
                                   Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write;
            }
            var startingBaseAddressPtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle,
                                                                                     mmFileAccessType,
                                                                                     0, 0,
                                                                                     UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row
                                                                                     null);


            if (startingBaseAddressPtr == (byte *)0) //system didn't succeed in mapping the address where we wanted
            {
                var innerException = new Win32Exception(Marshal.GetLastWin32Error(), "Failed to MapView of file " + FileName);

                var errorMessage = string.Format(
                    "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of virtual memory with size = {0:##,###;;0} bytes",
                    (_fileStream.Length));

                throw new OutOfMemoryException(errorMessage, innerException);
            }

            NativeMemory.RegisterFileMapping(_fileInfo.FullName, new IntPtr(startingBaseAddressPtr), _fileStream.Length);

            // If we are working on memory validation mode, then protect the pages by default.
            ProtectPageRange(startingBaseAddressPtr, (ulong)_fileStream.Length);

            var allocationInfo = new PagerState.AllocationInfo
            {
                BaseAddress = startingBaseAddressPtr,
                Size        = _fileStream.Length,
                MappedFile  = mmf
            };

            var newPager = new PagerState(this)
            {
                Files           = new[] { mmf },
                MapBase         = startingBaseAddressPtr,
                AllocationInfos = new[] { allocationInfo }
            };

            return(newPager);
        }
Ejemplo n.º 11
0
 public override void ReleaseAllocationInfo(byte *baseAddress, long size)
 {
     if (Win32MemoryMapNativeMethods.UnmapViewOfFile(baseAddress) == false)
     {
         throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to UnMapView of file " + FileName);
     }
     NativeMemory.UnregisterFileMapping(_fileInfo.FullName, new IntPtr(baseAddress), size);
 }
Ejemplo n.º 12
0
 public override void ReleaseAllocationInfo(byte *baseAddress, long size)
 {
     if (Win32MemoryMapNativeMethods.UnmapViewOfFile(baseAddress) == false)
     {
         throw new Win32Exception();
     }
     NativeMemory.UnregisterFileMapping(_fileInfo.FullName, new IntPtr(baseAddress), size);
 }
Ejemplo n.º 13
0
        public override void Sync()
        {
            ThrowObjectDisposedIfNeeded();

            if (PagerState.AllocationInfos.Any(allocationInfo =>
                                               Win32MemoryMapNativeMethods.FlushViewOfFile(allocationInfo.BaseAddress, new IntPtr(allocationInfo.Size)) == false))
            {
                throw new Win32Exception();
            }

            if (Win32MemoryMapNativeMethods.FlushFileBuffers(_handle) == false)
            {
                throw new Win32Exception();
            }
        }
Ejemplo n.º 14
0
        private PagerState CreatePagerState()
        {
            var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length,
                                                      _memoryMappedFileAccess,
                                                      HandleInheritability.None, true);

            var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle();
            var mmFileAccessType  = _access == Win32NativeFileAccess.GenericRead
                ? Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read
                    : Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read | Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write;

            var startingBaseAddressPtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle,
                                                                                     mmFileAccessType,
                                                                                     0, 0,
                                                                                     UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row
                                                                                     null);


            if (startingBaseAddressPtr == (byte *)0) //system didn't succeed in mapping the address where we wanted
            {
                var innerException = new Win32Exception();

                var errorMessage = string.Format(
                    "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of virtual memory with size = {0:##,###;;0} bytes",
                    (_fileStream.Length));

                throw new OutOfMemoryException(errorMessage, innerException);
            }

            var allocationInfo = new PagerState.AllocationInfo
            {
                BaseAddress = startingBaseAddressPtr,
                Size        = _fileStream.Length,
                MappedFile  = mmf
            };

            var newPager = new PagerState(this)
            {
                Files           = new[] { mmf },
                MapBase         = startingBaseAddressPtr,
                AllocationInfos = new[] { allocationInfo }
            };

            newPager.AddRef(); // one for the pager
            return(newPager);
        }
Ejemplo n.º 15
0
        public override void Sync(long totalUnsynced)
        {
            if (DisposeOnceRunner.Disposed)
            {
                ThrowAlreadyDisposedException();
            }

            if ((_fileAttributes & Win32NativeFileAttributes.Temporary) == Win32NativeFileAttributes.Temporary ||
                (_fileAttributes & Win32NativeFileAttributes.DeleteOnClose) == Win32NativeFileAttributes.DeleteOnClose)
            {
                return; // no need to do this
            }
            var currentState = GetPagerStateAndAddRefAtomically();

            try
            {
                using (var metric = Options.IoMetrics.MeterIoRate(FileName.FullPath, IoMetrics.MeterType.DataSync, 0))
                {
                    foreach (var allocationInfo in currentState.AllocationInfos)
                    {
                        metric.IncrementFileSize(allocationInfo.Size);

                        if (
                            Win32MemoryMapNativeMethods.FlushViewOfFile(allocationInfo.BaseAddress,
                                                                        new IntPtr(allocationInfo.Size)) == false)
                        {
                            var lasterr = Marshal.GetLastWin32Error();
                            throw new Win32Exception(lasterr);
                        }
                    }

                    metric.IncrementSize(totalUnsynced);

                    if (Win32MemoryMapNativeMethods.FlushFileBuffers(_handle) == false)
                    {
                        var lasterr = Marshal.GetLastWin32Error();
                        throw new Win32Exception(lasterr);
                    }
                }
            }
            finally
            {
                currentState.Release();
            }
        }
Ejemplo n.º 16
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));
        }
Ejemplo n.º 17
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();
            }
        }
Ejemplo n.º 18
0
        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);
            }
        }
Ejemplo n.º 19
0
        public override void Sync()
        {
            if (Disposed)
            {
                ThrowAlreadyDisposedException();
            }

            foreach (var allocationInfo in PagerState.AllocationInfos)
            {
                if (Win32MemoryMapNativeMethods.FlushViewOfFile(allocationInfo.BaseAddress, new IntPtr(allocationInfo.Size)) == false)
                {
                    throw new Win32Exception();
                }
            }

            if (Win32MemoryMapNativeMethods.FlushFileBuffers(_handle) == false)
            {
                throw new Win32Exception();
            }
            // TODO : Measure IO times (RavenDB-4659) - Flushed & sync {sizeToWrite/1024:#,#} kb in {sp.ElapsedMilliseconds:#,#} ms
        }
Ejemplo n.º 20
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);
            }
        }
Ejemplo n.º 21
0
        private PagerState CreatePagerState()
        {
            var mmf = MemoryMappedFile.CreateFromFile(_fileStream, null, _fileStream.Length,
                                                      _memoryMappedFileAccess,
                                                      null, HandleInheritability.None, true);

            var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle();
            var mmFileAccessType  = _access == Win32NativeFileAccess.GenericRead
                                ? Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read
                                        : Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read | Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write;

            var startingBaseAddressPtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle,
                                                                                     mmFileAccessType,
                                                                                     0, 0,
                                                                                     UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row
                                                                                     null);


            if (startingBaseAddressPtr == (byte *)0)            //system didn't succeed in mapping the address where we wanted
            {
                throw new Win32Exception();
            }

            var allocationInfo = new PagerState.AllocationInfo
            {
                BaseAddress = startingBaseAddressPtr,
                Size        = _fileStream.Length,
                MappedFile  = mmf
            };

            var newPager = new PagerState(this)
            {
                Files           = new[] { mmf },
                MapBase         = startingBaseAddressPtr,
                AllocationInfos = new[] { allocationInfo }
            };

            newPager.AddRef();             // one for the pager
            return(newPager);
        }
        private PagerState CreateInitialPagerState(long size)
        {
            var allocationSize = NearestSizeToAllocationGranularity(size);
            var mmf            = MemoryMappedFile.CreateNew(null, allocationSize, MemoryMappedFileAccess.ReadWrite);

            var fileMappingHandle = mmf.SafeMemoryMappedFileHandle.DangerousGetHandle();

            var startingBaseAddressPtr = Win32MemoryMapNativeMethods.MapViewOfFileEx(fileMappingHandle,
                                                                                     Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read |
                                                                                     Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write,
                                                                                     0, 0,
                                                                                     UIntPtr.Zero, //map all what was "reserved" in CreateFileMapping on previous row
                                                                                     null);

            if (startingBaseAddressPtr == (byte *)0) //system didn't succeed in mapping the address where we wanted
            {
                throw new Win32Exception();
            }

            var allocationInfo = new PagerState.AllocationInfo
            {
                BaseAddress = startingBaseAddressPtr,
                Size        = allocationSize,
                MappedFile  = mmf
            };

            var newPager = new PagerState(this)
            {
                Files           = new[] { mmf },
                MapBase         = startingBaseAddressPtr,
                AllocationInfos = new[] { allocationInfo }
            };

            newPager.AddRef();

            return(newPager);
        }
Ejemplo n.º 23
0
 protected internal override unsafe void PrefetchRanges(Win32MemoryMapNativeMethods.WIN32_MEMORY_RANGE_ENTRY *list, int count)
 {
     Win32MemoryMapNativeMethods.PrefetchVirtualMemory(Win32Helper.CurrentProcess, (UIntPtr)count, list, 0);
 }
        private PagerState AllocateMorePagesAndRemapContinuously(long allocationSize)
        {
            var retryCount = 0;

            while (retryCount++ < MaxAllocationRetries)
            {
                byte *newBaseAddress;
                if (TryFindContinuousMemory((ulong)(_totalAllocationSize + allocationSize), out newBaseAddress) == false)
                {
                    var message =
                        string.Format(
                            "Unable to allocate more pages - unsuccessfully tried to allocate continuous block of size = {0} bytes\r\n" +
                            "It is likely that we are suffering from virtual memory exhaustion or memory fragmentation.\r\n" +
                            "64 bits process: {1}\r\n" +
                            "If you are running in 32 bits, this is expected, and you need to run in 64 bits to resume normal operations.\r\n" +
                            "If you are running in 64 bits, this is likely an error and should be reported."
                            , (_totalAllocationSize + allocationSize), Environment.Is64BitProcess);
                    throw new OutOfMemoryException(message);
                }

                bool failedToAllocate = false;
                long offset           = 0;
                var  allocationInfoAfterReallocation = new List <PagerState.AllocationInfo>();
                foreach (var allocationInfo in PagerState.AllocationInfos)
                {
                    var newAlloctedBaseAddress = Win32MemoryMapNativeMethods.MapViewOfFileEx(allocationInfo.MappedFile.SafeMemoryMappedFileHandle.DangerousGetHandle(),
                                                                                             Win32MemoryMapNativeMethods.NativeFileMapAccessType.Read |
                                                                                             Win32MemoryMapNativeMethods.NativeFileMapAccessType.Write,
                                                                                             0, 0,
                                                                                             UIntPtr.Zero,
                                                                                             newBaseAddress + offset);

                    if (newAlloctedBaseAddress == null || newAlloctedBaseAddress == (byte *)0)
                    {
                        Debug.WriteLine("Failed to remap file continuously. Unmapping already mapped files and re-trying");
                        UndoMappings(allocationInfoAfterReallocation);
                        failedToAllocate = true;
                        break;
                    }

                    offset += allocationInfo.Size;
                    allocationInfoAfterReallocation.Add(new PagerState.AllocationInfo
                    {
                        BaseAddress = newAlloctedBaseAddress,
                        MappedFile  = allocationInfo.MappedFile,
                        Size        = allocationInfo.Size
                    });
                }

                if (failedToAllocate)
                {
                    continue;
                }

                var newAllocationInfo = TryCreateNewFileMappingAtAddress(allocationSize, newBaseAddress + _totalAllocationSize);
                if (newAllocationInfo == null)
                {
                    UndoMappings(allocationInfoAfterReallocation);
                    continue;
                }

                var newPagerState = new PagerState(this)
                {
                    Files           = PagerState.Files.Concat(newAllocationInfo.MappedFile),
                    AllocationInfos = allocationInfoAfterReallocation.Concat(newAllocationInfo),
                    MapBase         = newBaseAddress
                };
                return(newPagerState);
            }

            throw new InvalidOperationException(
                      string.Format(
                          "Something bad has happened, after {0} tries, could not find any spot in virtual memory to remap continuous virtual memory for {1:##,###;;0} bytes",
                          MaxAllocationRetries, allocationSize));
        }
Ejemplo n.º 25
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);
            }
        }