Про строки

В процессе портирования одной игры на Sony PSP возникла “классическая” проблема с нехваткой памяти. Впихнуть в N/10 мегабайт памяти игрушку – ещё то развлечение.

Игра была написана, можно сказать по книжке про C++ и STL, но, к счастью, без книжки Александреску. Код довольно чистый и аккуратный, но, поскольку товарищи считают, что памяти много, то аллокации считать не надо, и можно смело делать, например, new ButtonPressedEvent() внутри кадра (это обеспечило дикое, по моему мнению, количество выделений памяти).

Здесь я расскажу ещё и о том, что в проекте всюду использовался std::string (и wstring) (на самом деле был самодельный клон, который по своей сути работал точно также, но позволял делать гадкую вещь – присваивать юникодным контейнерам неюникодные строки и наоборот, в остальном – тоже самое).

При старте игры зачитываются xml конфиги, из которых вычитываются пути к почти всем ресурсам и загружаются сразу в память. После этого вступительные ролики и главное меню.

В общем в результате при входе в главное меню у нас наблюдалась картина:

nAllocatedBlocks 47089
nAllocatedSize 14563733
peakAllocationSize 17645007

Как мы видим – 47 тыс аллокаций, дающих в результате 14,5 МБ.

Решено было перевести такую безобидную вещь, как Filename (т.е. имя файла с ресурсами, которые загружаются и по которым потом работают ещё всякие мапы и прочие поиски – тоже зло, конечно) с std::wstring (а иногда std::string) на фиксированую строку rk::String<1024> (в зависимости от настроек компилятора она внутри или char, или wchar_t, в нашем случае wchar_t).

Возни при переделке было очень много. Из злобных вещей, которые сразу всплывали – были “неявные” конверсии между ANSI – Unicode – т.е. выражение вида std::wstring filename = “texture.png” на самом деле вызывало бурю эмоций у системы, т.к. нужно было сначала создать строку ansi, создать буфер в памяти, сконвертить её в юникод и потом записать в целевой контейнер. И это только потому что автор забыл написать перед строчкой букву L (L”text”). Ну а поскольку встречались эпические куски кода, где разные строки конкатенировались  из фрагментов, где часть была анси, а часть юникод, чтобы получить полный путь к ресурсу – то получаемый оверхед представляется значительным.

После того, как весь код, связанный с именами файлов был переведён на фиксированые строки и использование только юникодных строк у нас получилась следующая картинка в главном меню:

nAllocatedBlocks 16978
nAllocatedSize 10259790
peakAllocationSize 12734865

Как мы видим – количество произведённых аллокаций уменьшилось почти в 3 раза, это в основном заслуга того, что исчезли неявные конверсии кодировок.

А вот выигрыш по памяти – почти 5МБ (30%) – это уже серьёзная заявка на успех, при том, что rk::String<1024> явный оверкилл и перерасход для имён файлов, длина которых врядле превысит 128 символов (хотя скорее всего здесь была или жуткая ошибка в логике игры, и строки плодились, как кролики, или странная странность в измерениях, но это поведение я буду и дальше изучать, вместе с дальнейшим выпиливанием динамических строк).

Собсно что я хотел рассказать в этом посте:

Старайтесь использовать фиксированые строки. Как правило, в игровом коде нету необходимости динамически менять строки и делать с ними всякие гадкие вещи. Если же вы видите, что ну никак без этого не обойтись – то это скорее всего из-за того, что, либо у вас очень высокая квалификация и вы точно знаете, что делаете и как оно будет работать, либо у вас наоборот – не очень высокая квалификация – и тогда стоит подумать ещё над проектом – может всё-таки найдётся возможность обойтись?

Не смешивайте в рамках одного проекта разные кодировки, особенно с неявными преобразованиями (их вообще лучше запретить под страхом луча поноса в сторону автора). Изначально определитесь, ANSI, UTF-8, UTF-16 или ещё что-то и пользуйтесь чем-то одним. Идеально – все статические строки оборачивать макросом типа _T(), который на основании настроек компиляции будет выбирать кодировку. Этим вы облегчите жизнь не только себе, когда внезапно окажется, что нужно делать японскую локализацию, но и тем людям, которые в будущем будут поддерживать ваш код. Ну и избежите ненужного оверхеда 🙂

Similar Posts

  • Киевская горка

    Ходили сегодня с Андрюхой (экс-старостой) на Протасов Яр покататься. В будни как-то поприятней выходит – народу поменьше, не так всё счёсано и не боишься налететь на кого-то или чтобы на тебя кто-то налетел 🙂 Огорчает только длина – она настолько маленькая, что подъем выходит значительно дольше спуска. Надо ехать в нормальные горы, пора… Share this…

  • Visual Studio Integration for GNU GCC ver 0.1 released

    Закончил писать инсталлятор и сумел поставить на “чистой” машине плагин, который смог подхватить проект и собрать его. Отлично, можно переходить к реализации следующей фазы – версия пригодная для наружного тестирования. Share this post: Share on X (Twitter) Share on Facebook Share on LinkedIn Share on Email Share on Reddit

  • После военки

    Странное я создание – пришел на военку, хочу спать, значит надо затусоваться где-то и поспать, приваливает счастье в виде отсутствия первой пары – вместо того чтобы воспользоваться моментом я читал книгу – новые главы нового произведения С. Лукьяненко. После 3й пары наш майор-подполковник зовет 2 добровольцев подержать лестницу и разрешает свалить после этого – я…

  • Многопоточность

    Я всегда боялся многопоточности, старался избегать ее всеми возможными путями. Еще в институте, когда у нас на занятиях по программированию началось изучение оной, я старался избежать расплаты 🙂 страшные названия мьютекс, семафор, критическая секция и прочие ввергали меня в панику. Это первая часть вступления, теперь вторая 🙂 Меня давно манили сети, те, которые компьютерные, мне…

  • Она!

    Вот она, моя новая подружка 🙂  Share this post: Share on X (Twitter) Share on Facebook Share on LinkedIn Share on Email Share on Reddit

  • Румыния: день 4

    29.04.2008 Вторник, 11:00 (Синая) Мы покинули гостеприимную Синаю и взяли курс на Бузау – грязевые вулканы. Выходя из гостинницы мы встретили гидов и знакомых представителей Укррома, через которых мы, собственно, и открывали визы. Нам доверительно сообщили, что администрация посчитала нас очень тихими и спокойными (наверное они ещё не нашли прожжённый кальяном ковёр). Хотя, с другой…