Sidewalker
19-11-2011, 09:49
Добрый день.
В общем задание - сравнить скорость чтения отображенного в ОЗУ файла и просто напрямую с диска через ReadFile.
("Сравнить среднее время доступа к данным в файле при использовании метода отображения файла на адресное пространство процесса и при использовании традиционного доступа к файлу с использованием системного вызова ReadFile.")
Погуглил погуглил и MSDN и пр. мне сказали что отображением файла занимается класс MemoryMappingFile. Вроде прогу написал, всё работает. НО ReadFile (который как я понял считывает с харда напрямую?) работает БЫСТРЕЕ чем в случае отображения файла.
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices; // для вызова функций из WinAPI
using System.Timers;
namespace mapping1
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
unsafe static extern bool ReadFile
(
IntPtr hFile,
void* lpBuffer,
int nNumberOfBytesToRead,
ref int lpNumberOfBytesRead,
IntPtr lpOverlapped
);
struct s1 { public int[] mas1;} // 1 MB
struct s20 { public int[] mas2;} // 20 MB
struct s512 { public int[] mas3;} // 256 MB
static void Main()
{
s1 Sc1;
Sc1.mas1 = new int[262144]; // 1 MB
s20 Sc2;
Sc2.mas2 = new int[5242880]; // 20 MB
s512 Sc3;
Sc3.mas3 = new int[67108864]; // 256 MB
long offset1 = 0x0000000; // смещение для CreateViewAccessor
long length1 = 0x0100000; // 1 mb
long offset2 = 0x00A00000; // 10 MB
long length2 = 0x01400000; // 20 MB
long offset3 = 0x10000000; // 256 MB
long length3 = 0x10000000; // 256 MB
long time1 = 0;
long time2 = 0;
long time3 = 0;
Console.ReadKey();
using (var mmf1 = MemoryMappedFile.CreateFromFile(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, "file1"))
{
// Create a random access view, from the 256th megabyte (the offset)
// to the 512th megabyte (the offset plus length).
using (var accessor1 = mmf1.CreateViewAccessor(offset1, length1))
{
Console.WriteLine("Mapping and reading from mapped file...");
Console.WriteLine("Mapped to RAM: " + (accessor1.Capacity / (1024 * 1024)) + " megabytes");
long a1 = DateTime.Now.Ticks;
accessor1.ReadArray<int>(0, Sc3.mas3, 0, 262144); // 1 mb
long a2 = DateTime.Now.Ticks;
time1 = (a2 - a1) / 10000; // milliseconds
Console.WriteLine("Reading time: " + time1 + " milliseconds\n");
}
mmf1.Dispose(); // освобождает все ресурсы, использумые mmf1
}
using (var mmf2 = MemoryMappedFile.CreateFromFile(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, "file1"))
{
using (var accessor1 = mmf2.CreateViewAccessor(offset2, length2))
{
Console.WriteLine("Mapped to RAM: " + (accessor1.Capacity / (1024 * 1024)) + " megabytes");
long a1 = DateTime.Now.Ticks;
accessor1.ReadArray<int>(0, Sc2.mas2, 0, 5242880); // 20 mb
long a2 = DateTime.Now.Ticks;
time2 = (a2 - a1) / 10000; // milliseconds
Console.WriteLine("Reading time: " + time2 + " milliseconds\n");
}
mmf2.Dispose(); // освобождает все ресурсы, использумые mmf2
}
using (var mmf3 = MemoryMappedFile.CreateFromFile(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, "file1"))
{
using (var accessor1 = mmf3.CreateViewAccessor(offset3, length3))
{
Console.WriteLine("Mapped to RAM: " + (accessor1.Capacity / (1024 * 1024)) + " megabytes");
long a1 = DateTime.Now.Ticks;
accessor1.ReadArray<int>(0, Sc3.mas3, 0, 67108864); // 256 mb
long a2 = DateTime.Now.Ticks;
time3 = (a2 - a1) / 10000; // milliseconds
Console.WriteLine("Reading time: " + time3 + " milliseconds\n");
}
mmf3.Dispose(); // освобождает все ресурсы, использумые mmf3
}
// принудительная сборка мусора
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.GetTotalMemory(true);
Console.ReadKey();
// part2 : directly from hdd
long time_1 = 0;
long time_2 = 0;
long time_3 = 0;
int length_1 = 262144;
int length_2 = 5242880;
int length_3 = 67108864;
length_1 *= sizeof(int);
length_2 *= sizeof(int);
length_3 *= sizeof(int);
Console.WriteLine("Reading from HDD...");
using (var fs1 = File.Open(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, FileAccess.Read))
{
unsafe
{
fixed (int* pointerForArray = Sc1.mas_1)
{
long a1 = DateTime.Now.Ticks;
ReadFile(fs1.Handle, pointerForArray, length_1, ref length_1, IntPtr.Zero);
long a2 = DateTime.Now.Ticks;
time_1 = (a2 - a1) / 10000; // milliseconds
}
Console.WriteLine("First block readed success. Time:" + time_1);
fixed (int* pointerForArray = Sc2.mas_2)
{
long a1 = DateTime.Now.Ticks;
ReadFile(fs1.Handle, pointerForArray, length_2, ref length_2, IntPtr.Zero);
long a2 = DateTime.Now.Ticks;
time_2 = (a2 - a1) / 10000; // milliseconds
}
Console.WriteLine("Second block readed success. Time:" + time_2);
fixed (int* pointerForArray = Sc3.mas_3)
{
long a1 = DateTime.Now.Ticks;
ReadFile(fs1.Handle, pointerForArray, length_3, ref length_3, IntPtr.Zero);
long a2 = DateTime.Now.Ticks;
time_3 = (a2 - a1) / 10000; // milliseconds
}
Console.WriteLine("Third block readed success. Time:" + time_3);
}
fs1.Dispose();
fs1.Close();
}
Console.WriteLine("Statistics:\nwith mapping (from RAM): " + time1 + " " + time2 + " " + time3 +
"\nwithout mapping (from HDD): " + time_1 + " " + time_2 + " " + time_3);
Console.ReadKey();
}
}
}
Mapping and reading from mapped file...
Mapped to RAM: 1 megabytes
Reading time: 3 milliseconds
Mapped to RAM: 20 megabytes
Reading time: 70 milliseconds
Mapped to RAM: 256 megabytes
Reading time: 836 milliseconds
Reading from HDD...
First block readed success. Time:0
Second block readed success. Time:12
Third block readed success. Time:173
Statistics:
with mapping (from RAM): 3 70 836
without mapping (from HDD): 0 12 173
WTF?.... Вроде сборщик мусора принудительно запускал, но память не очищается - до первого ReadKey прога весит в озу 19 мб, до второго ReadKey 300 мб, до третьего (в итоге) - примерно 570 Мб.
В общем задание - сравнить скорость чтения отображенного в ОЗУ файла и просто напрямую с диска через ReadFile.
("Сравнить среднее время доступа к данным в файле при использовании метода отображения файла на адресное пространство процесса и при использовании традиционного доступа к файлу с использованием системного вызова ReadFile.")
Погуглил погуглил и MSDN и пр. мне сказали что отображением файла занимается класс MemoryMappingFile. Вроде прогу написал, всё работает. НО ReadFile (который как я понял считывает с харда напрямую?) работает БЫСТРЕЕ чем в случае отображения файла.
using System;
using System.IO;
using System.IO.MemoryMappedFiles;
using System.Runtime.InteropServices; // для вызова функций из WinAPI
using System.Timers;
namespace mapping1
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true)]
[return: MarshalAs(UnmanagedType.Bool)]
unsafe static extern bool ReadFile
(
IntPtr hFile,
void* lpBuffer,
int nNumberOfBytesToRead,
ref int lpNumberOfBytesRead,
IntPtr lpOverlapped
);
struct s1 { public int[] mas1;} // 1 MB
struct s20 { public int[] mas2;} // 20 MB
struct s512 { public int[] mas3;} // 256 MB
static void Main()
{
s1 Sc1;
Sc1.mas1 = new int[262144]; // 1 MB
s20 Sc2;
Sc2.mas2 = new int[5242880]; // 20 MB
s512 Sc3;
Sc3.mas3 = new int[67108864]; // 256 MB
long offset1 = 0x0000000; // смещение для CreateViewAccessor
long length1 = 0x0100000; // 1 mb
long offset2 = 0x00A00000; // 10 MB
long length2 = 0x01400000; // 20 MB
long offset3 = 0x10000000; // 256 MB
long length3 = 0x10000000; // 256 MB
long time1 = 0;
long time2 = 0;
long time3 = 0;
Console.ReadKey();
using (var mmf1 = MemoryMappedFile.CreateFromFile(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, "file1"))
{
// Create a random access view, from the 256th megabyte (the offset)
// to the 512th megabyte (the offset plus length).
using (var accessor1 = mmf1.CreateViewAccessor(offset1, length1))
{
Console.WriteLine("Mapping and reading from mapped file...");
Console.WriteLine("Mapped to RAM: " + (accessor1.Capacity / (1024 * 1024)) + " megabytes");
long a1 = DateTime.Now.Ticks;
accessor1.ReadArray<int>(0, Sc3.mas3, 0, 262144); // 1 mb
long a2 = DateTime.Now.Ticks;
time1 = (a2 - a1) / 10000; // milliseconds
Console.WriteLine("Reading time: " + time1 + " milliseconds\n");
}
mmf1.Dispose(); // освобождает все ресурсы, использумые mmf1
}
using (var mmf2 = MemoryMappedFile.CreateFromFile(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, "file1"))
{
using (var accessor1 = mmf2.CreateViewAccessor(offset2, length2))
{
Console.WriteLine("Mapped to RAM: " + (accessor1.Capacity / (1024 * 1024)) + " megabytes");
long a1 = DateTime.Now.Ticks;
accessor1.ReadArray<int>(0, Sc2.mas2, 0, 5242880); // 20 mb
long a2 = DateTime.Now.Ticks;
time2 = (a2 - a1) / 10000; // milliseconds
Console.WriteLine("Reading time: " + time2 + " milliseconds\n");
}
mmf2.Dispose(); // освобождает все ресурсы, использумые mmf2
}
using (var mmf3 = MemoryMappedFile.CreateFromFile(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, "file1"))
{
using (var accessor1 = mmf3.CreateViewAccessor(offset3, length3))
{
Console.WriteLine("Mapped to RAM: " + (accessor1.Capacity / (1024 * 1024)) + " megabytes");
long a1 = DateTime.Now.Ticks;
accessor1.ReadArray<int>(0, Sc3.mas3, 0, 67108864); // 256 mb
long a2 = DateTime.Now.Ticks;
time3 = (a2 - a1) / 10000; // milliseconds
Console.WriteLine("Reading time: " + time3 + " milliseconds\n");
}
mmf3.Dispose(); // освобождает все ресурсы, использумые mmf3
}
// принудительная сборка мусора
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.GetTotalMemory(true);
Console.ReadKey();
// part2 : directly from hdd
long time_1 = 0;
long time_2 = 0;
long time_3 = 0;
int length_1 = 262144;
int length_2 = 5242880;
int length_3 = 67108864;
length_1 *= sizeof(int);
length_2 *= sizeof(int);
length_3 *= sizeof(int);
Console.WriteLine("Reading from HDD...");
using (var fs1 = File.Open(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, FileAccess.Read))
{
unsafe
{
fixed (int* pointerForArray = Sc1.mas_1)
{
long a1 = DateTime.Now.Ticks;
ReadFile(fs1.Handle, pointerForArray, length_1, ref length_1, IntPtr.Zero);
long a2 = DateTime.Now.Ticks;
time_1 = (a2 - a1) / 10000; // milliseconds
}
Console.WriteLine("First block readed success. Time:" + time_1);
fixed (int* pointerForArray = Sc2.mas_2)
{
long a1 = DateTime.Now.Ticks;
ReadFile(fs1.Handle, pointerForArray, length_2, ref length_2, IntPtr.Zero);
long a2 = DateTime.Now.Ticks;
time_2 = (a2 - a1) / 10000; // milliseconds
}
Console.WriteLine("Second block readed success. Time:" + time_2);
fixed (int* pointerForArray = Sc3.mas_3)
{
long a1 = DateTime.Now.Ticks;
ReadFile(fs1.Handle, pointerForArray, length_3, ref length_3, IntPtr.Zero);
long a2 = DateTime.Now.Ticks;
time_3 = (a2 - a1) / 10000; // milliseconds
}
Console.WriteLine("Third block readed success. Time:" + time_3);
}
fs1.Dispose();
fs1.Close();
}
Console.WriteLine("Statistics:\nwith mapping (from RAM): " + time1 + " " + time2 + " " + time3 +
"\nwithout mapping (from HDD): " + time_1 + " " + time_2 + " " + time_3);
Console.ReadKey();
}
}
}
Mapping and reading from mapped file...
Mapped to RAM: 1 megabytes
Reading time: 3 milliseconds
Mapped to RAM: 20 megabytes
Reading time: 70 milliseconds
Mapped to RAM: 256 megabytes
Reading time: 836 milliseconds
Reading from HDD...
First block readed success. Time:0
Second block readed success. Time:12
Third block readed success. Time:173
Statistics:
with mapping (from RAM): 3 70 836
without mapping (from HDD): 0 12 173
WTF?.... Вроде сборщик мусора принудительно запускал, но память не очищается - до первого ReadKey прога весит в озу 19 мб, до второго ReadKey 300 мб, до третьего (в итоге) - примерно 570 Мб.