Проецируемые на память файлы
, быстродействие и т.д.
![]() |
Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
|
| ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
| [216.73.216.28] |
|
|
Правила раздела C/C++: Системное программирование и WinAPI
FAQ Сайта (C++)
FAQ Форума
Наши Исходники
Поиск по Разделу
MSDN Library Online (Windows Driver Kit)
Google| Страницы: (5) « Первая ... 2 3 [4] 5 все ( Перейти к последнему сообщению ) |
Проецируемые на память файлы
, быстродействие и т.д.
|
Сообщ.
#46
,
|
|
|
|
ёёё... Цитата linuxfan @ А теперь включаем логику, здравый смысл и прочие атрибуты мыслительного процесса: ... б) последовательное чтение mmap: 1. отображаем файл в память 2. при чтении следующего фрагмента возникает исключение, ОС реально выдеояет память и читает туда кусок файла; при это надо не забыть поправить область дескрипторов страниц и сбросить кэш страниц 3. файл здоровый, а памяти и так мало => при последующих обращениях ОС будет вынуждена засвопить какую-то страницу (страницы) 4. goto 2 пока не финиш В итоге имеем кучу неприятностей, включая мухлеж со страничной адресацией и своппинг и необходимость в куче свободной памяти. Имхо, в этих этапах логики совсем не увидел. Хотя, если умдрится и такое намыслить, то последнее утверждение про мухлёж вполне справедливо. Вам батенька подизучатьб матчасть... |
|
Сообщ.
#47
,
|
|
|
|
Цитата Ace @ Вам батенька подизучатьб матчасть... Нельзя ли указать конкретную главу? |
|
Сообщ.
#48
,
|
|
|
|
linuxfan > "обосновать необходимость буферизованного чтения (fread, ifstream)? "
Hryak > "Меньшим количеством переходов в режим ядра" Да кто ж об этом задумывается-то ![]() Стандартный размер буфера составляет всего 512 байт и предназначен для чтения текстовых файлов или небольших записей бинарных файлов. Задавать буфер существенно больше смысла нет, т.к. будут заметные потери на копирование данных. Поэтому при чтении больших блоков данных fread читает их напрямую через ReadFile в буфер юзера, но окружает это чтение доп.прибамбасами типа lock\unlock linuxfan > "для последовательной обработки файла последовательное чтение большими блоками будет быстрее, чем mmap" Да действительно, но с некоторыми оговорками. Можно утверждать, что последовательное небуферированное (FILE_FLAG_NO_BUFFERING) чтение блоками >= 64К всегда несколько быстрее чем MMF (разумеется речь идет о реальном (первом) чтении данных с диска, без всяких там хитростей, когда все или часть данных уже находятся в ОЗУ). Но и здесь есть оговорки. Во-первых, длина блока не должна быть слишком большой, т.е. д.б. заведомо меньше размера доступной физ.памяти иначе можно нарваться на свопинг. Во-вторых, если размер самого файла также не превышает размера доступной физ.памяти, то проигрыш MMF оказывается незначительным (на уровне 5-15%). Это связано с тем, что обработка отказов страниц занимает сравнительно небольшой процент от времени чтения данных с диска (см. измышлизмы на эту тему). Наличие\отсутствие упреждающего чтения при MMF - вопрос неясный и может зависеть от версии ОС (по кр.мере в некоторых статьях утверждается, что при маппинге исполняемых образов винда может подгружать за раз более одной страицы). И вообще най мой взгляд главное достоинство небуферированной обработки по сравнению с MMF и обычным буферированным чтением, заключается именно в независимости от особенностей (кривости) реализации тех или иных функций ОС. Например, как я уже говорил, в Win XP обычное чтение хорошо работает с размерами блоков до 64К, а затем наблюдается резкое увеличение числа промахов файлового кэша и соответствущее падение скорости чтения (см. примерчик), поэтому говорить о преимуществе обычного чтения перед MMF можно только с учетом этого ограничения, а не вообще. Зато вроде как XP распознает последовательное чтение и не дает безразмерно расти файловому кэшу. А вот с MMF наблюдается обратная картина - при чтении большого файла XP может "загадить" этим файлом всю физ.память, не соображая, что уже обработанные куски нам больше не понадобятся - в результате подходя к критическому значению она начинает лихорадочно сбрасывать на диск все подряд, что также приводит к падению скорости. Возможно на это как-то можно повлиять (например, ограничением рабочего набора или еще как), но в этом то и основная неприятность - на деле все оказывается не так просто и неизвестно где и на какие виндовые грабли можно наступить, используя ее продвинутые фичи. Поэтому ты прав - лучше уж самому, ручками сделать на основе ясного и понятного Read\Write ![]() PS: мда торможу, тут столько всего понаписали, пока я телился ![]() PPS: подредактировал ссылки, т.к. после обновления васма они указывали "пальцем в небо"... |
|
Сообщ.
#49
,
|
|
|
|
leo, респект.
|
|
Сообщ.
#50
,
|
|
|
|
Чтобы не быть голословным, затестил для сравнения:
Win XP SP2, HDD Maxtor 80Gb 7200 rpm, RAM DDR400 512Mb, CPU P4 3.2GHz HT-on Чтение, модификация и запись на то же место ![]() ![]() 1) Влияние размера блока при фикс.размере CopySize = 100Mб Блок NO_BUF R\W MMF+Flush MMF ---- ------ ------ --------- ------ 64К 7.5 7.5 8.9 2.7 (+ ~2.8 на FlushFileBuffers) 10М 5.7 < 20.0(!) 5.7 2.7 (- " -) 2) Влияние размера CopySize при фикс.размере блока 10Мб (ОЗУ 512Мб) Size NO_BUF MMF+Flush MMF ---- ------ --------- ------ 100M 5.7 5.7 2.7 512M 29.3 29.9 26.8 (!) 800M 46.7 46.9 131.1 (!!!) Методы чтения\записи R\W - обычные буферированные Read\WriteFile NO_BUF - тоже при FILE_FLAG_NO_BUFFERING MMF - "обычный" MMF (без вызова Flush после модификации данных) MMF+Flush - то же с вызовом FlushViewOfFile Числа в таблицах - число секунд на выполнение операции В первой табличке видим: - для бесхитростных NO_BUF и MMF+Flush с увеличением размера блока скорость копирования возрастает - для обычного R\W при увеличении размера блока наблюдается резкое ухудшение за счет увеличения кэш-промахов (видно по монитору производительности); разброс результатов значительно больше чем в других случаях - хитрый MMF без записи на диск держит все модифицированные данные в ОЗУ; если принудительно не вызвать FlushFileBuffers, то эти данные могут сидеть в памяти очень долго - происходит суперленивая фоновая запись и освобождение памяти ~1Мб за несколько секунд. Flush освобождает память примерно за то же время, что и чтение. Из второй таблички видно - время выполнения предсказуемых NO_BUF и MMF+Flush растет пропорционально размеру файла (точнее - размеру изменяемых данных) - MMF+Flush незначительно отличается от NO_BUF (хотя если только читать данные без записи, то разница получается больше ~10%) - "обычный" MMF ("быстрый", "простой", "удобный" и как его еще только не величают) из "супербыстрого" при малых размерах копируемых данных "вдруг" превращается в заурядного (но зловредного), когда размер файла приближается к размеру доступной физ.памяти, и в полный отстой когда размер файла заметно больше размера ОЗУ. На консоль производительности без корвалола и валерианы лучше не смотреть - такое впечатление, что хрюша готова пожертвовать собой, лишь бы сохранить по максимуму "драгоценные" даные (хотя на самом деле наверняка действует дебильный принцип LRU, а ограничения на WorkingSize почему-то игнорируются). Ну и разумеется после отработки проги проблемы не кончаются, т.к. доступная физ.память колеблется вблизи нуля и похоже часть системного кода сброшена в своп, поэтому если не сделать Flush или не перезагрузить комп, то придется какое-то время мучится с заторможенной системой. Такая же ситуация может возникнуть и при чистом чтении, если проецировать файл не блоками, а целиком - если суммарный размер прочитанных данных приблизится к критическому, начнется такая же "поросячья истерика". Как с этим бороться я не знаю, неужели в хваленой многозадачной ОС могли допустить такую глупость ? Или есть секретные приемы, не раскрываемые широким массам ? |
|
Сообщ.
#51
,
|
|
|
|
Цитата leo @ Чтобы не быть голословным, затестил для сравнения: Уважаемый leo. Хочу обратить твоё внимание на то, что находишься не разделе Windows или Hardware, а в разделе Программирование \ C/C++ \ Чистый С/С++ . Тут программисты тусуются и результаты тестов нужно выкладывать вместе с исходными кодами. "Это не от недоверия к тебе" © д-р Борменталь. У меня, например, прямо щас нет времени писать такие тесты с нуля, но я мог бы взять твой за основу и показать другую сторону медали. Цитата Чтение, модификация и запись на то же место Просто тепличные условия для использования небуферизированного ввода/вывода. По-моему, ни один сторонник MMF в данной ветке не утверждал, что в данных условиях MMF сделает прочие способы. Врочем, по-твоему тесту в ряде случаев так и может получиться. Всё зависит от конкретной задачи - а именно, от последствий ленивой записи. Например, если после обработки программа выдает приглашение пользователю что-нить ввести и начинает ждать, то согласись, что Цитата вывести приглашение через 2.7 сек - это получше, чем через даже 7.5, не говоря уж о 8.9. Пользователь доволен - программист доволен, а что винт шуршит, пока пользователь читает сообщение и думает, что же ему ответить - да кого это волнует?Блок NO_BUF R\W MMF+Flush MMF ---- ------ ------ --------- ------ 64К 7.5 7.5 8.9 2.7 (+ ~2.8 на FlushFileBuffers) Так что даже здесь у MMF могут быть преимущества. Все решает конкретная задача и её контекст. Далее. Разбавь немного свои тепличные условия и добавь в алгоритм работы случайные чтения/запись с уже обработанных страничек. Чем больше - тем больше NO_BUF идет лесом. Результаты R/W и MMF не должны сильном меняться. Вопрос - что использовать в таком случае? Думаю, в большинстве случаев не R/W (20c против 2.7 для MMF из твоего теста). Цитата 2) Влияние размера CopySize при фикс.размере блока 10Мб (ОЗУ 512Мб) Size NO_BUF MMF+Flush MMF ---- ------ --------- ------ 100M 5.7 5.7 2.7 512M 29.3 29.9 26.8 (!) 800M 46.7 46.9 131.1 (!!!) Еще одна причина, по которой хотелось чутка поправить твои исходники. Где результаты обычного R/W? Или ты решил пожалеть поклонников MMF и не шокировать их прекраснейшими вражескими результатами? 131 сек - это много, конечно, но: Цитата leo в этом то и основная неприятность - на деле все оказывается не так просто и неизвестно где и на какие виндовые грабли можно наступить, используя ее продвинутые фичи. Поэтому ты прав - лучше уж самому, ручками сделать на основе ясного и понятного Read\Write Всё дело в использовании мощного и гибкого инструмента, но сложного инструмента. 1. Незнание, неумение пользоваться. Например, дай осаждающим замок тысячу лет назад людям артиллерийскую пушку, сказав, что с ее помощью они смогут влегкую высадить ворота, но ничего более не говори. Они попробуют её покатить к воротам, используя как стенобитное орудие, а потом тебя же посадят на кол, сказав, что их старые добрые стенобитные орудия работают гораздо лучше этой штуки (а может, и не попробуют катить, а прикинут сразу, что неудобная штука). Почему тебя посадили на кол? Потому что люди не умели пользоваться инструментом. 2. Наличие знания, но недостаточное умение. Пример из C: есть указатель на строку и нужно определить, что он указывает на непустую строку. По канонам хорошего стиля нужно было бы писать: ![]() ![]() if (p != NULL && *p != 0) ![]() ![]() if (p && *p) Да, к чему это я? К MMF, конечно. Как и любой другой мощный инструмент, его надо знать - его сильные и слабые стороны. Поросячий визг начинается при доступной физ. памяти ~ 0? Дак делай изредка FlushViewOfFile (из результатов всё твоего же теста). Если можешь определить блок, с которым скорее всего не будешь работать - ему делай, не можешь - всему делай. Хотя во втором случае лучше просто рабочий набор уменьшить - пусть система сама сообразит - какие данные более старые и ненужные. -юсртыхэю Цитата Hryak @ Почему тебя посадили на кол? Ты эта...... Серьезно-то не воспринимай. Это всё пары C2H5OH. За клавой-то я еще сижу, а вот стоять мне проблема. Ну, и в голову стукает. |
|
Сообщ.
#52
,
|
|
|
|
Уважаемый, Hryak.
Если убрать эмоции, то получится что мы говорим об одном и том же "Как и любой другой мощный инструмент, его надо знать - его сильные и слабые стороны" Золотые слова, применимые не только к MMF, но и к обычному R\W и NO_BUF. Но на деле оказывается, что в официальных доках и в популярных изложениях почему-то выпячивают только сильные стороны, и умалчивают о слабых. В результате складывается впечатление о чудесном супербыстром MMF и умной заботливой винде, которая сделает за нас все, что нужно. Наряду с этими наивно-или-лукаво хвалебными представлениями, на программерских форумах гуляют прямо противоположные мнения тех, кто уже попробовал на вкус этот чудо MMF и напоролся на его подводные камни. Вот и бьются друг с другом до посинения. А я лично "ни за белых, ни за красных - мое дело сторона". Я лишь (без претензий на полноту и всеобщность) пытаюсь на конкретных цифрах проиллюстрировать эти самые сильные и слабые стороны - чтобы "юноши, обдумывающие житье" не верили лозунгам белых и красных, а делали собственные выводы и не наступали на известные грабли. Поскольку в данном топике речь идет о модификации файла, то и тестовые примеры ес-но относятся к данному "тепличному" случаю. И приводить в данном случае код, особого смысла не имеет, т.к. тут все тривиально и достаточно просто изменить параметры в уже приведенных вариантах. Единственная проблема - это очистка ОЗУ при повторных проходах. Для NO_BUF ничего чистить не нужно, для MMF можно делать FlushFileBuffers, а вот с обычным R\W проблем больше - нужно или ресетить комп, или тестировать на разных файлах или разных частях одного большого файла. Отсюда и больше мороки, и бОльшой разброс результатов для R\W, и тестить копирование больших объемов мегабайтными блоками - пустая трата времени. А для блоков 64К могу привести доп.цифры: 512Мб за 35.3 с, 800Мб за 52.8 с - все достаточно линейно, т.к. при последовательном чтении\записи размеры кэша и отложенной записи практически не растут. Но это так, к слову ![]() Вывод: у каждого метода есть свои особенности, свои "сильные и слабые стороны". Поэтому использовать их и тем более сравнивать между собой нужно с оговорками, а не вообще, как это к сожалению часто делается |
|
Сообщ.
#53
,
|
|
|
|
Цитата leo @ Но на деле оказывается, что в официальных доках и в популярных изложениях почему-то выпячивают только сильные стороны, и умалчивают о слабых. В результате складывается впечатление о чудесном супербыстром MMF и умной заботливой винде, которая сделает за нас все, что нужно. Не видел выпячивания в официальных доках, может приведёшь хоть один официальный источник где тебе навязывают использовать именно ммф, т.к. он чудесный и супербыстрый? Тебе предоставили стандартизованный интерфейс работы с обьектами, которые "чудесным образом" могут быть связанны с физическими файлами на дисках. Если желаешь, можешь себе представить это как верхний уровень некоего интерфейса, который берёт на себя всю нудную и черновую работу по взаимодействию с физическими проблемами чтения,записи,выделения памяти,etc... Где тебе, как пользователю этого интерфейса, остаётся направлять поведение в нужное русло и контролировать исполнение твоих желаний. Цитата leo @ Наряду с этими наивно-или-лукаво хвалебными представлениями, на программерских форумах гуляют прямо противоположные мнения тех, кто уже попробовал на вкус этот чудо MMF и напоролся на его подводные камни. Вот и бьются друг с другом до посинения. Врядли стоит сильно заморачиватся от мнений тех кто пробовал/не пробовал/всегда в танке. Иногда, достаточно грамотный и знающий обсуждаемую проблему человек, - просто прочитает посты, улыбнётся от потока глупости и её напора, и даже не захочет указать "посиневшим от спора" их неправоту в тех или иных заблуждениях. Цитата leo @ Я лишь (без претензий на полноту и всеобщность) пытаюсь на конкретных цифрах проиллюстрировать эти самые сильные и слабые стороны - чтобы "юноши, обдумывающие житье" не верили лозунгам белых и красных, а делали собственные выводы и не наступали на известные грабли. Понимаешь, все эти предоставляемые цифры (я не тебя конкретно сейчас имею в виду), полученные после непонятно каких тестов могут оказывать действия только на тех, кто пребывает в "посиневшим от спора" состоянии. Для того, чтоб оценить справедливость заявленного, требуется предоставить полную раскладку использовавшихся средств, исходный код, полный отчет о состоянии системы на момент тестов, и т.д. и т.п... Цитата leo @ Вывод: у каждого метода есть свои особенности, свои "сильные и слабые стороны". Поэтому использовать их и тем более сравнивать между собой нужно с оговорками, а не вообще, как это к сожалению часто делается Вот с этим согласен |
|
Сообщ.
#54
,
|
|
|
|
Цитата leo @ Если убрать эмоции Какие эмоции? Цитата то получится что мы говорим об одном и том же Бесспорно. |
|
Сообщ.
#55
,
|
|
|
|
Цитата Hryak @ Цитата linuxfan @ Интересно, а кто из присутствующих может обосновать необходимость буферизованного чтения (fread, ifstream)? Современные ОС все равно выполняют read-ahead, т. е. из без этого буферизуют. Меньшим количеством переходов в режим ядра. Что это означает? Вы хотите сказать при использовании fread, ifstream ОС не занимается буферизацией? Или что? Можно об этом подробнее? Меня этот вопрос интересовал когда-то, но разбираться некогда было. И еще: буферизация операционной системой и кеширование - одно и то же, или разные вещи? |
|
Сообщ.
#56
,
|
|
|
|
по поводу выбора оптимального размера буффера....
седня потести R/W .. копировался файл 650МБ у меня рэйд в функции main после каждово вызова функции копирования стоит комментарий.. в нем --- сколько секунд длился вызов на моей системе.. ![]() ![]() double RWNBCopy (const char* src, const char* dst, DWORD buffsize = 64*1024, DWORD flags = FILE_FLAG_NO_BUFFERING) { HANDLE hFiler = CreateFile (src, GENERIC_READ, 0, 0, OPEN_ALWAYS, flags, 0); if (hFiler == INVALID_HANDLE_VALUE) { std::cout << "Cannot open file for reading, error N " << GetLastError() << "\n"; return 0; } HANDLE hFilew = CreateFile (dst, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, hFiler); if (hFilew == INVALID_HANDLE_VALUE) { std::cout << "Cannot open file for writing, error N " << GetLastError() << "\n"; return 0; } char* buff = (char*)VirtualAlloc (0, buffsize, MEM_COMMIT|MEM_RESERVE, PAGE_READWRITE); DWORD read = 0; int tm = GetTickCount(); while (ReadFile (hFiler, buff, buffsize, &read, 0) && read) WriteFile (hFilew, buff, read, &read, 0); double ret = ((double)GetTickCount() - tm)/1000; VirtualFree (buff, buffsize, MEM_DECOMMIT|MEM_RELEASE); CloseHandle (hFiler); CloseHandle (hFilew); return ret; } int main(int, char*) { std::cout << "64KB NB " << RWNBCopy ("E:\\file.avi", "E:\\file2.avi") << "\n"; //24.5 std::cout << "4KB NB " << RWNBCopy ("E:\\file.avi", "E:\\file2.avi", 4*1024) << "\n"; //38.5 std::cout << "4MB NB " << RWNBCopy ("E:\\file.avi", "E:\\file2.avi", 4*1024*1024) << "\n"; //25.5 std::cout << "32MB NB " << RWNBCopy ("E:\\file.avi", "E:\\file2.avi", 32*1024*1024) << "\n"; //22 std::cout << "32MB B " << RWNBCopy ("E:\\file.avi", "E:\\file2.avi", 32*1024*1024, 0) << "\n"; //31 } Добавлено 512 РАМ остальное вродь как не важно.. Добавлено кстати, когда я попробовал задать размер буффера - 64МБ , копирование обломилось с ошибкой... пока не пытался понять почему... Добавлено Предлагаю эту тему дообсуждать , доопсасывать и потом сделать из нее FAQ .. |
|
Сообщ.
#57
,
|
|
|
|
LuckLess, держи, поиграйся
![]() ![]() double RWNBCopy (const char* src, const char* dst, DWORD buffsize = 64*1024, DWORD dwTmp = 0) { CxFileMap::ErrorCode eCode; CxFileMap fin, fout; eCode = fin.Open( src); if( eCode != CxFileMap::EC_SUCCESS) { std::cout << "Cannot open file for reading, error N " << DWORD( eCode) << "\n"; return 0; } eCode = fout.Create( fin.GetFileSize(), dst, FALSE, FALSE); if( eCode != CxFileMap::EC_SUCCESS) { std::cout << "Cannot open file for writing, error N " << DWORD( eCode) << "\n"; return 0; } int tm = GetTickCount(); ULARGE_INTEGER uliOffs = {}; for( LPVOID pPtrIn = fin.GetView( uliOffs, buffsize); pPtrIn; pPtrIn = fin.GetView( uliOffs, buffsize) ) { LPVOID pPtrOut = fout.GetView( uliOffs, fin.GetSizeView()); if( !pPtrOut || fout.GetSizeView() != fin.GetSizeView()) break; memcpy( pPtrOut, pPtrIn, fin.GetSizeView()); uliOffs.QuadPart += fin.GetSizeView(); fout.FlushView(); } double ret = ((double)GetTickCount() - tm)/1000; if( uliOffs.QuadPart != fin.GetFileSize().QuadPart) { std::cout << "Error copy data!" << "\n"; return 0; } return ret; } Хедер с классиком CxFileMap тут. ЗЫ. В цикле специально делается FlushView, чтоб писалось сразу... Добавлено Цитата LuckLess @ остальное вродь как не важно.. Эт как это, а если у тя там в это время касперский сканит диски |
|
Сообщ.
#58
,
|
|
|
|
Цитата Что это означает? Вы хотите сказать при использовании fread, ifstream ОС не занимается буферизацией? Или что? Можно об этом подробнее? Меня этот вопрос интересовал когда-то, но разбираться некогда было. И еще: буферизация операционной системой и кеширование - одно и то же, или разные вещи? вот цитата из умной книжки: "При выполнении вывода данные не сразу записываются на связанное с потоком физическое устройство, а информация временно сохраняется во внутреннем буфере. Только после заполнения буфера его содержимое переписывается на диск. Однако вызов функции flush()вызывает физическую запись информации на диск до заполнения буфера.Ниже показан прототип функции flush(), являющейся членом потоковых классов вывода: ![]() ![]() ostream &flush(); Г.Шилдт ,самоучитель с++. |
|
Сообщ.
#59
,
|
|
|
|
Цитата Ace @ Эт как это, а если у тя там в это время касперский сканит диски ![]() Был бы рад еслиб я во время скана Касперским дисков копировал 650МБ за 22сек ))))Кстати сама систем копирует медленне(значительно)... (CTRL+C , CTRL+V имеется ввиду), что странно... |
|
Сообщ.
#60
,
|
|
|
|
LuckLess
Интересно, почему ты при создании dst не задаешь flags как в src ? Видимо поэтому результат 64Кб NB получается лучше, чем 4Mb NB - рулит кэшируемая запись Ace Просто копировать файлы (без модификации) с помошью MMF это нечто выдающееся, разве что "поиграться" ![]() Матчасть учит, что в данном случае к бессмыленным потерям на отказы страниц при чтении мы добавляем столько же на отказы при записи + примерно столько же (если не больше) на копирование данных с места на место. В приведенном коде лучше закомментировать FlushView и посмотреть, что будет с системой при копировании файла, превышающего размер ОЗУ. Тут даже точные измерения не нужны - достаточно включить системный монитор и понаблюдать за доступной памятью, обменом страниц и записью на диск. Ну и затем посмотреть как будет вести себя система после такого стресса - пооткрывать папки, программы, документы. PS: Да, кстати, ты просил привести хоть один официальный источник, пиарящий чудесный супербыстрый MMF. Загляни в MSDN: Platform SDK разделы File Mapping и Improving Application Performance, выпиши на бумажку и заучи фразы: "Adwantages of File Mapping", "major adwantages", "Faster and easier file access", "access files more quickly and easily", "improves efficiency", "improve general system performance" (и это как раз в отношении отложенной записи !), ну и наконец откровенное лукавство "Using memory-mapped files for sequential file access is faster than standard sequential file access". После заучивания, можно вместе с другими попугаями повторять эти фразы до посинения Ну а упрямые факты и цифры для попугаев это ес-но туфта - происки Касперского и "не то" состояние системы на момент тестов |