Победа OutOfMemoryException.

Автор: | 2 августа 2010

Доволь­но дол­го мы боро­лись за про­из­во­ди­тель­ность про­грам­мы WinDraw, а имен­но за вза­и­мо­дей­ствие меж­ду WinDraw и MS SQL Server.

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

1. Исполь­зо­ва­ние мето­да dbo.ZipUnPack в запросах(то есть на сто­роне SQL Server) постро­и­те­ля отче­тов Stimulsoft Reports.Net при­во­дил к тому, что ошиб­ка System.OutOfMemoryException появ­ля­лась гораз­до чаще!!! Пере­ве­дя выпол­не­ние это­го мето­да на сто­ро­ну сер­ве­ра при­ло­же­ний (т.е. исполь­зуя Atechnology.Components.ZipArchiver.UnZip2(byte[] classnative) ) мы зна­чи­тель­но уве­ли­чи­ли вре­мя рабо­ты SQLServer без пере­за­груз­ки!!!

2. Желез­ный апгрейд не реша­ет про­бле­му System.OutOfMemoryException, дока­за­но опыт­ным путем!!! А имен­но, с момен­та пер­во­го опи­са­ния про­бле­мы (Про­бле­ма про­из­во­ди­тель­но­сти WinDraw…) мы при­об­ре­ли новый сер­вер — Hewlett Packard Proliant DL380G6 (2xXeonQC, 32Gb опе­ра­тив­ной памя­ти), на кото­ром уста­но­ви­ли Microsoft Windows Server 2003 Ent, Microsoft SQL Server 2008 Ent. В настрой­ках Microsoft SQL Server вклю­чи­ли опцию Address Windowing Extensions (AWE). Уже на сле­ду­ю­щий день мы полу­чи­ли ошиб­ку System.OutOfMemoryException, при­чем судя по Task Manager опе­ра­тив­ная память была исполь­зо­ва­на все­го НАПОЛОВИНУ!!!

Исхо­дя из все­го это­го, и мно­же­ства сове­тов в интернете(правда боль­шин­ство сове­тов отно­си­лось к рабо­те про­грам­мы 1С с SQL Server, но про­бле­ма была очень похо­жа на нашу) — реше­но было попро­бо­вать исполь­зо­вать x64 плат­фор­му и ПО.

На Этот же самый сер­вер (Hewlett Packard Proliant DL380G6 (2xXeonQC, 32Gb опе­ра­тив­ной памя­ти)) была уста­нов­ле­на опе­ра­ци­он­ная систе­ма Microsoft Windows Server 2008 R2 Enterprise x64, Microsoft SQL Server 2008 R2 x64, опция Address Windowing Extensions (AWE) выклю­че­на (кста­ти при­шла идея попро­бо­вать вклю­чить и ее!!!). Итог потря­са­ю­щий!!!

Уже боль­ше меся­ца мы не полу­ча­ли ошиб­ки System.OutOfMemoryException, хотя опе­ра­тив­ная память исполь­зу­ет­ся прак­ти­че­ски пол­но­стью!

System.OutOfMemoryException

Исхо­дя из это­го дан­ный набор ПО счи­та­ем необ­хо­ди­мым при одно­вре­мен­ном досту­пе к SQL Server более 30 поль­зо­ва­те­лей.

З.Ы. В бли­жай­шее вре­мя попро­бу­ем вклю­чить опцию Address Windowing Extensions (AWE) и опи­шем резуль­тат!


Немно­го тех­ни­че­ской инфор­ма­ции!

Меха­низм Address Windowing Extensions (AWE), исполь­зу­е­мый в SQL Server, состо­ит из двух частей, рас­пре­де­ля­ю­щих физи­че­скую память и отоб­ра­жа­ю­щую её на Virtual Address Space (VAS) дан­но­го про­цес­са. Если физи­че­ская память рас­пре­де­ле­на, то опе­ра­ци­он­ная систе­ма уже не смо­жет её затре­бо­вать, пока исполь­зу­ю­щий её про­цесс не будет завер­шён или этот про­цесс осво­бо­дит память, вер­нув её опе­ра­ци­он­ной систе­ме. При­ло­же­ние может управ­лять и даже пол­но­стью предот­вра­щать листа­ние. Пре­иму­ще­ство меха­низ­ма mapping/unmapping в том, что одна и та же физи­че­ская стра­ни­ца может быть отоб­ра­же­на на раз­ные участ­ки VAS. На 64‑х бит­ных плат­фор­мах в unmapping нет необ­хо­ди­мо­сти, посколь­ку VAS мы име­ем доста­точ­но, что­бы вме­стить всю име­ю­щу­ю­ся физи­че­скую память.

Из тео­рии опе­ра­ци­он­ных систем, для опи­са­ния отоб­ра­же­ния стра­ни­цы VAS на физи­че­ские стра­ни­цы, систе­ма опе­ри­ру­ет запи­ся­ми таб­ли­цы стра­ниц — Page Table Entry (PTE). Внут­ри физи­че­ская стра­ни­ца опи­сы­ва­ет­ся номе­ром бло­ка стра­ниц — Page Frame Number (PFN). Из PFN мож­но полу­чить всю инфор­ма­цию о физи­че­ской стра­ни­це, кото­рую он пред­став­ля­ет. Напри­мер, PFN пока­зы­ва­ет, како­му Non-Uniform Memory Access (NUMA) — узлу при­над­ле­жит эта стра­ни­ца. В опе­ра­ци­он­ной систе­ме есть база дан­ных, хра­ня­щая сово­куп­ность PFN, кото­ры­ми систе­ма управ­ля­ет. Если стра­ни­ца в VAS явля­ет­ся закреп­лён­ной, суще­ству­ет PTE, кото­рый может ука­зы­вать или не ука­зы­вать на задей­ство­ван­ные PFN. Кон­цеп­ту­аль­но, стра­ни­ца, кото­рую пред­став­ля­ет PTE, может быть в памя­ти или нет, напри­мер, если она выгру­же­на на диск. В пер­вом слу­чае она при­вя­за­на к задей­ство­ван­но­му PFN, а в послед­нем — нет. В свою оче­редь, как толь­ко физи­че­ская стра­ни­ца при­вя­зы­ва­ет­ся к стра­ни­це в VAS, её PFN воз­вра­ща­ют­ся PTE.

Когда опе­ра­ци­он­ная систе­ма закреп­ля­ет, осво­бож­да­ет, получает/отдаёт стра­ни­цы задей­ство­ван­но­го PTE, или долж­на полу­чить немно­го инфор­ма­ции об этом (напри­мер алло­ка­ция NUMA), она долж­но задей­ство­вать бло­ки­ров­ку рабо­че­го мно­же­ства про­цес­са — что­бы обес­пе­чить ста­биль­ность при­вяз­ки PTE к PFN. Эта бло­ки­ров­ка обхо­дить­ся доволь­но доро­го и может испор­тить мас­шта­би­ру­е­мость про­цес­са.

При рас­пре­де­ле­нии физи­че­ских стра­ниц, исполь­зо­ва­ние AWE меха­низ­ма предо­став­ля­ет нам набор запи­сей PFN непо­сред­ствен­но из базы дан­ных PFN. Опе­ра­ци­он­ная систе­ма обя­за­на уста­нав­ли­вать бло­ки­ров­ку на базу дан­ных PFN во вре­мя рас­пре­де­ле­ния запи­сей PFN. Исполь­зуя меха­низм отоб­ра­же­ния AWE, Вы може­те отоб­ра­зить алло­ци­ру­е­мые запи­си PFN на VAS про­цес­са. Когда про­ис­хо­дит такое отоб­ра­же­ние, PTE алло­ци­ру­ют­ся, при­вя­зы­ва­ют­ся к PFN и отме­ча­ют­ся как бло­ки­ро­ва­ные. В этом слу­чае опе­ра­ци­он­ная систе­ма долж­на разо­во уста­но­вить бло­ки­ров­ку рабо­че­го мно­же­ство про­цес­са. При отоб­ра­же­нии обыч­ных стра­ниц, опе­ра­ци­он­ная систе­ма дела­ет это по тре­бо­ва­нию и, сле­до­ва­тель­но, долж­на будет запо­лу­чить рабо­чее мно­же­ство и уста­но­вить бло­ки­ров­ку в базе дан­ных PFN для каж­дой стра­ни­цы. Так как стра­ни­цы в памя­ти бло­ки­ро­ва­ны, в момент листа­ния эти PTE систе­мой будет игно­ри­ро­вать­ся.

На 64‑х бит­ных плат­фор­мах луч­ше назы­вать такие стра­ни­цы бло­ки­ро­ван­ны­ми стра­ни­ца­ми (locked pages), и, пожа­луй­ста, не путай­те их со стра­ни­ца­ми, бло­ки­ро­ван­ны­ми сред­ства­ми VirtualLock API. Как было опи­са­но выше, у бло­ки­ро­ван­ных стра­ниц есть два важ­ных свой­ства — они не участ­ву­ют в листа­нии, про­во­ди­мом опе­ра­ци­он­ной систе­мой, и во вре­мя рас­пре­де­ле­ния они захва­ты­ва­ют рабо­чее мно­же­ство и уста­нав­ли­ва­ют разо­вую бло­ки­ров­ку в базе дан­ных для PFN.

Пер­вое свой­ство име­ет не оче­вид­ное вли­я­ние на высо­ко­про­из­во­ди­тель­ные систе­мы, такие, как систе­мы с архи­тек­ту­рой NUMA. Оно при­во­дит к явной рези­дент­но­сти в памя­ти. Помни­те, что систе­ма закреп­ля­ет стра­ни­цы по тре­бо­ва­нию. Для рас­пре­де­ле­ния физи­че­ской памя­ти будет исполь­зо­вать­ся узел, на кото­ром выпол­ня­ет­ся обра­ща­ю­щий­ся к памя­ти поток. Толь­ко после это­го стра­ни­ца может быть выгру­же­на опе­ра­ци­он­ной систе­мой во вре­мя сво­пин­га. Далее, она может сно­ва попасть в память, опе­ра­ци­он­ная систе­ма сно­ва рас­пре­де­лит физи­че­скую стра­ни­цу узлу, на кото­ром поток про­дол­жа­ет рабо­тать с этой памя­тью. В этом слу­чае узел может ока­зать­ся уже совсем дру­гим. Такое пове­де­ние при­ве­дет к допол­ни­тель­ной нагруз­ке на при­ло­же­ния, кото­рые исполь­зу­ют для стра­ниц рези­дент­ность NUMA. Бло­ки­ров­ка стра­ни­цы поз­во­ля­ет раз­ре­шить эту про­бле­му, пол­но­стью защи­щая их от листа­ния.

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

В NUMA архи­тек­ту­ре, SQL Server Buffer Pool фик­си­ру­ет каж­дую рас­пре­де­лен­ную стра­ни­цу с выде­лен­ным для неё узлом. Дости­га­ет­ся это­го за счёт исполь­зо­ва­ния QueryWorkingSetEx. Как толь­ко стра­ни­ца рас­пре­де­ле­на, вызы­ва­ет­ся этот API, кото­рый поз­во­ля­ет узнать дета­ли рези­дент­но­сти стра­ни­цы. Дела­ет­ся это толь­ко один раз. Поэто­му вклю­че­ние locked pages для SQL Server на 64‑х бит­ной плат­фор­ме улуч­ша­ет рабо­ту с пило­об­раз­ной нагруз­кой и повы­ша­ет про­из­во­ди­тель­ность и мас­шта­би­ру­е­мость на более дли­тель­ных отрез­ках вре­ме­ни. При рабо­те SQL Server в режи­ме locked pages, Вам не нуж­но боль­ше вол­но­вать­ся о про­из­во­ди­тель­но­сти систе­мы в целом, зави­си­мо­сти от изъ­я­тия памя­ти у SQL Server, когда он участ­ву­ет в меха­низ­ме листа­ния опе­ра­ци­он­ной систе­мы, про­слу­ши­вая опо­ве­ще­ния отве­ча­ю­ще­го в систе­ме за память API, и сокра­щая своё рабо­чее мно­же­ство, когда это от него тре­бу­ют.

Давай­те под­ве­дём итог этой ста­тьи: на 64‑х бит­ных плат­фор­мах VAS мы име­ем доста­точ­но, что­бы вме­стить всю име­ю­щу­ю­ся физи­че­скую память, поэто­му веро­ят­ность полу­че­ния исклю­че­ния System.OutOfMemoryException прак­ти­че­ски исклю­че­на.

Исполь­зо­ва­ны мате­ри­а­лы:

1. http://blogs.msdn.com/b/slavao/archive/2005/04/29/413425.aspx
2. http://sqlblogcasts.com/blogs/christian/archive/2008/01/07/sql-server-memtoleave-vas-and-64-bit.aspx

Победа OutOfMemoryException.: 6 комментариев

  1. Мимо Проходил

    “… такие, каки­ми их напи­сал раз­ра­бот­чик. …”

    Ой! я изви­ня­юсь, я думал вы и есть раз­ра­бот­чик. Раз­ра­бот­чи­ки не сооб­ра­жа­ют ниче­го в MS SQL SERVER’е пото­му у вас как заказ­чи­ка такие про­бле­мы. Очень жаль.

    1. Внедренец Автор записи

      Нет, мы заказ­чи­ки. Хотя поне­мно­гу ста­но­вим­ся раз­ра­бот­чи­ка­ми 😉 Ибо раз­ра­бот­чик не спе­шит решать про­блем.
      Кста­ти, недав­но появи­лось обнов­ле­ние для MS SQL 2008 R2, кото­рое борет­ся с сете­вой утеч­кой памя­ти. Обнов­ле­ние пока доступ­но толь­ко по тре­бо­ва­нию, мы его уже уста­но­ви­ли у себя, и пока тести­ру­ем. Но резуль­та­ты уже впе­чат­ля­ют — память про­сто так не рас­тет, как рань­ше. А посте­пен­но наби­ра­ет­ся, по ночам поне­мно­гу воз­вра­ща­ет­ся. Как будем уве­рен­ны — опи­шу что это за обнов­ле­ние и как оно дей­ству­ет.
      Пока вот ссыл­ка — http://support.microsoft.com/kb/2345451

  2. Внедренец Автор записи

    Да мы и не позо­рим­ся, а пишем что есть. Схе­ма дан­ных и хра­ни­мые про­це­ду­ры такие, каки­ми их напи­сал раз­ра­бот­чик. И такая про­бле­ма не у нас одних — почи­тай­те ком­мен­та­рии https://www.windraw.net/2010/03/problema-proizvoditelnosti-windraw.html . В неко­то­рых ком­па­ни­ях и того мень­ше поль­зо­ва­те­лей, а ошиб­ка такая вре­мя от вре­ме­ни появ­ля­ет­ся…

  3. Мимо Проходил

    “…Исхо­дя из это­го дан­ный набор ПО счи­та­ем необ­хо­ди­мым при одно­вре­мен­ном досту­пе к SQL Server более 30 поль­зо­ва­те­лей…”

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

  4. Внедренец Автор записи

    1. Бил­ды от Атех­но­лод­жи — это отдель­ная исто­рия. У меня хра­нят­ся все бека­пы, кро­ме пер­вых трех… Но эти пер­вые три сто­и­ли мне очень доро­го… Нико­гда не зна­ешь, что поте­ря­ешь в новом бил­де. Не было тако­го обнов­ле­ния, после кото­ро­го поми­мо нуж­ных исправ­ле­ний мы бы не полу­чи­ли новых оши­бок (ино­гда даже уже решен­ных ранее!!!). Но об этом будет напи­са­но отдель­но, когда-нибудь. Если у нас будет Ваш новый билд — мы его с радо­стью поте­сти­ру­ем на нашей тесто­вой базе, и обя­за­тель­но опи­шем резуль­тат.

    2. Молод­цы. Одна­ко никто из Вас до это­го сооб­ще­ния ни разу не писал об этом. Ваши сотруд­ни­ки лишь сове­то­ва­ли обно­вить плат­фор­му Net Framework (вот ком­мен­та­рий — https://www.windraw.net/2010/03/problema-proizvoditelnosti-windraw.html#comment‑4)…

    3. Наша фра­за напи­са­на пра­виль­но, ибо есть еще один SQL Server и про­грам­мы от трех раз­ных раз­ра­бот­чи­ков. Все они пре­крас­но ужи­ва­ют­ся и про­блем с исполь­зо­ва­ни­ем памя­ти не воз­ни­ка­ет. Поэто­му про­бле­ма реаль­но про­яв­ля­ет­ся в связ­ке WinDraw и MS SQL Server…

  5. Александр

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

    2. sql server 2008 r2 всем насто­я­тель­но сове­ту­ем

    3. фра­за “Доволь­но дол­го мы боро­лись за про­из­во­ди­тель­ность про­грам­мы WinDraw, а имен­но за вза­и­мо­дей­ствие меж­ду WinDraw и MS SQL Server.” на самом деле, если быть чуточ­ку кор­рект­ней к ком­па­нии-раз­ра­бот­чи­ку 🙂 долж­на зву­чать так: “мы … за про­из­во­ди­тель­ность и ста­биль­ность рабо­ты ms sql server”, но это, я так…

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

*