Про строки

В процессе портирования одной игры на 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

  • Kyiv, apr 10, 19:00 SCORPIONS

    Вчера к нам приезжали Scorpions. Зажгли старички очень почотно, до сих пор уши не отошли полностью 🙂 Песни пели всякие разные – из новых альбомов, из старых, барабанщик снова отличился своим соляком. Очень громко и сильно стучал, прыгал по барабанам, бил в гонг, который висел сзади и потом разбил об голову бутылку – классное шоу!…

  • debugger watches you

    Сидел я на выходных и развлекался отладкой одного production софта, который отлично работал на линуксе, но после того, как предыдущий сервер сдох, а на новом решено было ставить FreeBSD, обнаружилось странное выпадание программы, вместо корректной работы. Начал я гуглить туториалы по gdb и заниматься отладкой. С горем пополам обнаружилось, что происходит банальный проезд по памяти….

  • Крым

    Съездил в Ялту на выходных, очень здорово, особенно то, что на самолете. У них сейчас зимние скидки и всякие акции, поэтому цена очень даже сопоставима с поездом, но скорость и комфорт всяко выше. Да и смена обстановки – это позитив, как ни крути 🙂 Особенно такая. Были на Ай-Петри, во второй раз за зиму увидел…

  • Vi iMproved

    Напишу-ка я про один из самых интересных текстовых редакторов. Идея появилась после того, как я нашел аддин – интегрирующий основную функциональность в студию. http://viemu.com/ В связи с моим администраторским увлечением (я занимаюсь небольшим саппортом нескольких серверов фирмы моих знакомых) мне пришлось познакомиться с консолью юникса, а там и с текстовыми редакторами – конфиги-то надо править…

  • Пивко

    Вчера вечером пили пиво в офисе, очень интересная компания получилась однако 🙂 Слева направо: KVaks, DDima, const (это я 🙂 ) Share this post: Share on X (Twitter) Share on Facebook Share on LinkedIn Share on Email Share on Reddit

  • Она!

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