Как я могу получить байты с упреждающим чтением?

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

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

РЕДАКТИРОВАТЬ: Соответствующий документ http://www.azulsystems.com/events/mspc_2008/2008_MSPC.pdf


person Bruno Martinez    schedule 28.04.2010    source источник
comment
Насколько велики элементы, которые вы извлекаете с диска? Независимо от упреждающего чтения файловая система будет считывать данные с диска единицами размера блока (часто 4 КБ). Итак, если ваши элементы, скажем, 100 байт, возможно, вы могли бы упростить свою задачу, отображая элементы в одном и том же блоке — что-то, что вы можете вычислить, не прибегая к причудливым интерфейсам.   -  person Keith Smith    schedule 03.05.2010
comment
Я хочу знать не статический минимум, который читает ОС, а количество байтов, которое она фактически читает для конкретной операции.   -  person Bruno Martinez    schedule 03.05.2010


Ответы (4)


Вы действительно можете использовать свой второй метод, по крайней мере, в Linux. mmap() файл, затем используйте функцию mincore(), чтобы определить, какие страницы являются резидентными. Со страницы руководства:

int mincore(void *addr, size_t length, unsigned char *vec);

mincore() возвращает вектор, указывающий, находятся ли страницы виртуальной памяти вызывающего процесса в ядре (ОЗУ) и, следовательно, не вызовут обращения к диску (ошибка страницы) при обращении к ним. Ядро возвращает информацию о местонахождении страниц, начинающихся с адреса addr и продолжающихся length байт.

Конечно, здесь есть условие гонки — mincore() может сказать вам, что страница является резидентной, но затем она может быть заменена непосредственно перед тем, как вы получите к ней доступ. Се ля ви.

person caf    schedule 29.04.2010
comment
vmtouch для печати статистики кэша файлов из командной строки (*nix) - person Ashwin Jayaprakash; 16.06.2011

Вы исходите из неверного предположения. По крайней мере, в Linux ОС попытается выяснить шаблоны доступа программы. Если вы читаете файл последовательно, ядро ​​выполняет предварительную выборку последовательно. Если вы будете много прыгать по файлу, ядро, вероятно, сначала запутается, но затем прекратит предварительную выборку.

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

Попробуйте подойти к этому по-другому. Прежде чем вызывать read() для получения необходимой информации, вызовите fadvise(), чтобы ОС знала, что вы хотите загрузить.

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

person Karmastan    schedule 28.04.2010
comment
Мне жаль разочаровывать, но у меня нет конкретного применения для этого. Это пришло мне в голову, когда я читал www.cs.sunysb.edu/~bender/pub/BenderHu-TODS07.pdf и другие статьи о забывчивости кеша. - person Bruno Martinez; 29.04.2010

Это, конечно, не может быть сделано в Windows. В Windows поведение опережающего чтения зависит от ОС, и даже если бы она могла сказать вам, сколько она прочитала вперед, это не принесло бы вам никакой пользы, потому что, как только вы это узнали, страницы в памяти, которые используемые для кэширования, могли быть восстановлены для какого-либо другого использования.

То же самое касается определения того, является ли страница резидентной или нет. Как только вы узнаете, ответ может измениться, когда какой-то другой поток нуждается в памяти для чего-то другого.

Если вы действительно хотите делать что-то в Windows, вы можете отключить буферизацию и управлять буферами самостоятельно. Это самый быстрый путь ввода-вывода, но он же и самый сложный — нужно быть очень осторожным, и часто ОС все же может сделать это лучше.

person Stewart    schedule 28.04.2010
comment
Ваша точка зрения о состоянии гонки между определением того, является ли страница резидентной, и ее фактическим чтением, хороша. Тем не менее, вы находитесь во власти выселения страниц, даже если не делаете ничего подозрительного, как я хочу сделать. Обычный вызов fread может вернуться, и страница памяти исчезнет до того, как я ее использую. - person Bruno Martinez; 28.04.2010
comment
Верно, хотя это менее вероятно, если вы не испытываете серьезной нехватки памяти, ОС вряд ли будет выгружать недавно использованные личные страницы, потому что она должна записывать их на диск. Страницы кэша или страницы файлов с отображением памяти уже находятся на диске, поэтому их потеря намного дешевле для ОС. В любом случае это не победа, как кажется — вы должны просто читать столько, сколько вам нужно, и надеяться, что это будет настолько бесплатно, насколько это возможно. - person Stewart; 28.04.2010

Какой API я могу использовать, чтобы узнать, что находится в кешах ОС?

Конечно, нет стандартного способа сделать это для любой системы posix, и я не знаю ни одного нестандартного способа, специфичного для Linux. Единственное, что вы можете знать (почти) наверняка, это то, что файловая система будет считывать данные, кратные размеру страницы, обычно 4 КБ. Таким образом, если ваши чтения невелики, вы можете с высокой вероятностью (хотя и не наверняка) знать, что данные на окружающей странице находятся в памяти.

Я полагаю, вы могли бы делать хитрые вещи, например, определять, сколько времени потребовалось системе чтения для завершения. Если это быстро, то есть 100 микросекунд или меньше, это, вероятно, попадание в кеш. Как только он достигает миллисекунды или около того, это, вероятно, был промах кеша. Конечно, на самом деле это не очень вам поможет, и это очень-очень хрупко.

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

Наконец, я поддерживаю предложение @Karmastan: объясните более широкую цель, которую вы пытаетесь достичь. Вероятно, есть способ сделать это, но тот, который вы предложили, не таков.

person Dale Hagglund    schedule 28.04.2010