Экстрэмальная аптымізацыя JavaScript
JavaScript — прыкметная з’ява ў сённяшнім свеце. Хоць мова застаецца адносна нязменнай на працягу апошняга дзесяцігоддзя, эвалюцыя назіраецца сярод праграмістаў. Яны выкарыстоўваюць тую ж мова, якую выводзі ў выглядзе радкоў у тэксце стану для таго, каб напісаць некалькі даволі цяжкіх кліенцкіх прыкладанняў. Хоць і можа здацца, што мы ўваходзім гонкі Лада ці F1, у рэчаіснасці апошнія дзесяць гадоў мы выдаткавалі кіраванне на гоначным аўтамабілі F1 узад і наперад па дарозе. З дапамогай мовы Мы ніколі не выкарыстоўвалі ўвесь яго патэнцыял. Ён адкрыў Ajax для запуску нас з пад’езда па гоначнай трасе. Але зараз, калі мы знаходзімся на трэку, там ёсць чырвоная рыса і можам чуць скрыгат. Не вельмі шмат людзей, здаецца, ведаюць, як кіраваць балідам F1. Прынамсі, на хуткасці 250 кіламетраў у гадзіну.
Даволі лёгка націснуць нагой педаль і атрымаць да 60 міль / ч. Але вельмі хутка вам прыйдзецца змяніць тактыку, калі вы жадаеце пазбегнуць прыпынкаў. Тое ж самае ідзе з напісаннем вялікіх прыкладанняў кліентаў у JavaScript. Хуткадзейныя працэсары ствараюць уражанне, што мы можам зрабіць што-небудзь з ім. Сапраўды,для невялікіх праграм гэта апраўдана. Але калі пісаць шмат дрэннага пра JavaScript-кода, можна вельмі хутка прыйсці да сітуацыі, калі ваш код пачне "паўзці". Мы павінны асвоіць усе тонкасці гэтай мовы, калі жадаем утрымоўваць яго бесперабойным у буйных маштабах.
Зменныя
Давайце зірнём на адну з граняў праграмавання – на зменныя. Некаторыя мовы патрабуюць аб’явы зменных перад іх выкарыстаннем, а JavaScript – не. Але толькі таму, што гэта не патрабуецца, але гэта не азначае, што вы не павінны рабіць гэта. Гэта таму, што ў JavaScript, калі зменная не абвешчана відавочна з дапамогай VAR па ключавым слове, гэта разглядаецца як глабальны характар. Чаму? Таму што перакладніку неабходна высвятліць, калі і дзе зменнае пытанне была першапачаткова абвешчана, таму ён звяртаецца да пошуку. Разгледзім наступны прыклад.
function doSomething(val) { count += val; };
Ці мае колькасць значэнне, ускладзенае на яго, ці яно выходзіць за рамкі чаго-небудзь? Ці яно проста не абвешчана правільна? Акрамя таго, у вялікай праграме, маючы такія агульныя глабальныя імёны зменных, цяжка пазбегнуць сутыкненняў.
Цыклы
Пошук у сферы, дзе ланцужок для падліку ў прыведзеным вышэй прыкладзе не з’яўляецца такой вялікай справай, адбудзецца адразу. Але ў буйных вэб-прыкладаннях гэта не вельмі проста для аднаго разу. Асабліва, калі завесы турбуюць. Першае, што трэба памятаць пра завесу, што яна была створана не толькі для JavaScript, гэта аўтаматычна перамяшчае большую частку працы за межы цыкла, вядома,наколькі гэта ўвогуле магчыма. Чым менш вы ў курсе працы, тым хутчэй ваш цыкл будзе працаваць. Давайце разгледзім найболей распаўсюджаную практыку ў завесе JavaScript, якую можна пазбегнуць. Зірніце на наступны прыклад і пагледзіце, калі вы можаце выявіць гэта:
for (var i = 0; i < arr.length; i++) { // some code here }
Вы гэта бачылі? Даўжыня масіва arr пералічваецца кожны раз, калі праходзіць цыкл. Простым рашэннем для гэтага з’яўляецца вызначэнне даўжыні масіва, напрыклад:
for (var i = 0, len = arr.length; i < len; i++) { // some code here }
Такім чынам, даўжыня масіва вылічаецца толькі адзін раз, а цыкл ставіцца да значэння кожны раз, калі адбываецца ітэрацыя.
Так што ж мы можам зрабіць для падвышэння прадукцыйнасці нашых завес? Якія яшчэ працы праводзяцца на кожнай ітэрацыі? Мы ацэньваем значэнне менш, чым кошт length, а таксама павялічваем i па адным. Ці можам мы паменшыць лік аперацый? Можам, калі парадак, у якім нашы цыкл выконваюцца, не мае значэнняў.
for (var i = 100; i--; ) { // some code here }
Гэты цыкл будзе выконвацца на 50% хутчэй, чым той, што вышэй, таму што на кожнай ітэрацыі яна проста адымае значэнне так, што значэнне не з’яўляецца "falsy", іншымі словамі, яно не з’яўляецца 0, пагэтаму цыкл працягваецца. У той момант, значэнне пры 0 спыніцца ў цыкле.
Вы можаце зрабіць гэта з іншымі выглядамі завес:
while (i--) { // some code here }
Ізноў жа, паколькі адзнака і аперацыі адымання з гэтага робіцца ў той жа час, як увесь час цыкл будзе falsy ці 0, ацыкл завершыцца.
Кэшаванне
Я коратка спыніўся на кэшаванні вышэй, калі мы вызначалі масіў пэўнай даўжыні ў зменнай. Той жа прынцып можа быць ужыты ў розных месцах у кодзе JavaScript. Па сутнасці, мы не жадаем прымушаць перакладніоў рабіць лішнюю працу (адзін раз ён ужо зрабіў гэта). Так, напрыклад, калі гаворка ідзе пра сканаванне сферы ланцуга, каб знайсці глабальную зменную для нас, кэшаванне гэтай спасылкі на месцы "захоўвае выманні перакладніка кожны раз. Тут дазвольце мне праілюстраваць гэта:
var aGlobalVar = 1; function doSomething(val) { var i = 1000, agv = aGlobalVar; while (i--) { agv += val; }; aGlobalVar = agv; }; doSomething(10);
У гэтым прыкладзе aGlobalVar я ўзяў толькі два разы. Калі б мы выкарыстоўвалі яго падчас цыклу, перакладнік выняў бы гэту зменную тысячу разоў. Сапраўды, цыкл вышэй займае каля 3 мс, каб бегчы ў той час, калі avg += val; былі заменены aGlobalVar += val; тады цыкл зойме каля 10мс для запуску.
Глыбіня ўласнасці
Укладненне аб’ектаў з тым каб выкарыстоўваць кропкавую натацыю – гэта выдатны спосаб для вызначэння імёнаў і арганізацыі кода. Калі гаворка заходзіць пра прадукцыйнасць, гэта можа стаць некаторай праблемай. Кожны раз, калі ўзнікае значэнне доступу ў такога роды сцэнар, перакладнік павінен прайсці ўкладзеныя аб’екты для таго, каб дабрацца да іх значэння. Чым глыбей значэнне, тым большы абыходаў, тым даўжэй трэба чакаць. Так што, хоць найменне і з’яўляецца вялікай арганізацыйнай прыладай, захоўванне дробных рэчаў з’яўляецца, магчыма, вашай лепшай стаўкай на хуткасць працы назапашвальніка. Апошняе ўвасабленне YUI бібліятэкі накіравана на тое, каб ліквідаваць цэлы пласт гнездавання найменняў. Так, напрыклад, YAHOO.util.Anim у нас -Y.Anim.
Рэзюмэ
Гэта толькі некалькі прыкладаў таго, як палепшыць прадукцыйнасць вашага кода, надаючы ўвага таму, як інтэрпрэтатар JavaScript робіць сваю працу. Майце на ўвазе, аднак, што браўзары ўвесь час развіваюцца, нават калі гэтага не робіць мова. Так, напрыклад, сённяшнія браўзары ўкаранілі JIT кампілятары для паскарэння працы. Але гэта не значыць, што мы павінны быць меней пільнымі. Таму ўрэшце, каб вэб-прыкладанне дамаглося велізарнага поспеху, трэба лічыць кожную мілісекунду.
