Пробуксовка
Пробуксовка
Пробуксовка может негативно сказаться на вашем приложении, превращая его из высокоэффективной оптимизированной программы в медленную и ленивую. Предположим, что существует приложение, которое требует большого объема памяти, скажем, например, половину всей имеющейся в компьютере физической памяти. Оно создает большие массивы крупных блоков, выделяя память из кучи. Такое выделение приведет к тому, что будут заниматься новые страницы, а старые, скорее всего, будут записываться на диск. Затем приложение считывает эти большие блоки, начиная с начала массива и в направлении его конца. Операционная система при необходимости будет считывать запрашиваемые страницы из ОЗУ. При этом никаких проблем возникать не будет.
А теперь представим себе, что приложение считывает блоки в произвольном порядке. Скажем, сначала оно считывает данные из блока 56, затем из блоков 123, 12, 234 и т.д. В таком случае вероятность возникновения ошибки отсутствия страницы увеличивается. При этом все большее и большее количество страниц будет записываться на диск и считываться с диска. Индикатор работы диска будет гореть почти постоянно, а скорость работы приложения упадет. Это и есть пробуксовка - непрерывный обмен страницами между диском и памятью, вызванный запросами приложения страниц в произвольном порядке.
В общем случае лекарства от пробуксовки нет. Большую часть времени блоки памяти выделяются из программы динамического распределения памяти Delphi. Кроме того, программист не может управлять конкретным расположением блоков памяти. Может случиться, например, что связанные блоки данных хранятся в разных страницах. (Здесь под словом "связанные" понимается блоки памяти, данные из которых, вероятно, будут считываться одновременно, поскольку сами данные связаны.) Одним из методов снижения риска возникновения пробуксовки является использование отдельных куч для выделения памяти для структур и данных разных приложений. Но алгоритм такого выделения в настоящей книге не приводится.
Рассмотрим пример. Предположим, что мы выделили память под элементы объекта TList. Каждый из элементов содержит, по крайней мере, одну строку, память для которой выделяется из кучи (например, мы пользуемся 32-разрядным Delphi и элемент использует длинные строки). А теперь представим себе, что приложение уже проработало некоторое время, и элементы в объекте TList неоднократно добавлялись и удалялись. Вполне возможно, что экземпляр TList, его элементы и строки элементов распределены по разным страницам памяти. Теперь при последовательном считывании элементов объекта TList от начала до конца приложение будет обращаться ко многим страницам, что приведет к активному обмену страницами между диском и памятью. Если количество элементов достаточно мало, все страницы, относящиеся к данному приложению, могут находиться в памяти. Но если в объекте TList элементов насчитывается несколько миллионов, при их считывании приложение может породить состояние пробуксовки.