Имя пользователя:
Пароль:  
Помощь | Регистрация | Забыли пароль?  | Правила  

Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » .NET - MemoryMappedFile & ReadFile

Ответить
Настройки темы
.NET - MemoryMappedFile & ReadFile

Пользователь


Сообщения: 107
Благодарности: 9


Конфигурация

Профиль | Цитировать


Изменения
Автор: Sidewalker
Дата: 18-07-2020
Добрый день.

В общем задание - сравнить скорость чтения отображенного в ОЗУ файла и просто напрямую с диска через 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 Мб.

Отправлено: 09:49, 19-11-2011

 

Аватара для lxa85

Необычный


Contributor


Сообщения: 4463
Благодарности: 994

Профиль | Сайт | Отправить PM | Цитировать


Цитата Sidewalker:
WTF?. »
А что ты хотел? Все правильно работает. Время мапирования файла в память больше, нежели просто чтение.
Цитата Sidewalker:
В общем задание - сравнить скорость чтения отображенного в ОЗУ файла и просто напрямую с диска через ReadFile.
("Сравнить среднее время доступа к данным в файле при использовании метода отображения файла на адресное пространство процесса и при использовании традиционного доступа к файлу с использованием системного вызова ReadFile.")
Погуглил погуглил и MSDN и пр. мне сказали что отображением файла занимается класс MemoryMappingFile. Вроде прогу написал, всё работает. НО ReadFile (который как я понял считывает с харда напрямую?) работает БЫСТРЕЕ чем в случае отображения файла. »
Вот теперь перечитай задание еще раз и внимательно (полезная вещь, сам пользуюсь )
Что тебя спрашивают? Правильно!
"Сравнить среднее время доступа к данным в файле(1) при использовании метода отображения файла(2) на адресное пространство процесса и при использовании традиционного доступа к файлу(3) с использованием системного вызова ReadFile."

Объясни мне, какое отношение написанный код имеет к скорости чтения файлов и мапирования их в память?
Отвечу - никакого!
То, что ты написал - подготовительный этап тестирования. Да, мапирование дольше, т.к. там
1 - чтение файла с медленного HDD, 2 - запись данных в ОЗУ (+накладные расходы, выделения памяти, менеджера памяти и т.д.). Чтение - это просто чтение.
----
Вот сейчас, когда у тебя файл на hdd и его дубликат в памяти, проводи тесты на скорость линейного доступа, случайного доступа. Получишь графики - объясняй их форму, характер и т.д.
Вот это - курсовая. А то что у тебя сейчас есть - это подготовительный этап, важный, но подготовительный. От него зависит, как именно файл будет расположен в памяти, и как файл будет расположен на hdd. Это исходные данные.
----
Беглый просмотр кода, позволяет тебя поздравить с выполнением этого этапа. Теперь самое интересное - тесты на скорость доступа.
Успехов!

-------
- Я не разрешаю тебе быть плохой! Потому что плохие люди совершают плохие поступки. А это нехорошо!
(Из наставлений 5 летней девочки своей младшей сестре)

Это сообщение посчитали полезным следующие участники:

Отправлено: 10:25, 19-11-2011 | #2



Для отключения данного рекламного блока вам необходимо зарегистрироваться или войти с учетной записью социальной сети.

Если же вы забыли свой пароль на форуме, то воспользуйтесь данной ссылкой для восстановления пароля.


Пользователь


Сообщения: 107
Благодарности: 9

Профиль | Цитировать


Цитата lxa85:
Да, мапирование дольше, т.к. там
1 - чтение файла с медленного HDD, 2 - запись данных в ОЗУ (+накладные расходы, выделения памяти, менеджера памяти и т.д.). »
Цитата Sidewalker:
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 »
Что насчёт того что я засекаю время именно копирования данных из озу (отображенный файл) в озу (массив в структуре) ?? Мне казалось что чтение файла с HDD выполняется в
Цитата Sidewalker:
var mmf1 = MemoryMappedFile.CreateFromFile(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, "file1")) »

Цитата lxa85:
Получишь графики - объясняй их форму, характер и т.д. »
Мне нужна МИКРОстатистика, не более того, без графиков и проч. Только небольшое сравнение.

Цитата lxa85:
проводи тесты на скорость линейного доступа, случайного доступа »
Я разве не этим занимаюсь в
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
? Чем не тест?

Последний раз редактировалось Sidewalker, 18-07-2020 в 17:04.


Отправлено: 10:31, 19-11-2011 | #3


Аватара для lxa85

Необычный


Contributor


Сообщения: 4463
Благодарности: 994

Профиль | Сайт | Отправить PM | Цитировать


ок.
Цитата Sidewalker:
Код: Выделить весь код
using (var mmf1 = MemoryMappedFile.CreateFromFile(@"C:\Users\RazoR\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
»
Вот этот кусок распиши по шагам.
Что куда попадает, в какой структурной форме (уровнем асбтракции) и т.п.
Т.е. у меня сейчас предположение, что тут "навёрнута" слишком дурацкая конструкция со множеством "вложенностей"
Код: Выделить весь код
(var mmf1 = MemoryMappedFile.CreateFromFile(@"C:\Users\RazoR\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, "file1")
Когда это выполняется?
Код: Выделить весь код
(var accessor1 = mmf1.CreateViewAccessor(offset1, length1)
Что это? Еще одна ссылка на внешний объект?
Где в коде можно поставить точку и сказать, что "Вот. Вот здесь мы получили "чистую" копию файла в памяти"?
Проверь, что не идет динамического обращения к дисковой подсистеме.
Постарайся вообще убрать всякую оптимизацию кода компилятором. А то кто эти компиляторы .NET знает, вполне могли оптимизировать.
Код: Выделить весь код
 accessor1.ReadArray<int>(0, Sc3.mas3, 0, 262144); // 1 mb
Это еще что такое? Причем здесь Sc3.mas3 ? Ладно, спишем, как опечатку.
----
Цитата Sidewalker:
Мне нужна МИКРОстатистика »
Ага, это ты на защите расскажешь.

-------
- Я не разрешаю тебе быть плохой! Потому что плохие люди совершают плохие поступки. А это нехорошо!
(Из наставлений 5 летней девочки своей младшей сестре)

Это сообщение посчитали полезным следующие участники:

Отправлено: 10:55, 19-11-2011 | #4


Пользователь


Сообщения: 107
Благодарности: 9

Профиль | Цитировать


Цитата lxa85:
Когда это выполняется? »
Всегда.
Цитата lxa85:
Что это? Еще одна ссылка на внешний объект? »
CreateFromFile(String, FileMode, String) - Создает из файла на диске размещенный в памяти файл с заданным режимом доступа и именем.
CreateViewAccessor() - Создает метод MemoryMappedViewAccessor, который соответствует представлению размещенного в памяти файла.
Внизу ссылки - пример. http://msdn.microsoft.com/ru-ru/libr...appedfile.aspx
Так что насчёт "дурацкая конструкция" - всё к мелкософту.

Цитата lxa85:
Проверь, что не идет динамического обращения к дисковой подсистеме. »
Не понял тебя. Что значит проверить? Мне все потоки харда палить или просто на лампочку системника посмотреть? Если да, то прога слишком быстро выполняется чтобы заметить))

Цитата lxa85:
Ладно, спишем, как опечатку. »
Так оно и есть. Хз как закралась) Конечно же там Sc1.mas1. Именовал так для удобства.

Цитата lxa85:
Ага, это ты на защите расскажешь. »
У нас защита не жесткая будет) Но сделать добросовестно конечно надо.

Отправлено: 14:48, 19-11-2011 | #5


Аватара для lxa85

Необычный


Contributor


Сообщения: 4463
Благодарности: 994

Профиль | Сайт | Отправить PM | Цитировать


Цитата Sidewalker:
Когда это выполняется? »
Всегда. »
До вызова процедуры, во время вызова процедуры, во время выполнения процедуры?
Цитата Sidewalker:
Проверь, что не идет динамического обращения к дисковой подсистеме. »
Меня интересует. Идет ли обращение к HDD во время выполнения процедуры?
У меня вопрос тот же. Поставить пальцем точку в листинге программы и сказать, что "От сих мы работаем только с ОЗУ". И разумеется обосновать свое решение.
Хорошо бы вообще отключить физический доступ к носителю, после того, как файл был скопирован в память. BTW имеет ли разницу слова "скопировать файл в память" и "смапировал/отобразил файл в память"?
----
На предзащите гораздо интереснее смотреть толковый график, нежели всматриваться в микро(очень маленькую? )статистику с колонками цифр.

-------
- Я не разрешаю тебе быть плохой! Потому что плохие люди совершают плохие поступки. А это нехорошо!
(Из наставлений 5 летней девочки своей младшей сестре)

Это сообщение посчитали полезным следующие участники:

Отправлено: 15:22, 19-11-2011 | #6


Пользователь


Сообщения: 107
Благодарности: 9

Профиль | Цитировать


Цитата lxa85:
До вызова процедуры, во время вызова процедуры, во время выполнения процедуры? »
До. То, что внутри () после using, выполняется до его тела. Собственно CreateFileMapping как раз и отображает ( =копирует) в озу часть (или весь, у меня часть) файла с другого носителя.

Цитата lxa85:
Поставить пальцем точку в листинге программы и сказать, что "От сих мы работаем только с ОЗУ". »
Цитата Sidewalker:
using (var mmf1 = MemoryMappedFile.CreateFromFile(@"C:\Users\xxx\Documents\Visual Studio 2010\Projects\sizetests1\sizetests1\bin\Debug\Test.data", FileMode.Open, "file1"))
{ »
ОТ СИХ. И до закрытия фигурной скобки using'а.

Цитата lxa85:
На предзащите гораздо интереснее смотреть толковый график, нежели всматриваться в микро(очень маленькую? )статистику с колонками цифр. »
Это не диплом, у нас у курсовых нет предзащит) Потом мб ещё другими объемами поиграюсь, а так хватит. Тем более для отображения ( = мэппинга) в ОЗУ требуется непрерывный(!) свободный кусок. А большого обычно такового нет.

В общем. Проблема решилась. Дело было в том, что при таком
Цитата Sidewalker:
accessor1.ReadArray<int>(0, Sc2.mas2, 0, 5242880); // 20 mb »
способе из озу считывается и копируется в массив поэлементно (ОБЕ операции), т.е. считалось 4 байта, скопировалось ( =записалось в озу в массив) в элемент, и потом так же для следующего. Всё бы ничего, НО ReadFile читает СРАЗУ весь блок с харда, а потом просто копирует его в массив. Соответственно это выполняется примерно с такой же скоростью как и в случае mapping'а, порой и быстрее. Т.к. отказываться от такой удобной обертки как MemoryMappedFile не хотелось и суперпроизводительность не была целью, решил исправить проблему путем считывания ReadFile по 4 байта в цикле.


Код: Выделить весь код
for (i = 0; i < length_1; i++)
                        {
                            ReadFile(fs1.Handle, pointerForArray+i, 4, ref plen_1, IntPtr.Zero);
                        }

Последний раз редактировалось Sidewalker, 18-07-2020 в 17:04.

Это сообщение посчитали полезным следующие участники:

Отправлено: 19:29, 19-11-2011 | #7



Компьютерный форум OSzone.net » Программирование, базы данных и автоматизация действий » Программирование и базы данных » .NET - MemoryMappedFile & ReadFile

Участник сейчас на форуме Участник сейчас на форуме Участник вне форума Участник вне форума Автор темы Автор темы Шапка темы Сообщение прикреплено

Похожие темы
Название темы Автор Информация о форуме Ответов Последнее сообщение
Apple iPod Touch 4G && Jailbreak - все еще нужно? mmx358 Мобильные ОС, смартфоны и планшеты 8 29-03-2011 10:00
Драйвер - PCI\VEN_1095&DEV_3132&SUBSYS_71321095&REV_01\4&662654C&0&00E0 kalion-kill Поиск драйверов, прошивок и руководств 1 08-11-2009 16:45
Функция ReadFile DillerInc Программирование и базы данных 8 18-07-2005 07:45
WinXP & Win2K & Net &  Inet проблема!! Help! SDL2000 Сетевые технологии 5 19-10-2003 22:29




 
Переход