2. Распределение памяти на микроскопическом "уровне алгоритма". Временную память для выполнения команд, определяемых вашими алгоритмами, распределяют функции. Эффективность этого процесса зависит от вашей стратегии реализации алгоритмов. Например, при написании кода, который должен выполняться в циклах, необходимо как можно тщательнее продумывать его эффективность в отношении использования ресурсов, чтобы свести к минимуму непроизводительные накладные расходы. Уделяя пристальное внимание эффективности распределения памяти в создаваемых вами алгоритмах, вы сможете значительно повысить общую производительность приложения.
Приложения для настольных компьютеров, хранящие в памяти большие рабочие наборы (рабочий набор, равный всей используемой памяти), обычно выталкивают в дисковый файл подкачки все новые и новые данные. Это позволяет освобождать память от редко используемых данных, что несколько сглаживает отрицательные последствия неэкономного управления памятью на макроскопическом уровне приложения. Результирующее поведение производительности в зависимости от объема используемой памяти в широких пределах носит примерно линейный характер. Кроме того, среды выполнения управляемого кода на настольных компьютерах располагают сложными механизмами очистки памяти от неиспользуемых объектов, что может частично нивелировать недостатки расточительных в отношении использования памяти алгоритмов. Это способствует повышению производительности приложения на микроскопическом уровне. Неэффективное управление памятью имеет отрицательные последствия и в случае приложений, выполняющихся на настольных компьютерах, однако огромная емкость вычислительной среды сглаживает эти эффекты.
ОЗУ мобильных устройств имеют гораздо меньший объем и, как правило, не позволяют надлежащим образом реализовать механизмы, использующие дополнительные внешние накопители для организации быстрого обмена страницами с памятью. Кроме того, в условиях ограниченных ресурсных возможностей на мобильных устройствах могут быть реализованы лишь сравнительно простые механизмы очистки памяти от неиспользуемых объектов. Это означает, что небрежно организованное управление памятью в приложениях для мобильных устройств будет иметь весьма заметные отрицательные последствия как на макроскопическом, так и на микроскопическом уровнях. По сравнению с настольными компьютерами мобильные устройства гораздо менее терпимы к любым просчетам в управлении памятью.
Использование тщательно продуманного управления памятью обеспечивает значительные преимущества как при разработке приложений для настольных компьютеров, так и при разработке приложений для мобильных устройств, однако в последнем случае такой подход должен быть обязательно плановым. Отсутствие продуманного управления памятью в случае приложений для настольных компьютеров приводит к постепенному обрастанию приложения неиспользуемыми объектами и замедлению его работы. В противоположность этому мобильное приложение, работающее без применения выверенных стратегий управления памятью на макроскопическом и микроскопическом уровнях, очень быстро пересекает опасную черту, и его дальнейшее использование становится истинным мучением.
Управление памятью на макроскопическом "уровне приложения"
На рис. 8.1 в схематическом виде отображено, как снижается производительность приложения с увеличением объема используемой памяти.
Рис. 8.1. Изменение производительности приложения с увеличением объема используемой памяти
Из поведения графиков видно, что в случае приложений для настольных компьютеров диапазон объемов используемой памяти, при которых производительность остается в допустимых пределах, является намного более широким. При превышении некоторого порогового значения производительность резко снижается, поскольку начинается свопинг данных между памятью и файлом подкачки, а сборщик мусора все чаще пытается освобождать и уплотнять память; вместе с тем, падение производительности происходит гораздо медленнее, чем в случае мобильных устройств. Для мобильных устройств диапазон используемых объемов памяти, при которых производительность остается на приемлемом уровне, оказывается более узким. При превышении некоторого порогового значения наблюдается резкое падение производительности мобильного приложения, поскольку сборщик мусора работает почти непрерывно, пытаясь высвободить все большие объемы памяти. На графиках отмечены участки, соответствующие использованию объемов памяти, при которых приложение еще способно нормально функционировать. Коль скоро потребление памяти не превышает некоторого критического значения, ничего особенного в целом не происходит. Однако при пересечении критической точки производительность приложения резко падает, поскольку сборщик мусора вынужден работать все чаще, изо всех сил пытаясь высвободить память для нужд приложения.
Будут ли меня преследовать те же проблемы, если я пишу приложение на основе собственного кода?