Хотите поблагодарить автора блога - жмите здесь !
1 2 0
1 2 0

Нажмите на рекламный баннер выше, если хотите поблагодарить автора блога !
Написание каждой статьи заняло в сотни раз больше времени, чем один клик.

суббота, июля 20, 2013

Некоторые размышления по поводу Android и SWAP

В заметке Кастомное ядро Android ThunderZap со swap vs Родное ядро Android 4.04 на Fly IQ 450 я ранее описал впечатления от использования SWAP  в Android. Чуть позже (после того как все перепроверю) я отдельно опишу, как всетаки можно сделать его более безболезненным, и даже приемлемым для использования (я его сча включил взад, и проверяю что вышло, но нужно немного попользоваться, чтобы не писать "малопроверенные первые впечатления" в качестве "рецепта для повторения") с помощью некоторых настроек sysctl ядра, а также какие плюсы от него всеже можно получить.
А сейчас, я бы хотел поделиться одним "размышлизмом", это не рецепт, это только вопрос, но как известно "в правильно заланном вопросе скрыта половина ответа" :) Возможно вместе мы найдем и сам ответ, на вопрос ПОЧЕМУ включение SWAP так слабо влияет на обьем доступной памяти у Android (по крайней мере в версии Android 4.04), настолько слабо, что делает включение свапа в общемто малополезным.

На этот вопрос я наткнулся случайно. Я вынудил ядро Линукс "освободить" часть реальной памяти (временно и "нехорошим способом", но для проверки этого хватило), и с удивлением обнаружил, что доступной памяти для приложений с точки зрения Android от этого не увеличилось ни на мегабайт, хотя собсвенно Линукс, который и "закопан в глубинах Андроид" показывал что у него появилось 64 метра свободной памяти. То есть нет прямой связи между свободной памятью собственно системы. и памятью, доступной для программ с точки зрения Android ! Поэтому и SWAP оказывается малоэффективным для Android.

Теперь по порядку. В ядрышке линукса, есть такой параметр: /proc/sys/vm/drop_caches. Вот что о нем сказано в мануале:
Writing to this will cause the kernel to drop clean caches, dentries and
inodes from memory, causing that memory to become free.

To free pagecache:
 echo 1 > /proc/sys/vm/drop_caches
To free dentries and inodes:
 echo 2 > /proc/sys/vm/drop_caches
To free pagecache, dentries and inodes:
 echo 3 > /proc/sys/vm/drop_caches

As this is a non-destructive operation and dirty objects are not freeable, the
user should run `sync' first.
 (вот тут мануал с описанием параметров sysctl ядра Линукс, связанных с памятью: Documentation for /proc/sys/vm/* )
Что я сделал. Я в консоли проделал следующее:
 sync
echo 1 > /proc/sys/vm/drop_caches
echo 2 > /proc/sys/vm/drop_caches
echo 3 > /proc/sys/vm/drop_caches
sync

Это не метод на самом деле для "освобождения памяти", так как он ведет к появлению серьезных тормозов и возможно других побочных эффектов, но в итоге комманда "free", показала появление порядка 64 метров свободной памяти в системе.
Но после того как я перешел в таск менеджер уже в самом Android, я обнаружил что памяти у Android от этого не прибавилось :() То есть сам Android просто не видит этой свободной памяти, которая появилась у системы Линукс, надстройкой над которой и является по сути Андроид.
Собственно, похожая ситуация наблюдается и со SWAP - "прибавка" памяти для приложений Android, при включении свапа в 256 метров, реально практически не ощутима (по кр мере на Android 4.04). И похоже тут "одна и та же причина". Android просто игнорирует эту дополнительную память.
У меня сложилось впечатление, что у Android есть какойто параметр, который устанавливается при старте, и который и определяет, какой максимально допустимый обьем памяти может использовать Android для приложений. И любую память сверх этого он собственно игнорирует. Но вот что это за параметр и где он находится - не знаю, как и то, возможно ли на него повлиять.  Но похоже именно в этом направлении лежит "ключ", который может позволить системе Android полноценно использовать swap, и получить от него реальный выиграш в быстродействии и обьеме памяти.
А на данный момент, ситуация выглядит так (насколько я вижу. Считаем гипотезой. но похожей на правду, исходя из опыта использования SWAP описанного мною ранее), что Android не использует эту память,и SWAP реально используется толко самим Linux. Но "сколько там того линукс", в результате идет вытеснение в SWAP частей самого ядра линукс, но выиграша от этого "чуть", зато "тормозов появляется немерянно", вместо того чтобы "положить" туда части неактивных приложений Android из ОЗУ, для чего собственно SWAP и включался.
Остался вопрос - как убедить сам Android, что у него появилась дополнительная память, и где лежит этот параметр, который заставляет Android "игнорить" часть имеющейся доступной ему памяти.
Кто что думает ?

Дополнение от 21 июля - кажется я нашел где "собака порылась".
Вот смотрите, что лежит в /proc/meminfo Android (обьем ОЗУ 512 метров):
MemTotal:         483476 kB
MemFree:            5032 kB
Buffers:            4924 kB
Cached:            91332 kB
SwapCached:        31208 kB
Active:           112356 kB
Inactive:         204112 kB
Active(anon):      81484 kB
Inactive(anon):   140148 kB
Active(file):      30872 kB
Inactive(file):    63964 kB
Unevictable:        4316 kB
Mlocked:           25888 kB
HighTotal:             0 kB
HighFree:              0 kB
LowTotal:         483476 kB
LowFree:            5032 kB
SwapTotal:        250012 kB
SwapFree:         203824 kB
Dirty:                40 kB
Writeback:             0 kB
AnonPages:        211536 kB
Mapped:            65444 kB
Shmem:               312 kB
Slab:              51396 kB
SReclaimable:       7644 kB
SUnreclaim:        43752 kB
KernelStack:       10296 kB
PageTables:         8036 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:      491748 kB
Committed_AS:    5941624 kB
VmallocTotal:     286720 kB
VmallocUsed:       98620 kB
VmallocChunk:     132044 k
А вот коммандная строка запуска ядра Линукс на этой же машинке (cat /proc/cmdline):
console=ttyMT3,921600n1 root=/dev/ram vmalloc=280M slub_max_order=0 uboot_ver=2010.06 uboot_build_ver=MAIN2.2.ubt.3090 lcm=1-lt5002f_otm8009a_24bits fps=2994






А теперь для сравнения то же с линукс сервера, с обьемом памяти в 6 гигабайт, не имеющего никаких проблем с полноценным использованием SWAP:
[root@maze ~]# cat /proc/meminfo
MemTotal:        6114780 kB
MemFree:          227420 kB
Buffers:          626516 kB
Cached:          4328144 kB
SwapCached:            0 kB
Active:          1010432 kB
Inactive:        4002316 kB
Active(anon):      53104 kB
Inactive(anon):    48584 kB
Active(file):     957328 kB
Inactive(file):  3953732 kB
Unevictable:        3496 kB
Mlocked:            3496 kB
SwapTotal:      12417084 kB
SwapFree:       12417084 kB
Dirty:                80 kB
Writeback:             0 kB
AnonPages:         61468 kB
Mapped:            28204 kB
Shmem:             41320 kB
Slab:             761208 kB
SReclaimable:     739592 kB
SUnreclaim:        21616 kB
KernelStack:        1480 kB
PageTables:         7996 kB
NFS_Unstable:          0 kB
Bounce:                0 kB
WritebackTmp:          0 kB
CommitLimit:    15474472 kB
Committed_AS:     364096 kB
VmallocTotal:   34359738367 kB
VmallocUsed:      104396 kB
VmallocChunk:   34359619772 kB
HardwareCorrupted:     0 kB
AnonHugePages:      2048 kB
HugePages_Total:       0
HugePages_Free:        0
HugePages_Rsvd:        0
HugePages_Surp:        0
Hugepagesize:       2048 kB
DirectMap4k:       94144 kB
DirectMap2M:     6197248 kB

[root@maze ~]# cat /proc/cmdline
BOOT_IMAGE=/vmlinuz-3.8.13-100.fc17.x86_64 root=UUID=fee62fe3-6c6e-425c-b87e-6f7af2c9ae3c ro rd.md=0 rd.lvm=0 rd.dm=0 SYSFONT=True KEYTABLE=us rd.luks=0 LANG=en_US.UTF-8 rhgb quiet nouveau.modeset=0 rd.driver.blacklist=nouveau
Что мы видим. Мы видим что при старте ядра Android ему принудительно установили vmalloc=280M , в то время как у линукс сервера, этот параметр практически не ограничен. Похоже ключ к "полноценному использованию памяти" именно в этом параметре. Осталось разобраться как его изменить чтобы "погираться". Абидна будет, если его можно менять только "ковыряясь в образе" и перепрошивая boot. В общем, если кто знает как это сделать боее "оперативным способом" - киньте ссылку на поисание в комменты.

Дополнение 22 июля.

Как видно из /proc/meminfo (cat /proc/meminfo) и сравнения  значений
VmallocTotal:     286720 kB
VmallocUsed:       98620 kB
VmallocChunk:     132044 k
А также их "динамики". после освобождения памяти например с помощью "FMR memory cleaner", максимальный размер паяти, используемой Android жестко задан  через
VmallocTotal. При освобождении памяти "клеанерами", увеличивается свободное место в этой обламти (значение VmallocChunk), и уменьшается "занятое" (VmallocUsed). И НИКАКОЙ SWAP  тут ниченм помочь не может, пока не будет выяснено КАК изменить коммандную строку, передаваемую ядру при запуске. Мало того, изменив коммандную строку, можно даже без свапа добавить метров 60-80 за счет "кешей", которые у нас не очень то и нужны, учитывая что флэши работают побыстрее винтов, настолько побыстрее что быстрые флеши иногда используют для кеширования данных винтов. В общем к вопросу целесообразности SWAP можно возвращаться ТОЛЬКО после решения вопроса "как изменить командную строку запуска ядра", а без этого включение SWAP больше напоминает вариант мазохизма, или "искусства ради искусства". В лучшем случае работа машинки не сильно ухудшится (если swapiness в system.ctl поставить поменьше), но вот точно лучше от этого не станет, по вышеуказанной причине. Сколько Вы не добавьте ему СВАП, а количество памяти для JAVA машин, в которых работают программы Android ЖЕСТКО ограничено параметром vmalloc=280M при старте ядра. И при этом хорошо видно что в 512ти метровом Android, более 120метров "гуляет" в виде "кешей", которые безболезненно можно урезать на 2/3 в виду отсутствия механического HDD, и которые втройне бесполезны, когда нет собственно SWAP.

Добавлено 24 июля. 
Командная строка запуска ядра (по кр мере кастаельно vmalloc), жестко вкомпилена в ядро. Вот  исходника ядра ThunderZap 1.1: https://github.com/varunchitre15/thunderzap_canvas_2 
А вот строка из конфигов этого ядра:
CONFIG_CMDLINE="console=ttyMT3,921600n1 root=/dev/ram vmalloc=280M slub_max_order=0"
В общем "доктор сказал в морг, значит"... В смысле только пересборка ядра, когда руки дойдут и время будет.

2 комментария:

  1. Спасибо за обширный анализ!

    ОтветитьУдалить
  2. Абсолютно верно. Осталось ток пересобрать ядро. Что проблематично в силу отсутствия ваааще каких либо доков, сырцов и прочее.

    vladicusmagnus@gmail.com

    ОтветитьУдалить

Закрыть окно X
Пожалуйста, потратьте несколько секунд на поддержку блога и его автора
Нажмите на рекламную ссылку: Рекламная ссылка для поддержки блога, или на баннер вверху справа страницы.