Лек­ция № 7: Кэш про­цес­со­ра

Кэш про­цес­со­ра — это быст­ро­дей­ствую­щая па­мять не­боль­шо­го объ­ё­ма, ис­поль­зу­е­мая для умень­ше­ния (в сред­нем) вре­ме­ни до­сту­па про­цес­со­ра к мед­лен­ной опе­ра­тив­ной па­мя­ти. Кэш хра­нит ко­пию ча­сти дан­ных опе­ра­тив­ной па­мя­ти. Умень­ше­ние вре­ме­ни до­сту­па про­ис­хо­дит из-за то­го, что боль­шин­ство дан­ных, тре­буе­мых про­цес­со­ром, ока­зы­ва­ют­ся в кэ­ше, и ко­ли­че­ство об­ра­ще­ний к опе­ра­тив­ной па­мя­ти сни­жа­ет­ся.

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

со­от­но­ше­ние ско­ро­сти ра­бо­ты про­цес­со­ров и ско­ро­сти ра­бо­ты опе­ра­тив­ной па­мя­ти

Ри­су­нок 1. Со­от­но­ше­ние ско­ро­сти ра­бо­ты про­цес­со­ров
и ско­ро­сти ра­бо­ты опе­ра­тив­ной па­мя­ти. Ис­точ­ник

Кэш со­сто­ит из соб­ствен­но кэш-па­мя­ти, и кэш-кон­т­рол­ле­ра (ри­су­нок 2). Кэш-кон­т­рол­лер управ­ля­ет кэш-па­мя­тью: за­гру­жа­ет в неё нуж­ные дан­ные из опе­ра­тив­ной па­мя­ти, и воз­вра­ща­ет, ко­гда нуж­но, мо­дифи­ци­ро­ван­ные про­цес­со­ром дан­ные в опе­ра­тив­ную па­мять.

Идея функ­цио­ни­ро­ва­ния кэ­ша

Ри­су­нок 2. Идея функ­цио­ни­ро­ва­ния кэ­ша

Важ­но по­ни­мать, что кэш все­гда «по­лон», так как остав­лять часть кэш-па­мя­ти «пу­стой» бы­ло бы со­вер­шен­но не­ра­цио­наль­но. Но­вые дан­ные по­па­да­ют в кэш толь­ко пу­тём вы­тес­не­ния (за­ме­ще­ния) ка­ких-ли­бо ста­рых дан­ных.

Обыч­но кэш про­зра­чен для при­клад­ных про­грамм. Это озна­ча­ет, что про­грам­мы ра­бо­та­ют с па­мя­тью, не за­бо­тясь о су­ще­ство­ва­нии кэ­ша: кэш «пе­ре­хва­ты­ват» за­про­сы к опе­ра­тив­ной па­мя­ти, предо­став­ляя про­грам­ме тре­буе­мые дан­ные. Од­на­ко, со­вре­мен­ные си­сте­мы поз­во­ля­ют при­ло­же­нию «под­ска­зать» кэ­шу пра­виль­ное по­ве­де­ние. Это мо­жет быть сде­ла­но, на­при­мер, при по­мо­щи ко­манд пред­ва­ри­тель­ной за­груз­ки дан­ных в кэш и за­пи­си дан­ных в па­мять, ми­нуя кэш. Бы­ва­ют так­же вы­чис­ли­тель­ные си­сте­мы, в ко­то­рых кэш пол­но­стью управ­ля­ет­ся про­грам­мой: про­грам­ма мо­жет не­за­ви­си­мо ра­бо­тать с кэш-па­мя­тью и опе­ра­тив­ной па­мя­тью, и са­ма ре­ша­ет, ка­кие имен­но дан­ные хра­нить в кэ­ше.

Ко­гда про­цес­сор хо­чет про­честь (или за­пи­сать) дан­ные по ка­ко­му-ли­бо ад­ре­су опе­ра­тив­ной па­мя­ти, он пе­ре­да­ёт этот ад­рес в кон­т­рол­лер кэш-па­мя­ти. Кон­т­рол­лер по не­ко­то­ро­му ал­го­рит­му (смот­ри­те да­лее) опре­де­ля­ет, со­дер­жат­ся ли в кэш-па­мя­ти дан­ные, со­от­вет­ствую­щие по­лу­чен­но­му от про­цес­со­ра ад­ре­су. Ес­ли дан­ные най­де­ны (это со­бы­тие на­зы­ва­ет­ся по­па­да­ни­ем в кэш, cache hit), то кэш-кон­т­рол­лер вы­да­ёт тре­буе­мые дан­ные про­цес­со­ру (в слу­чае чте­ния), ли­бо пе­ре­за­пи­сы­ва­ет их по­лу­чен­ны­ми от про­цес­со­ра дан­ны­ми (в слу­чае за­пи­си). Ес­ли же дан­ные не най­де­ны (про­мах кэ­ша, cache miss), то про­из­во­дит­ся об­ра­ще­ние к опе­ра­тив­ной па­мя­ти, и про­цес­сор вы­нуж­ден ждать.

Эф­фек­тив­но­стью кэ­ша на­зы­ва­ет­ся от­но­ше­ние чис­ла по­па­да­ний кэ­ша к об­ще­му ко­ли­че­ству об­ра­ще­ний про­цес­со­ра. Эф­фек­тив­ность, та­ким об­ра­зом, — это чис­ло от 0 до 1. Ну­ле­вая эф­фек­тив­ность озна­ча­ет, что кэш ни­сколь­ко не уско­рил ра­бо­ту си­сте­мы; эф­фек­тив­ность, рав­ная еди­ни­це, озна­ча­ет, что уско­ре­ние мак­си­маль­но, и вре­мя об­ра­ще­ния к па­мя­ти опре­де­ля­ет­ся ско­ро­стью ра­бо­ты кэ­ша, а не ско­ро­стью ра­бо­ты опе­ра­тив­ной па­мя­ти. Эф­фек­тив­ность кэ­ша за­ви­сит от сле­дую­щих фак­то­ров:

  • Объ­ём кэ­ша. Чем боль­ше объ­ём кэ­ша, тем бо́льшую часть тре­буе­мых про­грам­ме дан­ных он мо­жет в се­бе со­дер­жать, тем ре­же бу­дут про­ис­хо­дить об­ра­ще­ния к опе­ра­тив­ной па­мя­ти, и тем вы­ше бу­дет об­щее быст­ро­дей­ствие си­сте­мы.
  • Ал­го­ритм функ­цио­ни­ро­ва­ния кэ­ша. К со­жа­ле­нию, за­ча­стую объ­ё­ма кэш-па­мя­ти не­до­ста­точ­но для то­го, что­бы вме­стить все не­об­хо­ди­мые для вы­чис­ле­ний дан­ные. В этом слу­чае кэш-кон­т­рол­лер дол­жен «ре­шить», ка­кие имен­но дан­ные сле­ду­ет дер­жать в кэ­ше. По­это­му кро­ме объ­ё­ма кэ­ша важ­ным яв­ля­ет­ся ал­го­ритм его функ­цио­ни­ро­ва­ния: кэш, осна­щён­ный хо­ро­шим ал­го­рит­мом, бу­дет го­раз­до эф­фек­тив­нее ис­поль­зо­вать свой объ­ём, хра­ня мень­ше не­нуж­ных дан­ных.
  • Вы­пол­ня­е­мая про­цес­со­ром про­грам­ма. Кэш ока­зы­ва­ет­ся эф­фек­тив­ным по­то­му, что боль­шин­ство ком­пью­тер­ных про­грамм об­ра­ща­ют­ся к па­мя­ти не слу­чай­ным об­ра­зом, а за­ко­но­мер­но. Чем луч­ше кэш-кон­т­рол­лер мо­жет «пред­ска­зать» об­ра­ще­ния при­ло­же­ния к па­мя­ти, тем вы­ше эф­фек­тив­ность.

За­ко­но­мер­ность об­ра­ще­ний про­грам­мы к опе­ра­тив­ной па­мя­ти обыч­но вы­ра­жа­ет­ся в том, что об­ра­ще­ния к па­мя­ти об­ла­да­ют временно́й и про­стран­ствен­ной ло­каль­но­стью:

  • Временна́я ло­каль­ность: ес­ли про­изо­шло об­ра­ще­ние к ячей­ке опе­ра­тив­ной па­мя­ти, то с боль­шой ве­ро­ят­но­стью эта ячей­ка па­мя­ти вско­ре по­на­до­бит­ся сно­ва.
  • Про­стран­ствен­ная ло­каль­ность: ес­ли про­изо­шло об­ра­ще­ние к ячей­ке опе­ра­тив­ной па­мя­ти, то с боль­шой ве­ро­ят­но­стью бу­дет про­из­ве­де­но об­ра­ще­ние к со­сед­ним ячей­кам па­мя­ти.

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

Пол­но­стью ас­со­ци­а­тив­ный кэш

Пусть ад­рес бай­та опе­ра­тив­ной па­мя­ти со­сто­ит из 32-х бит (4-х байт). Со­ста­вим кэш из строк: пусть каж­дая стро­ка со­дер­жит (хра­нит) ад­рес и байт, ко­то­рый со­от­вет­ству­ет это­му ад­ре­су в опе­ра­тив­ной па­мя­ти. Хра­ни­мый ад­рес при­ня­то на­зы­вать те­гом (tag), что­бы не пу­тать его с ад­ре­сом (но­ме­ром) строки́ кэ­ша.

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

по­иск эле­мен­та в кэ­ше по его ад­ре­су

Ри­су­нок 3. При­мер по­ис­ка эле­мен­та в кэ­ше по его ад­ре­су.
Дан­ные при­ве­де­ны в ше­ст­на­дца­те­рич­ном ви­де

Ко­гда про­цес­сор хо­чет про­честь дан­ные по ка­ко­му-ли­бо ад­ре­су опе­ра­тив­ной па­мя­ти, он пе­ре­да­ёт этот ад­рес в кон­т­рол­лер кэш-па­мя­ти. Кэш осу­ществ­ля­ет од­но­вре­мен­ное срав­не­ние всех имею­щих­ся у не­го те­гов с пе­ре­дан­ным ад­ре­сом. Ес­ли ад­рес най­ден, то кэш вы­да­ёт тре­буе­мый байт дан­ных (ри­су­нок 3). Ес­ли же дан­ные не най­де­ны (про­мах кэ­ша), то про­из­во­дит­ся об­ра­ще­ние к опе­ра­тив­ной па­мя­ти.

Ско­рее все­го, толь­ко что про­чи­тан­ные дан­ные вско­ре по­на­до­бят­ся вновь, по­это­му, в слу­чае про­ма­ха кэ­ша, их нуж­но за­не­сти в кэш. Но кэш все­гда по­лон. Это озна­ча­ет, что пе­ред за­не­се­ни­ем но­вых дан­ных ка­кие-то дру­гие дан­ные из не­го нуж­но вы­бро­сить. Ал­го­ритм, опре­де­ляю­щий, ка­кие дан­ные нуж­но вы­бро­сить из кэ­ша, на­зы­ва­ет­ся по­ли­ти­кой за­ме­ще­ния дан­ных.

Вы­бра­сы­вать нуж­но тот эле­мент, к ко­то­ро­му наи­бо­лее дол­го не бу­дет об­ра­ще­ний. Но, так как кэш не зна­ет, ка­кие об­ра­ще­ния к па­мя­ти бу­дут в бу­ду­щем, он вы­нуж­ден ис­поль­зо­вать ка­кое-то пра­ви­ло, ко­то­рое бы хо­ро­шо «уга­ды­ва­ло» нуж­ный эле­мент. На­при­мер, мож­но вы­бра­сы­вать слу­чай­ную стро­ку из кэ­ша. Но на прак­ти­ке ча­ще все­го вы­бра­сы­ва­ет­ся тот эле­мент, ко­то­рый доль­ше всех не ис­поль­зо­вал­ся. Мо­ти­ва­ция та­кая: «ес­ли стро­ка дол­го не ис­поль­зо­ва­лась, то она, ско­рее все­го, ещё не ско­ро по­на­до­бит­ся вновь».

Но как опре­де­лить, ка­кая стро­ка доль­ше всех не ис­поль­зо­ва­лась? Пусть, на­при­мер, в кэ­ше име­ют­ся 65536 строк. То­гда в каж­дую стро­ку кэ­ша мож­но до­ба­вить двух­бай­то­вое це­лое чис­ло, ко­то­рое бу­дет обо­зна­чать «воз­раст» этой строки́. Стро­ка, к ко­то­рой об­ра­ща­лись наи­бо­лее дав­но, име­ет воз­раст, рав­ный 65535. Стро­ка, к ко­то­рой бы­ло про­из­ве­де­но об­ра­ще­ние в по­след­нюю оче­редь, име­ет воз­раст 0.

до­пол­ни­тель­ные бай­ты для хра­не­ния воз­рас­та стро­ки

Ри­су­нок 4. До­пол­ни­тель­ные бай­ты для хра­не­ния воз­рас­та строки́

Пусть про­изо­шло по­па­да­ние в кэш, и со­от­вет­ствую­щая стро­ка име­ла воз­раст N. При­сво­им ей воз­раст 0, а воз­рас­ты всех осталь­ных строк, ко­то­рые бы­ли мень­ше N, уве­ли­чим на еди­ни­цу. Не­труд­но ви­деть, что по­сле та­кой опе­ра­ции все эле­мен­ты кэ­ша вновь име­ют пра­виль­ный воз­раст, со­от­вет­ствую­щий по­ряд­ку их ис­поль­зо­ва­ния. Что­бы уско­рить эту про­це­ду­ру, нуж­но снаб­дить все стро́ки кэ­ша устрой­ства­ми, од­но­вре­мен­но до­бав­ляю­щи­ми еди­ни­цу к воз­рас­ту сво­их строк. В слу­чае про­ма­ха кэ­ша из не­го вы­бра­сы­ва­ет­ся эле­мент с мак­си­маль­ным (65535) воз­рас­том, все воз­рас­ты уве­ли­чи­ва­ют­ся на еди­ни­цу, а но­вый эле­мент по­лу­ча­ет воз­раст 0.

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

Од­на­ко, ес­ли за­пись в каж­дую стро­ку кэ­ша про­ис­хо­дит в сред­нем бо­лее од­но­го ра­за до сме­ны этой строки́, то вы­год­на дру­гая стра­те­гия. Очень ча­стый сце­на­рий ра­бо­ты с кон­крет­ным эле­мен­том па­мя­ти — «за­пись, чте­ние, за­пись, чте­ние, ...». Здра­вый смысл под­ска­зы­ва­ет, что за­пись в опе­ра­тив­ную па­мять нуж­но про­из­ве­сти лишь в са­мом кон­це по­доб­ной це­поч­ки. А ко­гда у це­поч­ки опе­ра­ций со стро­кой кэ­ша на­сту­па­ет ко­нец? То­гда, ко­гда эта стро­ка вы­бра­сы­ва­ет­ся из кэ­ша.

Та­ким об­ра­зом, ко­гда стро­ка вы­бра­сы­ва­ет­ся из кэ­ша, она долж­на быть за­пи­са­на в опе­ра­тив­ную па­мять. Но что, ес­ли она не бы­ла из­ме­не­на? То­гда её не нуж­но за­пи­сы­вать. Для то­го, что­бы от­сле­жи­вать из­ме­не­ния строк кэ­ша, снаб­дим каж­дую стро­ку до­пол­ни­тель­ным би­том (ри­су­нок 5), ко­то­рый бу­дет уста­нав­ли­вать­ся в еди­ни­цу при мо­дифи­ка­ции дан­ных в стро­ке. То­гда при вы­тес­не­нии строки́ нуж­но бу­дет про­ве­рить этот бит, и, ес­ли он ра­вен еди­ни­це, про­из­ве­сти за­пись в опе­ра­тив­ную па­мять.

бит мо­дифи­ка­ции стро­ки

Ри­су­нок 5. Бит мо­дифи­ка­ции строки́

Итак, про­цес­сор за­пи­сы­ва­ет дан­ные в па­мять. Ес­ли эти дан­ные есть в кэ­ше, то они пе­ре­за­пи­сы­ва­ют­ся и по­ме­ча­ют­ся, как из­ме­нён­ные. Ес­ли дан­ных в кэ­ше нет, то са­мая ста­рая стро­ка вы­тес­ня­ет­ся, и на её ме­сто за­пи­сы­ва­ют­ся но­вые дан­ные, опять же по­ме­чен­ные как из­ме­нён­ные. Не­до­ста­ток та­ко­го под­хо­да в том, что при про­ма­хе кэ­ша те­перь ча­сто бу­дут про­ис­хо­дить две опе­ра­ции: за­пись дан­ных ста­рой строки́ из кэ­ша в опе­ра­тив­ную па­мять, и за­груз­ка тре­буе­мых дан­ных из па­мя­ти в кэш. По­это­му ино­гда де­ла­ют так, что кэш в сво­бод­ное вре­мя сам пе­ре­пи­сы­ва­ет мо­дифи­ци­ро­ван­ные дан­ные в опе­ра­тив­ную па­мять, об­ну­ляя со­от­вет­ствую­щие би­ты мо­дифи­ка­ции.

Нам оста­лось ре­шить две про­бле­мы:

  1. Наш кэш хо­ро­шо справ­ля­ет­ся с временно́й ло­каль­но­стью об­ра­ще­ния к дан­ным, но он со­вер­шен­но не адап­ти­ро­ван к про­стран­ствен­ной ло­каль­но­сти. Как быть, ес­ли про­цес­сор об­ра­ща­ет­ся к од­но­му бай­ту опе­ра­тив­ной па­мя­ти, за­тем к со­сед­не­му, и так да­лее?
  2. Раз­ра­бо­тан­ный кэш бу­дет иметь очень вы­со­кие на­клад­ные рас­хо­ды при ап­па­рат­ной реа­ли­за­ции. Дей­стви­тель­но, каж­дая стро­ка кэ­ша, по­ми­мо един­ствен­но­го бай­та дан­ных, со­дер­жит: че­ты­ре бай­та ад­ре­са, устрой­ство срав­не­ния ад­ре­сов, два бай­та для хра­не­ния воз­рас­та строки́, устрой­ство для на­ра­щи­ва­ния воз­рас­та, и бит, обо­зна­чаю­щий мо­дифи­ка­цию строки́.

Для ре­ше­ния этих про­блем бу­дем хра­нить в каж­дой стро­ке кэ­ша не один байт дан­ных, а не­сколь­ко байт, иду­щих под­ряд в опе­ра­тив­ной па­мя­ти. Те­гом строки́ бу­дем счи­тать ад­рес пер­во­го со­дер­жа­ще­го­ся в ней бай­та. Рас­смот­рим при­мер, ко­гда в стро­ке кэ­ша хра­нят­ся 16 байт. Для то­го, что­бы дан­ные в стро­ках не мог­ли «пе­ре­кры­вать­ся» (пе­ре­кры­тие дан­ных зна­чи­тель­но услож­нит ло­ги­ку ра­бо­ты), по­тре­бу­ем, что­бы те­ги всех строк бы­ли крат­ны 16. То­гда 4 по­след­них би­та те­га бу­дут рав­ны ну­лю, и их не нуж­но хра­нить. Мы ви­дим, что от­но­ше­ние «по­лез­но­го» объ­ё­ма кэ­ша к об­ще­му зна­чи­тель­но улуч­ши­лось (ри­су­нок 6).

каж­дая стро­ка кэ­ша име­ет не­сколь­ко байт дан­ных

Ри­су­нок 6. Каж­дая стро­ка кэ­ша име­ет не­сколь­ко байт дан­ных

Что­бы ско­рость ра­бо­ты кэ­ша не сни­зи­лась из-за то­го, что при каж­дом про­ма­хе тре­бу­ет­ся за­гру­жать из па­мя­ти сра­зу 16 байт, снаб­дим опе­ра­тив­ную па­мять «ши­ро­кой» ши­ной дан­ных, ко­то­рая бу­дет пе­ре­да­вать в кэш все 16 байт од­но­вре­мен­но.

При по­ис­ке дан­ных в та­ком кэ­ше по ад­ре­су сле­ду­ет взять стар­шие 28 бит ад­ре­са, и по­дать их на срав­не­ние в стро́ки кэ­ша. Ес­ли стро­ка най­де­на, то нуж­но взять из строки́ байт, опре­де­ляе­мый млад­ши­ми че­тырь­мя би­та­ми ад­ре­са. Ес­ли стро­ка не най­де­на, то тре­бу­ет­ся об­ра­ще­ние к опе­ра­тив­ной па­мя­ти.

Те­перь, ес­ли про­цес­сор бу­дет за­пра­ши­вать бай­ты из па­мя­ти под­ряд, то лишь каж­дое 16-е об­ра­ще­ние к па­мя­ти бу­дет при­во­дить к про­ма­ху кэ­ша. Ко­неч­но, есть и не­до­ста­ток: со­сед­ние 15 байт бу­дут за­гру­жать­ся (и за­ни­мать часть кэш-па­мя­ти) да­же то­гда, ко­гда они про­цес­со­ру не по­на­до­бят­ся. Мож­но услож­нить ал­го­ритм, что­бы чте­ние или за­пись дан­ных под­ряд во­об­ще не при­во­ди­ло к про­ма­хам кэ­ша: для это­го нуж­но за­гру­жать в кэш сле­дую­щие 16 байт, ес­ли про­изо­шло об­ра­ще­ние к по­след­не­му бай­ту строки́.

35 отзывов на запись «Лек­ция № 7: Кэш про­цес­со­ра»

Спа­си­бо боль­шое за ма­те­ри­ал.
Спа­си­бо ав­то­ру, ста­тья от­лич­ная!
>Ес­ли дан­ных в кэ­ше нет, то са­мая ста­рая стро­ка вы­тес­ня­ет­ся, и на её ме­сто за­пи­сы­ва­ют­ся но­вые дан­ные, опять же по­ме­чен­ные как из­ме­нён­ные Не по­нят­но — ес­ли ли­ния счи­та­на и уже по­ме­че­на как из­ме­нён­ная — то­гда её на­до бу­дет сбро­сить в па­мять да­же ес­ли про­цес­сор в неё ни­че­го не пи­сал.
А, в смыс­ле, име­лось в ви­ду что не за­гру­же­на из па­мя­ти, а что про­цес­сор в неё за­пи­сал, спа­си­бо, те­перь по­нят­но.
Спа­си­бо за ста­тью, на­пи­са­на яс­но и до­ход­чи­во!
ка­жет­ся опе­чат­ка
в N-ас­со­ци­а­тив­ном кэ­ше под боль­шой кар­тин­кой
«ес­ли тэ­ги не сов­па­ли, …уве­ли­чить воз­рас­та…
за­тем сно­ва уве­ли­чить воз­рас­та «
до­слов­но
ес­ли тэ­ги не сов­па­ли (пе­ре­за­пи­сы­вае­мые дан­ные не про­кэ­ши­ро­ва­ны), то вы­пол­ня­ют­ся сле­дую­щие дей­ствия:
сре­ди че­ты­рёх про­чи­тан­ных строк вы­би­ра­ет­ся для за­ме­ще­ния стро­ка с мак­си­маль­ным воз­рас­том; её воз­раст об­ну­ля­ет­ся, воз­рас­ты осталь­ных трёх строк уве­ли­чи­ва­ют­ся на еди­ни­цу;
….
те­перь тре­буе­мые дан­ные точ­но при­сут­ству­ют в кэ­ше (тэг од­ной из че­ты­рёх строк сов­па­да­ет с тэ­гом, вы­де­лен­ным из ад­ре­са); кон­т­рол­лер уве­ли­чи­ва­ет на еди­ни­цу воз­раст тех строк (сре­ди че­ты­рёх про­чи­тан­ных), воз­раст ко­то­рых мень­ше воз­рас­та строки́ с нуж­ны­ми дан­ны­ми, а воз­раст строки́ с нуж­ны­ми дан­ны­ми об­ну­ля­ет; P.S. хо­ро­шая стать­ся
P.P.S. ес­ли на­ве­сти кур­сор на боль­шую кар­тин­ку, то пи­шет «При-мер по-ис-ка дан-ных…»
Спа­си­бо. Ис­пра­вил. Не ду­мал, что кто-ни­будь бу­дет так вни­ма­тель­но вчи­ты­вать­ся.
Огром­ное спа­си­бо Ав­то­ру, очень по­лез­ная ста­тья.
top cash advance in 27410 payday loans
unsecured personal loan options
Take a look at my zooppa buy cialis online without a prescription.
http://canadianrxpharmacyonline.com/ online pharmacy no prescription
http://doxycyclinebrandname.accountant/#738 doryx 200 mg is doxycycline strong malaria doxycycline doxycycline shelf life doxycycline minocycline
http://generic-name-for-keflex.accountant/#448 what is cephalexin used to treat cephalexin for humans cephalexin pregnancy
http://lisinoprilhydrochlorothiazide2016.accountant/#407 drug lisinopril lisinopril 20 mg lisinopril and potassium prinivil medication lisinopril hctz side effects
http://cephalexin-cost.accountant doxycycline calcium doryx price
Вы­воз му­со­ра в СПб http://s-musor.ru/page-165749.html Му­сор пух­то
Вы­воз ме­бе­ли из квар­ти­ры на ути­ли­за­цию http://kudamusor.ru/page-429333.html Разо­брать ста­рый дом
Де­мон­таж до­ма сто­и­мость http://nanomusor.ru/page-42532.html Стро­и­тель­ные ра­бо­ты де­мон­таж
Сто­и­мость вы­но­са стро­и­тель­но­го му­со­ра из квар­ти­ры http://nanomusor.ru/page-753414.html Сколь­ко сто­ит вы­нос му­со­ра
Вы­воз тон­ны му­со­ра http://nanomusor.ru/page-592475.html Пла­сти­ко­вые кон­тей­не­ры для му­со­ра
Вы­воз ме­бе­ли де­ше­во http://nanomusor.ru/page-853681.html Вы­воз не­га­ба­рит­но­го му­со­ра
Арен­да вы­воз му­со­ра http://mega-musor.ru/page-202109.html Арен­да пух­то 27
Сло­мать ста­рый дом и вы­вез­ти му­сор http://nanomusor.ru/page-945105.html Снос зда­ний СПб
Слом и вы­воз му­со­ра http://s-musor.ru/page-132237.html Слом до­ма и вы­воз му­со­ра це­на
Вы­воз бы­то­во­го му­со­ра це­на http://s-musor.ru/page-510341.html Вы­воз му­со­ра це­на за м3
I don’t usually comment but I gotta admit thanks for the post on this great one
Rattling great visual appeal on this web site, I’d value it 10.
I really like your blog.. very nice colors & theme. Did you create this website yourself or did you hire
someone to do it for you? Plz answer back as I’m
looking to create my own blog and would like to find out where u got this from.
appreciate it
Generally I do not learn article on blogs, but I would like to say that this write-up very compelled me to try and do it!
Your writing style has been surprised me. Thank you, quite great post.
I absolutely love your blog and find a lot of your post’s to be exactly
I’m looking for. can you offer guest writers to
write content for yourself? I wouldn’t mind publishing a post or
elaborating on most of the subjects you write concerning here.
Again, awesome website!
I’m no longer certain the place you’re getting your information,
but good topic. I needs to spend a while studying more or understanding more.
Thanks for great info I was searching for this information for my mission.
Fabulous, what a website it is! This website provides useful data to us, keep it up.
As the admin of this site is working, no doubt very
quickly it will be famous, due to its feature contents.
Do you have a spam problem on this website; I also am a
blogger, and I was wondering your situation; we have developed some nice methods and we are
looking to swap methods with other folks, please shoot me an e-mail if interested.
I enjoy reading through a post that can make people think. Also, thanks for allowing me to comment!

Оставить отзыв

Жёлтые поля обязательны к заполнению

   

Можете использовать теги <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang=""> <div class=""> <span class=""> <br>