Блуж­дая по форумам и раз­ного рода сай­там, пос­вящен­ным Android, мы пос­тоян­но стал­кива­емся с совета­ми, как уве­личить про­изво­дитель­ность смар­тфо­на. Одни рекомен­дуют вклю­чить swap, дру­гие — добавить спе­циаль­ные зна­чения в build.prop, третьи — изме­нить перемен­ные ядра Linux. Подоб­ного рода рецеп­тов в раз­ных вари­антах мож­но най­ти огромное количес­тво, что на XDA, что на 4PDA. Но работа­ют ли они на самом деле?
 

Введение

Поль­зуясь самыми раз­ными *nix-сис­темами на про­тяже­нии пос­ледних десяти лет, я всег­да удив­лялся, с каким упорс­твом некото­рые, казалось бы, гра­мот­ные поль­зовате­ли смар­тфо­нов пыта­ются впих­нуть общес­твен­ности свои идеи опти­маль­ной нас­трой­ки Android и лежаще­го в его осно­ве ядра Linux. И лад­но бы дело огра­ничи­валось лег­ким тюнин­гом под­систе­мы управле­ния вир­туаль­ной памятью или вклю­чени­ем экспе­римен­таль­ных опций. Нет, обыч­но нам пред­лага­ют при­менить длин­нющие скрип­ты, изме­няющие бук­валь­но каж­дую перемен­ную ядра, перемон­тиру­ющие фай­ловые сис­темы с раз­ными стран­ными опци­ями, вклю­чающие swap, акти­виру­ющие раз­личные сис­темные демоны и выпол­няющие еще мил­лиар­ды раз­личных опе­раций.

Нет, ну мож­но, конеч­но, пред­положить, что ядро Linux, Android и фир­менные про­шив­ки для смар­тфо­нов раз­рабаты­вают без­гра­мот­ные иди­оты, работу которых необ­ходимо кар­диналь­ным обра­зом переде­лывать, но на прак­тике почему‑то ока­зыва­ется, что самые извес­тные инс­тру­мен­ты тюнин­га, опуб­ликован­ные на XDA, — это не что иное, как сбор­ная солян­ка из огромно­го количес­тва раз­рознен­ных рекомен­даций, при­думан­ных непонят­но кем и неиз­вес­тно зачем. Абсурд ситу­ации доходит того, что в этих инс­тру­мен­тах мож­но обна­ружить стро­ки, без изме­нений ско­пиро­ван­ные из скрип­тов для уве­личе­ния про­изво­дитель­нос­ти Linux-сер­вера в усло­виях высоких наг­рузок (я не шучу, взгля­ни на содер­жимое извес­тно­го скрип­та ThunderBolt!).

В целом ситу­ация более чем запутан­ная. Все совету­ют всё, ник­то не совету­ет ничего, а те, кто что‑то понима­ют, сидят и, попивая чай, сме­ются над про­исхо­дящим балага­ном. Но поп­робу­ем все‑таки раз­грес­ти всю эту кашу.

Pimp My Rom — один из самых известных инструментов тюнинга Android
Pimp My Rom — один из самых извес­тных инс­тру­мен­тов тюнин­га Android
 

Swap

Нач­нем со swap — самой абсур­дной идеи из всех, что толь­ко мож­но при­думать для при­мене­ния в смар­тфо­нах. Ее смысл в том, что­бы соз­дать и под­клю­чить файл под­качки, за счет чего удас­тся осво­бодить полез­ное прос­транс­тво в опе­ратив­ной памяти. Сама по себе идея, конеч­но, здра­вая, но толь­ко если речь идет о сер­вере, которо­му инте­рак­тивность никуда не упи­рает­ся. На смар­тфо­не регуляр­но исполь­зуемый файл под­качки при­ведет к неил­люзор­ным лагам, воз­ника­ющим вследс­твие про­махов мимо кеша, — дос­таточ­но пред­ста­вить, что будет, если при­ложе­ние попыта­ется отоб­разить одну из сво­их пик­тограмм, а она ока­жет­ся в сво­пе, который при­дет­ся вновь заг­ружать с дис­ка, пред­варитель­но осво­бодив мес­то путем помеще­ния в своп дан­ных дру­гого при­ложе­ния. Ужас.

Не­кото­рые юзе­ры могут воз­разить, что на самом деле пос­ле вклю­чения swap никаких проб­лем не воз­ника­ет, но за это надо бла­года­рить механизм lowmemorykiller, который регуляр­но уби­вает осо­бо раз­дувши­еся и дав­но не исполь­зуемые при­ложе­ния. Бла­года­ря ему девайс с 1 Гб памяти может никог­да и не дой­ти до необ­ходимос­ти сбро­са дан­ных в своп. Он же и явля­ется при­чиной того, почему в отли­чие от Linux-дес­кто­па в Android своп не нужен.

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

 

zRAM

Swap дей­стви­тель­но очень мед­ленный, и даже на дес­кто­пе его сущес­тво­вание зачас­тую неоп­равдан­но, но что, если обма­нуть сис­тему? Соз­дадим вир­туаль­ный диск пря­мо в опе­ратив­ке с встро­енной фун­кци­ей сжа­тия дан­ных, под­клю­чим его как swap — и вуаля. Фун­кция сжа­тия дан­ных доволь­но дешева даже для сов­ремен­ных мобиль­ных про­цес­соров, поэто­му мы смо­жем рас­ширить раз­мер опе­ратив­ки прак­тичес­ки без потерь про­изво­дитель­нос­ти.

Идея нас­толь­ко пра­виль­ная, что даже Google рекомен­дует при­менять zRAM для осно­ван­ных на KitKat устрой­ствах в том слу­чае, если объ­ем опе­ратив­ки не пре­выша­ет 512 Мб. Заг­воз­дка толь­ко в том, что спо­соб работа­ет лишь для сов­ремен­ных бюд­жетни­ков, то есть устрой­ств, осно­ван­ных на мно­гоядер­ных бюд­жетных про­цах от какой‑нибудь MTK и 512 Мб опе­ратив­ки. В этом слу­чае поток шиф­рования мож­но вынес­ти на отдель­ное ядро и вооб­ще не парить­ся о про­изво­дитель­нос­ти.

На уста­рев­ших устрой­ствах с одним ядром, для которых «гуру форумов» и рекомен­дуют при­мене­ние дан­ной тех­нологии, мы вновь получим лаги, при­чем в доволь­но боль­шом количес­тве. То же, кста­ти, отно­сит­ся и к тех­нологии KSM (Kernel SamePage Merging), которая поз­воля­ет объ­еди­нять оди­нако­вые стра­ницы памяти, осво­бож­дая таким обра­зом прос­транс­тво. Она так­же рекомен­дована Google, но на ста­рых девай­сах при­водит к еще боль­шим лагам, что впол­не логич­но, учи­тывая пос­тоян­но активный ядер­ный поток, который неп­рерыв­но ходит по памяти в поис­ках дуб­ликатов стра­ниц (а так ли мно­го этих дуб­ликатов на самом деле?).

Вер­дикт: зависит от устрой­ства, в боль­шинс­тве слу­чаев замед­ляет сис­тему.

 

Seeder

В свое вре­мя это при­ложе­ние надела­ло мно­го шума и породи­ло мно­жес­тво ана­логов. В Сети появи­лось огромное количес­тво сооб­щений о яко­бы феноме­наль­ном при­рос­те про­изво­дитель­нос­ти смар­тфо­на пос­ле его уста­нов­ки. Доморо­щен­ные сбор­щики кас­томных про­шивок начали вклю­чать его в свои сбор­ки, а автор был объ­явлен спа­сите­лем. И все это при том, что Seeder не выпол­нял никаких гряз­ных хаков, а прос­то исправ­лял один глу­пый баг Android.

Ес­ли вкрат­це, то баг сос­тоял в том, что некото­рые высоко­уров­невые ком­понен­ты сре­ды исполне­ния Android активно исполь­зовали файл /dev/random для получе­ния энтро­пии/соли. В какие‑то момен­ты буфер /dev/random опус­тошал­ся, и сис­тема ока­зыва­лась заб­локиро­вана до момен­та его запол­нения необ­ходимым количес­твом дан­ных. А так как запол­нялся он тем, что пос­тупало с раз­ных дат­чиков, кно­пок и сен­соров смар­тфо­на, то вре­мени на эту про­цеду­ру ухо­дило столь­ко, что поль­зователь успе­вал заметить лаг.

Для решения этой проб­лемы автор Seeder взял Linux-демон rngd, ском­пилиро­вал его для Android и нас­тро­ил так, что­бы он брал слу­чай­ные дан­ные из гораз­до более быс­тро­го (но и нам­ного более пред­ска­зуемо­го) /dev/urandom и каж­дую секун­ду сли­вал их в /dev/random, не поз­воляя пос­ледне­му исто­щить­ся. Как резуль­тат — сис­тема никог­да не испы­тыва­ла недос­татка в энтро­пии и спо­кой­но работа­ла.

Дан­ный баг был зак­рыт Google еще в Android 3.0, и, казалось бы, нам незачем вспо­минать о Seeder. Но дело в том, что при­ложе­ние с тех пор активно раз­вивалось и даже сегод­ня рекомен­дует­ся мно­гими «экспер­тами» для при­мене­ния. Более того, у при­ложе­ния появи­лось нес­коль­ко ана­логов (нап­ример, sEFix), а мно­гие соз­датели скрип­тов/инс­тру­мен­тов для уско­рения до сих пор вклю­чают подоб­ную фун­кци­ональ­ность в свои тво­рения. Иног­да это тот же самый rngd, иног­да — демон haveged, иног­да прос­то сим­линк /dev/urandom на /dev/random.

sEFix — один из наследников Seeder
sEFix — один из нас­ледни­ков Seeder

Все, кто про­бовал, напере­бой кри­чат об эффектив­ности решения, одна­ко, если верить Рикар­ду Сер­кей­ре (Ricardo Cerqueira) из ком­пании Cyanogen, в сов­ремен­ных вер­сиях Android /dev/random исполь­зует­ся все­го тре­мя ком­понен­тами: libcrypto (для шиф­рования SSL-соеди­нений, генера­ции клю­чей SSH и так далее), wpa_supplicant/hostapd (для генера­ции WEP/WPA-клю­чей) и нес­коль­кими биб­лиоте­ками для генера­ции слу­чай­ных ID при соз­дании фай­ловых сис­тем ext2/3/4.

Эф­фектив­ность при­ложе­ния в сов­ремен­ном Android, по его мне­нию, свя­зана вов­се не с попол­нени­ем пула /dev/random, а с тем, что rngd пос­тоян­но про­буж­дает устрой­ство и зас­тавля­ет его повышать час­тоту про­цес­сора, что позитив­но ска­зыва­ется на про­изво­дитель­нос­ти и негатив­но на батарее.

Вер­дикт: пла­цебо.

 

Odex

Сто­ковые про­шив­ки смар­тфо­нов всег­да одек­сирова­ны. Это зна­чит, что наряду со стан­дар­тны­ми для Android пакета­ми при­ложе­ний в фор­мате APK в катало­гах /system/app/ и /system/priv-app/ (начиная с KitKat) так­же находят­ся одно­имен­ные фай­лы с рас­ширени­ем odex. Они содер­жат так называ­емый опти­мизи­рован­ный байт‑код при­ложе­ния, уже про­шед­ший через верифи­катор и опти­миза­тор вир­туаль­ной машины и записан­ный в обо­соб­ленный файл (это дела­ется с помощью ути­литы dexopt).

Смысл сущес­тво­вания фай­лов odex в том, что­бы раз­гру­зить вир­туаль­ную машину и таким обра­зом уско­рить запуск при­ложе­ний (сто­ковых). С дру­гой сто­роны, фай­лы odex меша­ют вно­сить в про­шив­ку модифи­кации, соз­дают проб­лемы с обновле­нием, и по этой при­чине мно­гие кас­томные ROM’ы (вклю­чая CyanogenMod) рас­простра­няют­ся без них. Вер­нуть (точ­нее, сге­нери­ровать) фай­лы odex мож­но раз­ными спо­соба­ми, в том чис­ле с помощью прос­тых ути­лит/скрип­тов вро­де Odexer Tool. Поль­зовать­ся ими лег­ко, и мно­гие «экспер­ты» совету­ют это делать.

Проб­лема толь­ко в том, что это чис­тей­шее пла­цебо. Не обна­ружив odex-фай­лов в катало­ге /system, сис­тема сама соз­даст их при сле­дующей заг­рузке и помес­тит в каталог /system/dalvik-cache/. Имен­но этим она занима­ется, ког­да при заг­рузке новой про­шив­ки на экра­не появ­ляет­ся сооб­щение «Идет опти­миза­ция при­ложе­ний...». В отно­шении при­ложе­ний из мар­кета это тоже, кста­ти, работа­ет. Но на эта­пе уста­нов­ки соф­та.

Вер­дикт: пла­цебо.

 

Твики lowmemorykiller

Ре­али­зация мно­гоза­дач­ности в Android силь­но отли­чает­ся от дру­гих мобиль­ных ОС и осно­вана на клас­сичес­кой модели. При­ложе­ния могут спо­кой­но работать в фоне, в сис­теме нет никаких огра­ниче­ний на их количес­тво, фун­кци­ональ­ность при перехо­де к фоново­му исполне­нию не уре­зает­ся. Все, как на дес­кто­пе, за исклю­чени­ем одной детали: сис­тема име­ет пол­ное пра­во убить любое фоновое при­ложе­ние в слу­чае недос­татка опе­ратив­ной памяти или (начиная с KitKat) излишней жад­ности при­ложе­ния к ресур­сам.

Этот механизм, наз­ванный lowmemorykiller, был при­думан для того, что­бы, сох­раняя чер­ты пол­ноцен­ной мно­гоза­дач­ной ОС, Android мог нор­маль­но жить в усло­виях огра­ничен­ного объ­ема памяти и отсутс­тву­юще­го swap-раз­дела. Поль­зователь может спо­кой­но запус­кать любые при­ложе­ния и быс­тро перек­лючать­ся меж­ду ними, а сис­тема сама позабо­тит­ся о завер­шении дав­но не исполь­зуемых при­ложе­ний и о том, что­бы в устрой­стве всег­да оста­валась сво­бод­ная память.

В пер­вые годы сущес­тво­вания Android наз­начение дан­ного механиз­ма для мно­гих поль­зовате­лей было непонят­ным, поэто­му ста­ли популяр­ными так называ­емые таск‑кил­леры — при­ложе­ния, которые вре­мя от вре­мени про­сыпа­лись и завер­шали все фоновые при­ложе­ния. Про­фитом в дан­ном слу­чае счи­талось боль­шое количес­тво сво­бод­ной опе­ратив­ки, что вос­при­нима­лось как плюс, хотя никаких плю­сов в этом, конеч­но же, не было. Зато было мно­го минусов в виде более дол­гого перек­лючения меж­ду при­ложе­ниями, повышен­ного рас­хода заряда батареи и проб­лем c про­буж­дени­ем вла­дель­ца по утрам (будиль­ник тоже уби­вал­ся).

Со вре­менем понима­ние прин­ципов мно­гоза­дач­ности приш­ло, и от таск‑кил­леров пос­тепен­но отка­зались. Одна­ко их быс­тро сме­нил дру­гой тренд — тюнинг самого механиз­ма lowmemorykiller (нап­ример, с помощью при­ложе­ния MinFreeManager). Основная идея метода в том, что­бы при­под­нять гра­ницы запол­нения опе­ратив­ной памяти, при дос­тижении которых сис­тема нач­нет уби­вать фоновые при­ложе­ния. Эта­кий спо­соб «и нам и вам», который поз­воля­ет осво­бодить нем­ного памяти штат­ными средс­тва­ми, не нарушая идей мно­гоза­дач­ности Android.

Но к чему это в ито­ге при­водит? Допус­тим, стан­дар­тные зна­чения гра­ниц запол­нения памяти — это 4, 8, 12, 24, 32 и 40 Мб, то есть при дос­тижении сво­бод­ного объ­ема памяти 40 Мб будет уби­то одно из кеширо­ван­ных при­ложе­ний (заг­ружено в памяти, но не запуще­но, это такая опти­миза­ция Android), при 32 — Content Provider, не име­ющий кли­ентов, 24 — одно из ред­ко исполь­зуемых фоновых при­ложе­ний, затем в рас­ход идут сер­висные про­цес­сы при­ложе­ний (нап­ример, сер­вис музыкаль­ного про­игры­вате­ля), видимые на экра­не при­ложе­ния и текущее запущен­ное при­ложе­ние. Раз­ница меж­ду пос­ледни­ми дву­мя в том, что «текущее» — это при­ложе­ние, с которым в дан­ный момент име­ет дело юзер, а «видимое» — это то, что, нап­ример, име­ет уве­дом­ление в стро­ке сос­тояния или отоб­ража­ет поверх экра­на какую‑либо инфу.

В целом все это зна­чит, что в смар­тфо­не всег­да будет сво­бод­но 40 Мб памяти, которых впол­не дос­таточ­но для того, что­бы вмес­тить еще одно при­ложе­ние, пос­ле чего прос­нется поток LKM и нач­нет очис­тку памяти. Все ОК, все доволь­ны. Сис­тема по мак­симуму исполь­зует память. А теперь пред­ста­вим, что будет, если юзер вос­поль­зует­ся советом доморо­щен­ного «экспер­та» и под­нимет эти зна­чения так, что пос­леднее будет сос­тавлять, ну, допус­тим, 100 Мб (обыч­но повыша­ются толь­ко три пос­ледних зна­чения). В этом слу­чае про­изой­дет одна прос­тая вещь: юзер потеря­ет 100 – 40 = 60 Мб памяти устрой­ства. Вмес­то того что­бы исполь­зовать это прос­транс­тво для хра­нения фоновых при­ложе­ний, что полез­но, так как сок­раща­ет вре­мя перек­лючения на них и заряд батареи, сис­тема будет оставлять его сво­бод­ным непонят­но для чего.

Спра­вед­ливос­ти ради сто­ит ска­зать, что тюнинг LKM может быть полезен для девай­сов с сов­сем уж неболь­шим объ­емом памяти (мень­ше 512) и Android 4.X на бор­ту или для вре­мен­ного уве­личе­ния порогов. Некото­рые раз­работ­чики тви­ков пря­мо рекомен­дуют исполь­зовать «агрессив­ные» нас­трой­ки толь­ко в слу­чае запус­ка тяжело­го соф­та вро­де hi-end игр, а все осталь­ное вре­мя оста­вать­ся на стан­дар­тных. В этом дей­стви­тель­но есть смысл.

MinFreeManager — приложения для тюнинга механизма lowmemorykiller
MinFreeManager — при­ложе­ния для тюнин­га механиз­ма lowmemorykiller

Вер­дикт: луч­ше не тро­гать.

 

Твики I/O

В скрип­тах, пуб­лику­емых на форумах, мож­но час­то встре­тить тви­ки под­систе­мы вво­да‑вывода. Нап­ример, в том же скрип­те ThunderBolt! есть сле­дующие стро­ки:

echo 0 > $i/queue/rotational;
echo 1024 > $i/queue/nr_requests;

Пер­вая дает пла­ниров­щику вво­да‑вывода понять, что он име­ет дело с твер­дотель­ным дис­ком, вто­рая уве­личи­вает мак­сималь­ный раз­мер оче­реди вво­да‑вывода с 128 до 1024 (перемен­ная $i в коман­дах содер­жит путь к дереву блоч­ного устрой­ства в /sys, нап­ример /sys/block/mmcblk0/, скрипт про­ходит по ним в цик­ле). Далее по тек­сту мож­но встре­тить сле­дующие стро­ки, отно­сящи­еся к пла­ниров­щику CFQ:

echo 1 > $i/queue/iosched/back_seek_penalty;
echo 1 > $i/queue/iosched/low_latency;
echo 1 > $i/queue/iosched/slice_idle;

Да­лее сле­дует еще нес­коль­ко строк, отно­сящих­ся к дру­гим пла­ниров­щикам (кста­ти, обра­ти вни­мание на совер­шенно лиш­ние точ­ки с запятой в кон­це команд). Что во всех этих стро­ках не так? Пер­вые две коман­ды бес­смыс­ленны по двум при­чинам:

  1. Пла­ниров­щики I/O в сов­ремен­ном ядре Linux сами спо­соб­ны понять, с каким типом носите­ля информа­ции они име­ют дело.
  2. Та­кая длин­ная оче­редь вво­да‑вывода (1024) совер­шенно бес­смыс­ленна на смар­тфо­не. Более того, она бес­смыс­ленна даже на дес­кто­пе и при­меня­ется на высоко­наг­ружен­ных сер­верах (из рекомен­даций по нас­трой­ке которых она, видимо, и попала в дан­ный скрипт).
Часть скрипта ThunderBolt!
Часть скрип­та ThunderBolt!

Пос­ледние три бес­смыс­ленны по той прос­той при­чине, что для смар­тфо­на, где фак­тичес­ки нет раз­деления при­ложе­ний по при­ори­тетам на ввод‑вывод и нет механи­чес­ких накопи­телей, луч­ший пла­ниров­щик — это noop, то есть прос­тая FIFO-оче­редь — кто пер­вый обра­тил­ся к памяти, тот и получил дос­туп. И у дан­ного пла­ниров­щика нет каких‑то осо­бен­ных нас­тро­ек. Поэто­му все эти мно­гоэк­ранные спис­ки команд луч­ше заменить на один прос­той цикл:

for i in /sys/block/mmc*; do
echo noop > $i/queue/scheduler
echo 0 > $i/queue/iostats
done

Кро­ме вклю­чения пла­ниров­щика noop, для всех накопи­телей он отклю­чает накоп­ление ста­тис­тики I/O, что так­же дол­жно позитив­но ска­зать­ся на про­изво­дитель­нос­ти (хотя это все­го лишь кап­ля в море, которая будет совер­шенно незамет­на).

Еще один твик, который час­то мож­но най­ти в скрип­тах тюнин­га про­изво­дитель­нос­ти, — это уве­личе­ние зна­чения readahead для кар­ты памяти до 2 Мб. Механизм readahead пред­назна­чен для заб­лагов­ремен­ного чте­ния дан­ных с носите­ля еще до того, как при­ложе­ние зап­росит дос­туп к этим дан­ным. Если ядро видит, что кто‑то дос­таточ­но дол­го чита­ет дан­ные с носите­ля, оно пыта­ется вычис­лить, какие дан­ные понадо­бят­ся при­ложе­нию в даль­нейшем, и заранее заг­рузит их в опе­ратив­ку, поз­воляя таким обра­зом сок­ратить вре­мя их отда­чи.

Зву­чит кру­то, но, как показы­вает прак­тика, алго­ритм readahead очень час­то оши­бает­ся, что при­водит к лиш­ним опе­раци­ям вво­да‑вывода и рас­ходу опе­ратив­ной памяти. Высокие зна­чения readahead (1–8 Мб) рекомен­дуют­ся к при­мене­нию на RAID-мас­сивах, тог­да как на дес­кто­пе или смар­тфо­не луч­ше все оста­вить как есть, то есть 128 Кб.

Изменить планировщик ввода-вывода можно с помощью Trickster Mod
Из­менить пла­ниров­щик вво­да‑вывода мож­но с помощью Trickster Mod

Вер­дикт: кро­ме noop, не нуж­но ничего.

Оптимизация баз данных

Скрипт для опти­миза­ции баз дан­ных нас­тро­ек сис­темы и при­ложе­ний. Для работы, естес­твен­но, тре­бует­ся root и BusyBox.

#!/system/bin/sh
for i in \
`busybox find /data -iname "*.db"`;
do \
/system/xbin/sqlite3 $i 'VACUUM;';
/system/xbin/sqlite3 $i 'REINDEX;';
done;
 

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

Кро­ме под­систе­мы I/O, при­нято так­же тюнин­говать под­систе­му управле­ния вир­туаль­ной памятью. Зачас­тую изме­нению под­верга­ются толь­ко две перемен­ные ядра: vm.dirty_background_ratio и vm.dirty_ratio, которые поз­воля­ют регули­ровать раз­мер буферов для хра­нения так называ­емых гряз­ных дан­ных, то есть тех дан­ных, которые были записа­ны на диск при­ложе­нием, но еще до сих пор находят­ся в опе­ратив­ной памяти и ждут, пока они будут записа­ны на диск.

Стан­дар­тные зна­чения этих перемен­ных в дес­ктоп­ных Linux-дис­три­бути­вах и Android при­мер­но сле­дующие:

vm.dirty_background_ratio = 10
vm.dirty_ratio = 20

Это зна­чит, что при дос­тижении раз­мера буфера «гряз­ных» дан­ных в 10% от все­го объ­ема опе­ратив­ки прос­нется ядер­ный поток pdflush и нач­нет записы­вать дан­ные на диск. Если же опе­рации записи дан­ных на диск будут слиш­ком интенсив­ными и, даже нес­мотря на работу pdflush, буфер будет про­дол­жать рас­ти, то при дос­тижении 20% от объ­ема опе­ратив­ки сис­тема перек­лючит все пос­леду­ющие опе­рации записи в син­хрон­ный режим (без пред­варитель­ной буфери­зации) и работа пишущих на диск при­ложе­ний будет заб­локиро­вана до того момен­та, пока дан­ные не будут записа­ны на диск (в тер­миноло­гии Android это при­нято называть лагом).

При этом важ­но понимать, что, даже если раз­мер буфера не дос­тиг 10%, сис­тема так или ина­че запус­тит поток pdflush через 30 с. Что нам дают эти зна­ния? Фак­тичес­ки ничего, что мы мог­ли бы исполь­зовать в сво­их целях. Ком­бинация 10/20% впол­не разум­на и, нап­ример, на смар­тфо­не с 1 Гб памяти сос­тавля­ет при­мер­но 100/200 Мб памяти, чего более чем дос­таточ­но в усло­виях ред­ких всплес­ков записи, ско­рость которых зачас­тую ниже ско­рос­ти записи в сис­темную NAND-память или SD-кар­ту (при уста­нов­ке соф­та или копиро­вании фай­лов с ком­па). Но соз­датели скрип­тов опти­миза­ции с этим, конеч­но же, не сог­ласны.

Нап­ример, в скрип­те Xplix мож­но най­ти при­мер­но такие стро­ки (в ори­гина­ле они нам­ного длин­нее из‑за про­верок на количес­тво опе­ратив­ной памяти и исполь­зования BusyBox):

sysctl -w vm.dirty_background_ratio=50
sysctl -w vm.dirty_ratio=90

Дан­ные коман­ды при­меня­ются к устрой­ствам с 1 Гб памяти, то есть уста­нав­лива­ют лимиты «гряз­ного» буфера, рав­ные (при­мер­но) 500/900 Мб. Такие высокие зна­чения абсо­лют­но бес­смыс­ленны для смар­тфо­на, так как работа­ют толь­ко в усло­виях пос­тоян­ной интенсив­ной записи на диск, то есть опять же для высоко­наг­ружен­ного сер­вера. В ситу­ации со смар­тфо­ном они будут ничем не луч­ше стан­дар­тных. Кста­ти, в скрип­те ThunderBolt! при­меня­ются гораз­до более разум­ные (и близ­кие к стан­дар­тным) зна­чения, но я сом­нева­юсь, что от их при­мене­ния поль­зователь заметит хоть какую‑то раз­ницу:

if [ "$mem" -lt 524288 ];then
sysctl -w vm.dirty_background_ratio=15;
sysctl -w vm.dirty_ratio=30;
elif [ "$mem" -lt 1049776 ];then
sysctl -w vm.dirty_background_ratio=10;
sysctl -w vm.dirty_ratio=20;
else
sysctl -w vm.dirty_background_ratio=5;
sysctl -w vm.dirty_ratio=10;
fi;

Пер­вые две коман­ды выпол­няют­ся на смар­тфо­нах с 512 Мб опе­ратив­ки, вто­рые — с 1 Гб, третьи — с более чем 1 Гб. Но на самом деле есть толь­ко одна при­чина изме­нять стан­дар­тные зна­чения — девайс с очень мед­ленной внут­ренней памятью и/или кар­той памяти (при­вет китай­цам). В этом слу­чае разум­но раз­нести зна­чения перемен­ных, то есть сде­лать при­мер­но так:

sysctl -w vm.dirty_background_ratio=10
sysctl -w vm.dirty_ratio=60

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

Просмотр и изменение размера «грязного» буфера на Motorola Defy
Прос­мотр и изме­нение раз­мера «гряз­ного» буфера на Motorola Defy

Вер­дикт: луч­ше не тро­гать.

Бесполезные настройки build.prop

LaraCraft304 с форумов XDA Developers про­вела иссле­дова­ние и выяс­нила, что вну­шитель­ное количес­тво нас­тро­ек /system/build.prop, которые рекомен­дуют к при­мене­нию «экспер­ты», вооб­ще не сущес­тву­ют в исходном тек­сте AOSP и CyanogenMod. Вот их спи­сок:

  • ro.ril.disable.power.collapse
  • ro.mot.eri.losalert.delay
  • ro.config.hw_fast_dormancy
  • ro.config.hw_power_saving
  • windowsmgr.max_events_per_sec
  • persist.cust.tel.eons
  • ro.max.fling_velocity
  • ro.min.fling_velocity
  • ro.kernel.checkjni
  • dalvik.vm.verify-bytecode
  • debug.performance.tuning
  • video.accelerate.hw
  • ro.media.dec.jpeg.memcap
  • ro.config.nocheckin
  • profiler.force_disable_ulog
  • profiler.force_disable_err_rpt
  • ersist.sys.shutdown.mode
  • ro.HOME_APP_ADJ
 

Выводы

Су­щес­тву­ет огромное количес­тво и более мел­ких опти­миза­ций, вклю­чая «тюнинг» сетево­го сте­ка, изме­нение перемен­ных ядра Linux и Android (build.prop), но 90% из них не ока­зыва­ют никако­го вли­яния на реаль­ную про­изво­дитель­ность устрой­ства, а осталь­ные 10% либо улуч­шают одни аспекты поведе­ния устрой­ства в ущерб дру­гих, либо нас­толь­ко нез­начитель­но повыша­ют про­изво­дитель­ность, что ты это­го даже не заметишь. Из того, что реаль­но дей­ству­ет, мож­но отме­тить сле­дующее:

  • Раз­гон. Неболь­шой раз­гон поз­воля­ет повысить про­изво­дитель­ность, а андерволь­тинг — сох­ранить нем­ного батарей­ки.
  • Оп­тимиза­ция баз дан­ных. Силь­но сом­нева­юсь, что это даст замет­ный при­рост ско­рос­ти работы, но теория говорит нам, что работать дол­жно.
  • Zipalign. Забав­но, но, нес­мотря на встро­енную в Android SDK фун­кцию вырав­нивания кон­тента внут­ри APK-фай­лов, в мар­кете мож­но най­ти боль­шое количес­тво соф­та, не про­шед­шего через zipalign.
  • От­клю­чение ненуж­ных сис­темных сер­висов, уда­ление неис­поль­зуемых сис­темных и ред­ко исполь­зуемых сто­рон­них при­ложе­ний (об этом я уже писал в одной из прош­лых ста­тей).
  • Кас­томное ядро с опти­миза­циями под кон­крет­ный девайс (опять же не все ядра оди­нако­во хороши).
  • Уже опи­сан­ный пла­ниров­щик вво­да‑вывода noop.
  • Ал­горитм насыще­ния TCP westwood+. Есть доказа­тель­ства, что в бес­про­вод­ных сетях он нам­ного эффектив­нее при­меня­емо­го в Android по умол­чанию Cubic. Дос­тупен в кас­томных ядрах.
Westwood+ позволяет эффективнее утилизировать весь канал передачи данных в сетях 3G
Westwood+ поз­воля­ет эффектив­нее ути­лизи­ровать весь канал переда­чи дан­ных в сетях 3G

А осталь­ное луч­ше не тро­гать.

Оставить мнение