LINUX.ORG.RU

Page cache

 


0

3

А вот есть такой теоретический вопрос:

допустим мы запустили bash. Потом вышли из него. Насколько я понимаю копия исполняемого файла должна остатся в кеше страниц. Теперь мы снова запускаем bash. Ядро при созднии процесса будет использовать непосредственно страницы из кеша или будет делать из них копии???

★★★★★

Ответ на: комментарий от geekless

Линкер вроде как обычная программа, так что должен просто ридом (копированием в юзерспейс) читать файл и делать с ним что нужно. Если файл в кеше, прочитает из кеша. Ков неприменим, т.к. файл не смаплен даже как своп-ресурс, а просто закеширован.

Могу ошибаться, но тоже интересно, как все работает.

arturpub ★★ ()
Ответ на: комментарий от arturpub

Линкер вроде как обычная программа, так что должен просто ридом (копированием в юзерспейс) читать файл и делать с ним что нужно.

facepalm.png

man 3 mmap

vadim@aquila:~$ pmap `pgrep openbox` | grep r-x
08048000    324K r-x-- openbox
b6937000      8K r-x-- ISO8859-1.so
b6d28000     44K r-x-- libnss_files-2.18.so
b6d38000    104K r-x-- libgraphite2.so.3.0.1
b6d54000    148K r-x-- liblzma.so.5.0.5
b6d7b000    152K r-x-- libexpat.so.1.6.0
b6da4000     60K r-x-- libbz2.so.1.0.6
b6db5000     84K r-x-- libz.so.1.2.8
b6dcc000     20K r-x-- libffi.so.6.0.1
b6dd3000    272K r-x-- libm-2.18.so
b6e19000      4K r-x-- libgthread-2.0.so.0.3600.4
b6e1c000     12K r-x-- libgmodule-2.0.so.0.3600.4
b6e22000    328K r-x-- libharfbuzz.so.0.919.0
b6e76000     20K r-x-- libXdmcp.so.6.0.0
b6e7d000      8K r-x-- libXau.so.6.0.0
b6e81000   1360K r-x-- libxml2.so.2.9.1
b6fdb000    364K r-x-- libImlib2.so.1.4.5
b704d000     80K r-x-- libXft.so.2.3.1
b7063000    228K r-x-- libfontconfig.so.1.7.0
b709e000    640K r-x-- libfreetype.so.6.10.0
b7153000    308K r-x-- libgobject-2.0.so.0.3600.4
b71a2000    288K r-x-- libpango-1.0.so.0.3400.1
b71ee000     80K r-x-- libpangoft2-1.0.so.0.3400.1
b7204000     28K r-x-- libpangoxft-1.0.so.0.3400.1
b720d000      4K r-x-- libX11-xcb.so.1.0.0
b7210000     16K r-x-- libxcb-util.so.1.0.0
b7216000     16K r-x-- libXfixes.so.3.1.0
b721d000     12K r-x-- libdl-2.18.so
b7222000    128K r-x-- libxcb.so.1.1.0
b7244000     96K r-x-- libpthread-2.18.so
b7260000    428K r-x-- libpcre.so.1.2.1
b72cd000     36K r-x-- libXrender.so.1.3.0
b72d9000   1696K r-x-- libc-2.18.so
b7488000     60K r-x-- libobt.so.2.0.1
b749d000    108K r-x-- libobrender.so.29.0.1
b74ba000     36K r-x-- libstartup-notification-1.so.0.0.0
b74c5000     36K r-x-- libXcursor.so.1.0.2
b74d1000   1228K r-x-- libX11.so.6.3.0
b7608000   1024K r-x-- libglib-2.0.so.0.3600.4
b770a000     36K r-x-- libXrandr.so.2.2.0
b7715000     68K r-x-- libXext.so.6.4.0
b7728000      8K r-x-- libXinerama.so.1.0.0
b775c000      4K r-x--   [ anon ]
b775d000    128K r-x-- ld-2.18.so
geekless ★★ ()
Ответ на: комментарий от geekless

Так ммап здесь только как способ доступа, или хочешь сказать эти страницы шарятся процессами? И если да, то не совсем понятно, что будет с рабочим процессом, если поменять файл сошки.

зы. Ты такой агрессивный, блин..

arturpub ★★ ()
Ответ на: комментарий от arturpub

Так ммап здесь только как способ доступа

Ты не прочитал ман.

зы. Ты такой агрессивный, блин..

Если не прочитаешь ман, то вообще покусаю. :D

И если да, то не совсем понятно, что будет с рабочим процессом, если поменять файл сошки.

Давай я почитаю тебе ман вслух и с выражением.

MAP_SHARED and MAP_PRIVATE describe the disposition of write references to the memory object. If MAP_SHARED is specified, write references shall change the underlying object. If MAP_PRIVATE is specified, modifications to the mapped data by the calling process shall be visible only to the calling process and shall not change the underlying object. It is unspecified whether modifications to the underlying object done after the MAP_PRIVATE mapping is established are visible through the MAP_PRIVATE mapping. Either MAP_SHARED or MAP_PRIVATE can be specified, but not both. The mapping type is retained across fork().

geekless ★★ ()
Ответ на: комментарий от arturpub

Линкер вроде как обычная программа, так что должен просто ридом (копированием в юзерспейс) читать файл

Линкер (ld.so) именно мапит файл.

Так ммап здесь только как способ доступа, или хочешь сказать эти страницы шарятся процессами?

Да, конечно.

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

Линкер вроде как обычная программа, так что должен просто ридом (копированием в юзерспейс) читать файл

Линкер (ld.so) именно мапит файл.

Хм, с оглядки на то что mmap использует собственный кеш я понимаю что все сложнее чем казалось изначально :(((

cvv ★★★★★ ()

а если бинарник изменился между запусками, например, новый bash скомпилировали?

ИМХО загружается каждый раз заново

Harald ★★★★★ ()
Ответ на: комментарий от Harald

Я так понимаю, сегменты кода замаплены на диск (page cache). Если мы перезапишем файл то в ФС всё равно должны остаться старые данные пока работает хоть один старый процесс.

Сужу об этом по тому что на одной из олимпиад яндекса говорил что сегмент кода никогда не попадает в своп. Смысла нет т.к. код всегда есть на диске.

true_admin ★★★★★ ()
Ответ на: комментарий от cvv

mmap использует собственный кеш

Нет никакого «своего кэша mmap», есть unified page cache. Все данные попадают в него, неважно, инициирован В/В read(2) или mmap(2).

все сложнее чем казалось изначально :(((

Нет. Всё примерно так, как сказал гиклес: страницы читаются с диска по page fault-ам и остаются в кэше; изменяемые страницы копируются CoW.

tailgunner ★★★★★ ()
Ответ на: комментарий от true_admin

поройся по форуму - здесь ктото пространно обьяснял что в отличие от read() mmap() напрямую в кеш страниц не суется. это приводит к тому что чтение через mmap() медленее read().

cvv ★★★★★ ()
Последнее исправление: cvv (всего исправлений: 2)
Ответ на: комментарий от cvv

здесь ктото пространно обьяснял что в отличие от read() mmap() напрямую в кеш страниц не суется. это приводит к тому что чтение через mmap() медленее read()

Если кто-то так говорил, он ошибался или врал - mmap изначально работал именно через page cache. С тех пор buffer cache и page cache почти объединили (мимо page cache идут только метаданные).

tailgunner ★★★★★ ()
Ответ на: комментарий от tailgunner

Хм. А как ты думаешь почему в 2.4 mmap() был быстрее чем read() а в 3.5 - наоборот? Я в этот кусок кернела пока еще не лазил.

cvv ★★★★★ ()
Последнее исправление: cvv (всего исправлений: 1)
Ответ на: комментарий от cvv

Я не вижу никаких причин, по которым mmap и read работали бы с разной скоростью на более-менее современном ядре и ФС с размером блока 4K или больше. Разве что readahead в каком-то включается быстрее, но это не должно сильно влиять.

tailgunner ★★★★★ ()
Ответ на: комментарий от Harald

Меня тоже этот момент смущает, по идее мемори-маппед ио основывается на том, что есть *физическая страница*, которая отвечает за страницу в файле. Если что-то меняет файл, страница меняется по определению. Соответственно отображенные страницы потенциально изменятся. Из лекции geekless'а ясно, что для map-private это unspecified. Неужто стабильность системы висит на unspecified волоске?

Разве что есть специальный механизм по отслеживанию изменений в файлах с шаред объектами. Я про это и имел ввиду «интересно».

arturpub ★★ ()
Ответ на: комментарий от arturpub

а если бинарник изменился между запусками, например, новый bash скомпилировали?

Если новый bash скомпилировали, его помещают на место при помощи rename(), а не при помощи write().

Из лекции geekless'а ясно, что для map-private это unspecified. Неужто стабильность системы висит на unspecified волоске?

Если ты с правами рута делаешь write() в образ исполняемого файла, из которого замаплен живой процесс, ты ССЗБ. Система не обязана защищаться от каждого дятла с правами рута, ведь так?

И вы, походу, ребята, забыли (не знали?), что файл на томе ФС — это прежде всего инод. Все операции чтения, записи, выгрузки и загрузки данных из кэша и т.п. проводятся по отношению к иноду. Если вы перемещаете новый файл на место старого с тем же именем, то это ДРУГОЙ файл.

geekless ★★ ()
Ответ на: комментарий от true_admin

Если мы перезапишем файл то в ФС всё равно должны остаться старые данные пока работает хоть один старый процесс. Сужу об этом по тому что на одной из олимпиад яндекса говорил что сегмент кода никогда не попадает в своп. Смысла нет т.к. код всегда есть на диске.

Сказали тебе всё правильно, а выводы ты делаешь неправильные.

У каждой страницы памяти процесса есть backing store. Для анонимных страниц и для страниц, которые менялись по COW, — это своп. Для прочих страниц запамленного файла, backing store — это сам файл. Система никогда не выгружает в своп такие страницы, потому что они привязаны к другому backing store.

Выгрузка данных производится в три этапа. Сначала специальный механизм отцепляет от адресного пространства страницы с соответствии некоторым алгоритмом.

Если страница отцеплена от всех адресных пространств, она попадает либо в список грязных (требующих записи на диск), либо чистых страниц. Страницы, запамленные из исполняемого файла, естественно, причинам попадают в читый, т.к. их содержимое не изменялось.

Отдельный механизм отвечает за запись грязных страниц, после чего они переводятся в список чистых.

И наконец, третий механихм отвечает за удаление страниц из чистого списка в случае, когда системе нужно больше памяти. Эти освобожденные страницы покидают page cache и затем переиспользуются системой под любые её нужды.

На любом этапе, если в процессе возникает page fault, страница изымается из этих списков и прицепляется обратно к адресному пространству.

Если же в момент page fault страница выгружена на диск, то производится выделение новой страницы и загрузка содержимого с диска.

Какой вывод? Страница исполняемого файла в любой момент может быть отброшена системой, а в случае надобности загружена с диска заново.

Никакого «специального, отдельного» кэша нет, page cache общий на всё. Также, обычные read() и write() идут через его же страницы.

Поэтому если кто-то делает write() в файл, из которого замаплена исполняемая область какого-нибудь процесса, то получится ад, треш и угар.

geekless ★★ ()
Последнее исправление: geekless (всего исправлений: 4)
Ответ на: комментарий от geekless

Страница исполняемого файла в любой момент может быть отброшена системой, а в случае надобности загружена с диска заново.

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

arturpub ★★ ()
Ответ на: комментарий от arturpub

Ты снова обманываешь, зелёная поня. Если бы тебе было ясно, то не было бы «внезапно просто». Ясно — это когда в голове всё факты и выводы относительно какого-либо предмета чётко увязаны друг с другом.

geekless ★★ ()
Ответ на: комментарий от arturpub

Так вот плагин с сетевого маунта прицепишь, и огребешь веселья с инжекцией с удаленной тачки. Для кого-то будет очень внезапно, я вот о чем :)

arturpub ★★ ()
Ответ на: комментарий от arturpub

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

Он остаётся не «как бы открытым», он остаётся самым настоящим образом открытым.

Более того, ты можешь создать файл и сразу удалить. Это стандартная практика для работы с временными файлами, которые нет нужды долговременно хранить на диске. Как только твой процесс сдохнет, файл тоже умрёт.

Вашу мать, ребята, мимо вас прошел Столлингс, Таненбаум, Бах и спека POSIX впридачу. Ладно, не все присутствующие заканчивали ВУЗ по соответствующим направлениям. Но как вообще можно писать что-то под POSIX-подобные сисемы (раздел форума называется development, на минуточку), не ознакомившись с общими принципами?

Извините, накипело. :D

geekless ★★ ()
Ответ на: комментарий от geekless

Ну так тыж здесь, всегда готовый объяснить и почитать вслух манов на ночь. Вроде все увязалось. Поню скоро уберу, страсти похоже улеглись.

А про обманываешь: всегда думал/догадывался, что сошка как минимум один раз копируется или хешируется, или еще как отслеживается, чтобы не завязываться на файл. А тут вон чо.

arturpub ★★ ()
Ответ на: комментарий от arturpub

В винде вроде был такой костыль для съемных носителей. Но, кажется, он требует специального указания в исполняеммом файле, что этот файл надо засовывать в ОЗУ целиком и держать там. Потому что уронить процесс, достав флешку, там — раз плюнуть.

geekless ★★ ()
Ответ на: комментарий от geekless

Ну не работал я с ммап, а тупо без раздумья переносить предположения из обычных опен/рид не приучен. Можно было не тупить здесь, а обложиться манами, но времени на это нет, и занимаюсь не этим. А интересно много кому думаю. Спасибо что объяснил, весьма полезный тред.

arturpub ★★ ()
Ответ на: комментарий от arturpub

Вот что касается nfs, то я не уверен, как это обслуживается, всё-таки там другая подсистема принимает участие. В особенности реализации сетевых ФС в linux никогда не вникал.

geekless ★★ ()
Ответ на: комментарий от geekless

в винде и фряхе на старте приложения приложение полностью копируется в своп а только потом запускается.

cvv ★★★★★ ()
Ответ на: комментарий от cvv

Не позорься

в винде и фряхе на старте приложения приложение полностью копируется в своп а только потом запускается.

Since Windows NT is a page-based virtual-memory system, memory-mapped files represent little more than an extension of an existing, internal memory management component. Essentially all applications in Windows NT are represented in their entirety by one or more files on disk and a subset of those files resident in random access memory (RAM) at any given time. For example, each application has an executable file that represents pages of executable code and resources for the application. These pages are swapped into and out of RAM, as they are needed, by the operating system. When a page of memory is no longer needed, the operating system relinquishes control over the page on behalf of the application that owns it and frees it for use by another. When that page becomes needed again, it is re-read from the executable file on disk. This is called backing the memory with a file, in this case, the executable file. Similarly, when a process starts, pages of memory are used to store static and dynamic data for that application. Once committed, these pages are backed by the system pagefile, similar to the way the executable file is used to back the pages of code. Figure 2 is a graphical representation of how pages of code and data are backed on the hard disk.

geekless ★★ ()
Ответ на: Не позорься от geekless

Переведу на русский: RO-секции с кодом/данными/ресурсами никогда не попадают в спов, т.к. всегда могут просто считаться с исходного файла, поэтому в винде запущенный бинарник нельзя удалить, т.к. он memory-mapped. Ну и грузится, соотв. не всё, а лишь то, что в данный момент нужно. А вот в линуксе запущенный файл удалить можно, т.к. он полностью в памяти (превед)

frame ★★★ ()
Ответ на: комментарий от cvv

в винде и фряхе на старте приложения приложение полностью копируется в своп а только потом запускается.

Не знаю про фряху, а в винде код программы копируется в swap только при наличии специального флага в бинаре.

tailgunner ★★★★★ ()

Блеадь, форум linux.org.ru целиком состоит из дебилов и новостей про убунту. Переименуйтесь уже в ubuntu.org.ru, чтобы название соответствовало содержанию.

geekless ★★ ()
Ответ на: комментарий от frame

Таки да, удаленный файл все еще на диске. Пока есть дескрипторы на него, файловая система не даст ему исчезнуть, хотя из директории он уже исключен. Это как reference counting — участие в директории или открытый дескриптор добавляет единичку. Физически иноды освобождаются только при нуле.

arturpub ★★ ()
Ответ на: комментарий от geekless

Вот так мы сами того не желая коллективно затролели гиклеса, и теперь у него «респринг» :) Расслабься, чувак, этот тред на порядок лучше и информативнее петоно-плюсовых, имхо.

arturpub ★★ ()
Ответ на: комментарий от arturpub

Чего у меня? Я человек простой, окадемиев не кончал, этих ваших хипсторских ругательств не уразумею.

geekless ★★ ()
Ответ на: комментарий от tailgunner

вот есть вот такая тестилка - поганяй сам. будешь удивлен.

http://www.kfs.org/oliver/code/io_mapped_file/mmaptest.cpp

в рассылке grep-a есть пространное обсуждение этого нюанса которое закончилось тем что mmap() выпили из грепа :(((

cvv ★★★★★ ()
Ответ на: комментарий от cvv

read() наиболее часто используется для последовательного доступа и оптимизирован для него. Включая readahead и прочие прелести. mmap используется для рандомизированного доступа и подгружает данные в ленивом режиме, генерируя кучу page fault-ов по ходу дела.

Теперь вопрос: какое это отношение имеет к предмету этого треда?

geekless ★★ ()
Последнее исправление: geekless (всего исправлений: 1)
Ответ на: комментарий от cvv

вот есть вот такая тестилка - поганяй сам. будешь удивлен.

Кстати о результатах. На холодном кэше результаты примерно одинаковы, что логично:

vadim@aquila:/tmp/mmaptest$ time ./mmaptest read /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso 
checksum of /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso is 0

real	0m8.345s
user	0m2.904s
sys	0m0.264s

vadim@aquila:/tmp/mmaptest$ time ./mmaptest mmap /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso 
checksum of /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso is 0

real	0m8.644s
user	0m1.272s
sys	0m0.040s

На горячем кэше mmap в 3 раза быстрее, что тоже логично:

vadim@aquila:/tmp/mmaptest$ time ./mmaptest read /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso 
checksum of /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso is 0

real	0m2.782s
user	0m1.140s
sys	0m1.524s
vadim@aquila:/tmp/mmaptest$ time ./mmaptest mmap /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso 
checksum of /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso is 0

real	0m0.995s
user	0m0.780s
sys	0m0.096s

geekless ★★ ()
Ответ на: комментарий от cvv
tmp$ time ./mmaptest read data.txt ; time ./mmaptest mmap data.txt
checksum of data.txt is 7367096160641199872

real	0m0.380s
user	0m0.062s
sys	0m0.318s
checksum of data.txt is 7367096160641199872

real	0m0.086s
user	0m0.043s
sys	0m0.040s

У меня тоже после разогрева ммап конкретно рвет рид. Последняя макось, 64-бит. data.txt = «Hello, World!\n» x 10^7.

arturpub ★★ ()
Ответ на: комментарий от cvv

На теплом кэше mmap быстрее в 2.5 раза, что и неудивительно с размером чтения 256 байт.

А после сброса кэшей разницы нет - 1.57м против 2.01м; при размере чтения 4096 времена 1.57 и 1.55

tailgunner ★★★★★ ()
Последнее исправление: tailgunner (всего исправлений: 3)
Ответ на: комментарий от arturpub

у меня наверное неправильный линукс:

Разогреваем кеш:

$ time ./mmaptest read /home/vc/Projects/android/MSI/18.tar.gz
checksum of /home/vc/Projects/android/MSI/18.tar.gz is 4172541390592687345

real    0m1.145s
user    0m0.056s
sys     0m0.108s
Press any key to continue...

горячий рид:

$ time ./mmaptest read /home/vc/Projects/android/MSI/18.tar.gz 
checksum of /home/vc/Projects/android/MSI/18.tar.gz is 4172541390592687345

real    0m0.065s
user    0m0.028s
sys     0m0.036s

горячий mmap:

$ time ./mmaptest mmap /home/vc/Projects/android/MSI/18.tar.gz 
checksum of /home/vchernooky/Projects/android/MSI/18.tar.gz is 4172541390592687345

real    0m0.068s
user    0m0.032s
sys     0m0.036s

система:

$ uname -a
Linux f37102 3.5.0-39-generic #60~precise1-Ubuntu SMP Wed Aug 14 15:38:41 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux
cvv ★★★★★ ()
Последнее исправление: cvv (всего исправлений: 2)
Ответ на: комментарий от tailgunner

Ого, не заметил в коде 256. На 4096 рид чуть быстрее — 64 vs 85, на 8192 конкретно быстрее — 52 vs 86. Дальше сильной разницы нет.

Хотя в общем автор теста прав, обычно все читают по-BUFSIZ-но.

arturpub ★★ ()
Ответ на: комментарий от cvv

Ну у меня не совсем линукс, но сути не должно менять. А ты точно с дефолтным 256-буфером тест гоняешь?

arturpub ★★ ()
Ответ на: комментарий от cvv

И что? Время ~одинаково, как и должно быть. Но вообще-то случай холодного кэша интереснее.

Кстати, в тесте же ясно написано: «But give it a BIG file». Вряд ли файл, сумма которого считается за 0.07с может считаться BIG.

tailgunner ★★★★★ ()
Ответ на: комментарий от arturpub

На моей машине read с буфером 64KiB быстрее mmap на 30%. И если мы посмотрим на строку «Minor (reclaiming a frame) page faults», то увидим, почему:

vadim@aquila:/tmp/mmaptest$ /usr/bin/time -v ./mmaptest read /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso 
checksum of /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso is 0
	Command being timed: "./mmaptest read /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso"
	User time (seconds): 0.40
	System time (seconds): 0.24
	Percent of CPU this job got: 96%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.67
	Average shared text size (kbytes): 0
	Average unshared data size (kbytes): 0
	Average stack size (kbytes): 0
	Average total size (kbytes): 0
	Maximum resident set size (kbytes): 844
	Average resident set size (kbytes): 0
	Major (requiring I/O) page faults: 0
	Minor (reclaiming a frame) page faults: 277
	Voluntary context switches: 1
	Involuntary context switches: 142
	Swaps: 0
	File system inputs: 0
	File system outputs: 0
	Socket messages sent: 0
	Socket messages received: 0
	Signals delivered: 0
	Page size (bytes): 4096
	Exit status: 0
vadim@aquila:/tmp/mmaptest$ /usr/bin/time -v ./mmaptest mmap /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso 
checksum of /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso is 0
	Command being timed: "./mmaptest mmap /media/stuff/data/Ненужности/archlinux-2013.08.01-dual.iso"
	User time (seconds): 0.76
	System time (seconds): 0.10
	Percent of CPU this job got: 94%
	Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.92
	Average shared text size (kbytes): 0
	Average unshared data size (kbytes): 0
	Average stack size (kbytes): 0
	Average total size (kbytes): 0
	Maximum resident set size (kbytes): 539408
	Average resident set size (kbytes): 0
	Major (requiring I/O) page faults: 0
	Minor (reclaiming a frame) page faults: 134918
	Voluntary context switches: 1
	Involuntary context switches: 226
	Swaps: 0
	File system inputs: 0
	File system outputs: 0
	Socket messages sent: 0
	Socket messages received: 0
	Signals delivered: 0
	Page size (bytes): 4096
	Exit status: 0
vadim@aquila:/tmp/mmaptest$ 
geekless ★★ ()
Ответ на: комментарий от tailgunner

Проверил, 1024. А вот и BIG FILE подоспел:

14000000000 30 авг 13:28 data.txt
read-256 real	3m11.725s
read-8k  real	2m24.578s
mmap real	2m21.641s

arturpub ★★ ()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.