 Превод. Оригиналът е на Брус Доусън: „Knowing Where to Type ‘Zero’“ За някои оптимизации са необходими сложни структури от данни и хиляди редове сорс код. В други случаи съвсем минималната намеса дава сериозен прираст на производителността и понякога е достатъчно да знаеш къде да поставиш нула. Ситуацията доста прилича на историята за локомотивния машинист, който съвсем точно знае къде да удари стоманата и предлага интересен начин да му се плаща за тази работа: $0,50 за един удар или $999,50, за да те научи къде да удряш. Идеята е, че можете да знаете много, но трябва да можете да прилагате в реалния живот това, което знаете. Значението на правилното измерване Във времената на оригиналната Xbox аз помогнах в оптимизацията на много игри. В една от тях профилирането показа функция за матрична трансформация, която отнемаше 7% от ресурса на централния процесор. В показаната диаграма това е най-големият пик. Наложи се внимателно да разгледам и оптимизирам тази функция. Виждаше се, че не съм първият, който е правил това. Функцията бе пренаписана на асемблер. Намерих някои места за потенциално подобрение на кода и се заех да измервам ефекта от тях. Това е важно, понеже лесно можеш да се заемеш с „оптимизация“, която нищо няма да промени и дори може да влоши ситуацията.
Но това измерване се оказа твърде трудно. Пусках играта, едновременно с това се занимавах с профилиране, а след това изучавах профила. Стори ми се, че има известно подобряване, но съвсем слабо. Тогава реших да използвам научния метод. Създадох колекция от тестове за управление на старата и новата версия на кода, за да мога съвсем точно да измеря разликите в производителността. Това не отне много време и както очаквах, новият код се оказа с около 10% по-бърз от стария.
Но бързо стана ясно, че 10% нищо не са. Много по-интересно бе, че в моите тестове кодът се изпълнява 10 пъти по-бързо. Ето това бе истинско откритие. След като за пореден път прегледах резултатите, известно време гледах в празното пространство, но след това ме осени. Ролята на кеширанетоЗа да даде пълен контрол на разработчиците и максимално възможна производителност, конзолите дават възможност за заделяне на памет с различни атрибути. Така например, оригиналната Xbox дава възможност за заделяне на памет, която няма да се кешира. Това е изключително важно, понеже не трябва да се дава възможност на играта да чете от некешираната памет. Този тип памет е полезен при записа на данни на графичния процесор. Понеже паметта не се кешира, данните веднага се записват в оперативната памет без задръжки и замърсяване на кеша. Некешираната памет е важна оптимизация, но трябва да се използва много внимателно. Така например, много е важно играта никога да не се опитва да чете от некешираната памет, понеже производителността сериозно ще падне. Дори и относително бавният CPU с тактова честота едва 733 MHz има нужда от свои кешове, за да осигури достатъчна производителност при четенето на данни. Сега става ясно, какво точно се случва. По всичко си личи, че данните на изследваната от мен функция се записват именно в некешираната памет и оттук идва ниската производителност. Беглата проверка потвърди тази хипотеза и настъпи време да се оправи проблема. Намерих реда в сорс кода, където се заделя памет за тази функция, два пъти кликнах по значението на флага и поставих нула. Вместо първоначалните 7% от от процесорния ресурс, сега функцията започна да използва само около 0,7% и повече не създаваше проблеми. Сериозно, моят отчет пред мениджмънта изглеждаше по следния начин: „39,99 часа проучване и изследване, 0,001 часа програмиране – съотношението е добро и това е един нелош успех“. Обикновено, на програмистите и разработчиците не се налага да мислят и да се безпокоят за случайно заделяне на некеширана памет: в повечето операционни системи тази опция не е достъпна и няма как да бъде достигната в потребителски акаунт чрез стандартните методи. Но ако ви е интересно, доколко некешираната памет може да забави една програма, пробвайте флаговете PAGE_NOCACHE и PAGE_WRITECOMBINE във VirtualAlloc. 0 GB понякога са по-добре от 4 GB Още една история. Тя е за бъга, който намерих аз, а го оправи друг. Преди две години забелязах, че дисковият кеш на моя лаптоп твърде често се изчиства. Видях че това става точно на границата на 4 GB. Оказа се, че драйверът на моя съвсем нов хард диск, който използвам за архиви, инциализира SectorSize в 0xFFFFFFFF (или ?1), при указване на неизвестен размер на сектора. Ядрото на Windows интерпретира това значение като 4 GB и заделя съответния блок кеш памет. Това бе проблемът.
Няма познати във Western Digital, но мога да се обзаложа, че те са оправили тази грешка, като са заменили константата 0xFFFFFFFF (или ?1) с нула. Един единствен въведен символ, а е решен сериозен проблем в производителността. ОбобщениеИ в двата случая проблемът е свързан с кеширанетоРешаващо бе използването на подходящ софтуер за профилиране на точно определен проблемБих могъл да опиша редица подобни случаи, но те или са секретни, или са скучниПравилното решение не е задължително да бъде сложно. Понякога съвсем малка промяна дава значително подобрение. Трябва само да знаеш точното място |