Rob The Quant
Rob The Quant

Reputation: 397

How do I prevent unloading memory mapped RAM pages in .NET?

I have a large data file 80GB+ that I memory map to RAM to make a high performance read-only data scan. The first time it runs slow because the data pages are loaded from disk to RAM. Subsequent scans run very fast because data is already in RAM. However after a few minutes of inactivity, Windows starts of unload the pages from RAM and release the RAM even thou there's plenty RAM to spare. I can see that in Resource Monitor. How can I make sure pages always stay in RAM at all times, and windows won't unload them? This is my C# code:

            long filesize=new FileInfo(path).Length;
            file = MemoryMappedFile.CreateFromFile(path, FileMode.Open, null, 0, MemoryMappedFileAccess.Read);
            accessor = file.CreateViewAccessor(0, 0, MemoryMappedFileAccess.Read);
            mapping = new MemoryMapped();
            handle = accessor.SafeMemoryMappedViewHandle;
            handle.AcquirePointer(ref ptr);
            mapping._handle = handle;
            mapping._pointer = ptr;
            mapping._size = filesize;

EDIT: Interestingly this happens only when I run my app via the Windows Task Scheduler. I set the PriorityClass = ProcessPriorityClass.High but that doesn't help.

Upvotes: 0

Views: 224

Answers (1)

Rob The Quant
Rob The Quant

Reputation: 397

It turns out that Windows Task Scheduler runs apps with Low Memory Priority and Low Processor priority. Here's my fix:

            using (Process p = Process.GetCurrentProcess())
            {
                print("Setting Memory Priority");
                _MEMORY_PRIORITY_INFORMATION a;
                a.MemoryPriority = 5;//normal
                int sz = Marshal.SizeOf(a);
                var ptr = Marshal.AllocHGlobal(sz);
                Marshal.StructureToPtr(a, ptr, false);
                SetProcessInformation(p.Handle, PROCESS_INFORMATION_CLASS.ProcessMemoryPriority, ptr, (uint)sz);
                Marshal.FreeHGlobal(ptr);

                print("Process Priority: " + p.PriorityClass.ToString());
                p.PriorityClass = ProcessPriorityClass.High;
                print("New Priority: " + p.PriorityClass.ToString());
            }

Upvotes: 1

Related Questions