Да, и кстати, строчки в PS* проекте нужны только для:
1. Текстов на экране
2. Связывания скриптов
Все остальные тексты - это зло, которое будет уничтожено при поисках, откуда взять еще 300 кБ памяти и 2 секунды на загрузке. Ибо strcmp() - это очень дорогая операция и придется все рассчитывать на препроцессинге, а в игре связывать сущности только по int32 id;
Я наверно не знаю убер-особых приемов работы с памятью, заточенных под консоли. Но то что знаю - считаю вполне применимым.
Мое видение проблемы основано на том, что в работе с памятью нужно применять специфические знания о типах объектов.
То есть, при помощи не очень сложной вспомогательной инфраструктуры, стоит организовать несколько пулов с фиксированными блоками различной длины. Для STL этой инфраструктурой являются аллокаторы. Почему бы не использовать их?
Типично, при создании объектов, под специфическим знанем я понимаю оценку размера, среднее время жизни, частоту обращений, частоту изменений объема занимаемой памяти, оценку частоты этих изменений и т.д. На основании этого знания, выбирается конкретный пул и место в нем.
Например, хотим создать строку std::string. Пусть в ней хранится имя монстра, которое может иметь размер от 8 до 32 символов - вот и оценка размера. Имя монстра не меняется, - вот и оценка изменений объема памяти. Среднее время жизни рядового монстра, допустим - 3 минуты. Поэтому выбираем вполне конкретный пул (аллокатор), и то место в нем, которое ближе к границам (это уже забота аллокатора).
Следующий вопрос - что делать, если объема пула не хватает? Очевидно, надо создать еще один пул. Вот этой ситуации следует избегать на консолях, то есть - настраивать миссии, и может быть даже сцены, но уже в терминах пулов. И страховать себя в продакшн системой приоритетов. То есть, когда что-то не влезает - то не грузим, или выгружаем что-то менее приоритетное.
Padawan
прально мыслите. но в реальности все еще чуть-чуть проще.
Padawan
> Пусть в ней хранится имя монстра, которое может иметь размер от 8 до 32 символов...
Давай про размер до 32 символов поговорим, когда узнаем ответ на этот вопрос из 59-го поста:
> Каков sizeof(str)? Чур отладчик не запускать! Сколько реально занимает памяти std::string str("BlaBlaBlaBlaBlaBla")?
А аллокатор/деаллокатор, какой бы он ни был быстрый, не сможет сравниться по скорости с sub esp, add esp :(
Димка
std::string str;
ну sizeof(str) == 28 всегда
str = ""
_Mysize == 0
_Myres == 15
str = "BlaBlaBlaBla";
_Mysize == 12
_Myres == 15
str = "BlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBlaBla"
_Mysize == 36
_Myres == 47
(да, с отладчиком, я читер ))) гоните меня прочь ))) и может я все не так понял ^^)
по моим наблюдением размер кеширутся на + 16 что вобщем то не критично
В VC 7.1 sizeof(std::string) - 48 байт. Что заодно позволяет ему очень быстро работать с короткими строками, не вызывая постоянные аллокации (там буфер на 16 символов).
Вариант с 28 байтами - кастрированный. То есть практически любая строчка требует аллокации памяти. Системная память аллокируется блоками по 16 байт. Плюс 16 байт заголовка блока. Соответственно, (это еще и ответ для Padawan) для std::string имеем:
28 байт sizeof()
16 байт заголовка
как минимум 16 байт на текст.
Итого, вместо std::string можно пользовать фиксированный буфер на 60 байт. Разницы по памяти не будет вообще, а выигрыш по скорости работы со строчками - огромен.
Если же мы говорим, что "имя монстра" может быть 32 байта максимум, то std::string полностью теряет все преимущества. Он сильно медленнее и жрет как минимум в 2 раза больше памяти.
Updated: если же мы еще и std::string выделем через new, картина еще хуже: sizeof(std::string) выравниваем до 32 + 16 байт заголовка. Итого: указатель на аллокированный стринг эквивалентен char array[108].
Димка
Ну для константных строк можно выделить какойнить стринг тейбл и там их копить в массивах
а по ходу в моей программе всего ничего ф-ций которые юзают стринги, тоесть обычно это имя объекта, тоесть можно везде поменять на char* но както при паре десятков объектов выигрыш будет ну пусть пару сотен байт....а операции по доступу или поиску объекта по имени практически нет, все что нужно имеет флаг.... а есть какойнить пример чтоб ну вот супер прирост по производительности при переводе на чары(при пряморукой архитектуре конечно)?
(правка - ачепятки)
bada
>Димка
>а по ходу в моей программе всего ничего ф-ций которые юзают стринги
Зависит от того _где_ они их юзают. Если на стартапе, то пох.
Если во внутреннем цикле рендера - ты запросто можешь получить ускорение в несколько раз :)
Updated:
Когда ты сидишь часами над неработающей программой и думаешь, с какого бы еще модуля срезать 30 килобайт, чтобы влезть в память, тебе замена std::string на char[] (а еще лучше на int32 guid) покажется сладкой песней по сравнению с другими методами оптимизации.
По ходу, для размышлений.
В CW
void test(void)
{
std::vector<int> v;
v.reserve(200);
for (int i = 0;i < 200;i++) v.push_back(i);
for (int i = 0;i < v.size();i++)
{
printf("%d\n",v);
}
}
; test():
0x00000000 0x27BDFFE0 addiu sp,sp,-32
0x00000004 0xAFBF000C sw ra,12(sp)
;
; 21: std::vector<int> v;
;
0x00000008 0x27A40014 addiu a0,sp,20
0x0000000C 0x0C000000 jal __ct__Q23std30vector<i,Q23std12allocator>Fv ; 0x00000000
0x00000010 0xAFB00008 sw s0,8(sp)
;
; 22: v.reserve(200);
; 23:
;
0x00000014 0x27A40014 addiu a0,sp,20
0x00000018 0x0C000000 jal reserve__Q23std30vector<i,Q23std12allocator>FUi ; 0x00000000
0x0000001C 0x240500C8 li a1,200
;
; 24: for (int i = 0;i < 200;i++) v.push_back(i);
; 25:
;
0x00000020 0xAFA00010 sw $0,16(sp)
0x00000024 0x27A40014 addiu a0,sp,20
0x00000028 0x0C000000 jal push_back__Q23std30vector<i,Q23std12allocator>FRCi ; 0x00000000
0x0000002C 0x27A50010 addiu a1,sp,16
0x00000030 0x8FA20010 lw v0,16(sp)
0x00000034 0x24420001 addiu v0,v0,1
0x00000038 0xAFA20010 sw v0,16(sp)
0x0000003C 0x284200C8 slti v0,v0,200
0x00000040 0x1440FFF8 bne v0,$0,*-28 ; 0x00000024
0x00000044 0x00000000 nop
;
; 26: for (int i = 0;i < v.size();i++)
; 27: {
;
0x00000048 0x27A40014 addiu a0,sp,20
0x0000004C 0x0C000000 jal size__Q23std37__vec_deleter<i,Q23std12allocator>CFv ; 0x00000000
0x00000050 0x00008021 addu s0,$0,$0
0x00000054 0x0002082B sltu $at,$0,v0
0x00000058 0x1020000E beq $at,$0,*+60 ; 0x00000094
0x0000005C 0x00000000 nop
;
; 28: printf("%d\n",v);
;
0x00000060 0x27A40014 addiu a0,sp,20
0x00000064 0x0C000000 jal __vc__Q23std30vector<i,Q23std12allocator>FUi ; 0x00000000
0x00000068 0x02002821 addu a1,s0,$0
0x0000006C 0x8C450000 lw a1,0(v0)
0x00000070 0x3C040000 lui a0,hi(@1639)
0x00000074 0x0C000000 jal printf ; 0x00000000
0x00000078 0x24840000 addiu a0,a0,lo(@1639)
;
; 29: }
; 30:
;
0x0000007C 0x27A40014 addiu a0,sp,20
0x00000080 0x0C000000 jal size__Q23std37__vec_deleter<i,Q23std12allocator>CFv ; 0x00000000
0x00000084 0x26100001 addiu s0,s0,1
0x00000088 0x0202102B sltu v0,s0,v0
0x0000008C 0x1440FFF4 bne v0,$0,*-44 ; 0x00000060
0x00000090 0x00000000 nop
0x00000094 0x27A40014 addiu a0,sp,20
0x00000098 0x0C000000 jal __dt__Q23std30vector<i,Q23std12allocator>Fv ; 0x00000000
0x0000009C 0x2405FFFF li a1,-1
;
; 31: }
0x000000A0 0x8FBF000C lw ra,12(sp)
0x000000A4 0x8FB00008 lw s0,8(sp)
0x000000A8 0x03E00008 jr ra
0x000000AC 0x27BD0020 addiu sp,sp,32
Заметьте, максимальная оптимизация, даже и не подумала сделать inline подстановки
даже operator[]
остался call ( __vc__Q23std30vector<i,Q23std12allocator>FUi )
я понимаю что в CW кривобокая STL и больная на всю голову, но альтернативы для CW в принципе нет.
Разве что ручками портировать.
Может конечно там еще флажки нада какакие-то поставить:)
предыдущий тест был с флажком в CW (don't inline)
счас с smart inline
08900000 <test__Fv>:
8900000: 27bdffd0 addiu sp,sp,-48
8900004: afbf000c sw ra,12(sp)
8900008: afb10008 sw s1,8(sp)
890000c: afb00004 sw s0,4(sp)
8900010: 27b0002c addiu s0,sp,44
8900014: ae000000 sw zero,0(s0)
8900018: 8e020000 lw v0,0(s0)
890001c: 27b10028 addiu s1,sp,40
8900020: afa00024 sw zero,36(sp)
8900024: 2c4100c8 sltiu at,v0,200
8900028: 10200004 beqz at,890003c <test__Fv+0x3c>
890002c: ae200000 sw zero,0(s1)
8900030: 27a40024 addiu a0,sp,36
8900034: 0e2400ee jal 89003b8 <reallocate_copy__Q23std37__vec_deleter<i,Q23std12allocator>FUi>
8900038: 240500c8 li a1,200
890003c: afa00020 sw zero,32(sp)
8900040: 00001821 move v1,zero
8900044: 8e240000 lw a0,0(s1)
8900048: 8e020000 lw v0,0(s0)
890004c: 0082082b sltu at,a0,v0
8900050: 50200018 beqzl at,89000b4 <test__Fv+0xb4>
8900054: 00001021 move v0,zero
8900058: 00032000 sll a0,v1,0x0
890005c: 8e230000 lw v1,0(s1)
8900060: 8fa20024 lw v0,36(sp)
8900064: 00042003 sra a0,a0,0x0
8900068: 24630001 addiu v1,v1,1
890006c: ae230000 sw v1,0(s1)
8900070: 00031880 sll v1,v1,0x2
8900074: 00431021 addu v0,v0,v1
8900078: ac44fffc sw a0,-4(v0)
890007c: 8fa20020 lw v0,32(sp)
8900080: 24430001 addiu v1,v0,1
8900084: 286200c8 slti v0,v1,200
8900088: 1440ffee bnez v0,8900044 <test__Fv+0x44>
890008c: afa30020 sw v1,32(sp)
8900090: 8fa20028 lw v0,40(sp)
8900094: 0002102b sltu v0,zero,v0
8900098: 1440000d bnez v0,89000d0 <test__Fv+0xd0>
890009c: 00008021 move s0,zero
89000a0: 27a40024 addiu a0,sp,36
89000a4: 0e240128 jal 89004a0 <__dt__Q23std37__vec_deleter<i,Q23std12allocator>Fv>
89000a8: 00002821 move a1,zero
89000ac: 10000016 b 8900108 <test__Fv+0x108>
89000b0: 8fbf000c lw ra,12(sp)
89000b4: 00023600 sll a2,v0,0x18
89000b8: 00063603 sra a2,a2,0x18
89000bc: 27a40024 addiu a0,sp,36
89000c0: 0e2400dd jal 8900374 <sub_push_back__Q23std37__vec_deleter<i,Q23std12allocator>FRCiQ210Metrowerks11int2type<1>>
89000c4: 27a50020 addiu a1,sp,32
89000c8: 1000ffed b 8900080 <test__Fv+0x80>
89000cc: 8fa20020 lw v0,32(sp)
89000d0: 8fa20024 lw v0,36(sp)
89000d4: 00101880 sll v1,s0,0x2
89000d8: 3c040891 lui a0,0x891
89000dc: 00431021 addu v0,v0,v1
89000e0: 8c450000 lw a1,0(v0)
89000e4: 0e243923 jal 890e48c <printf>
89000e8: 248433c0 addiu a0,a0,13248
89000ec: 8e220000 lw v0,0(s1)
89000f0: 26100001 addiu s0,s0,1
89000f4: 0202102b sltu v0,s0,v0
89000f8: 1440fff5 bnez v0,89000d0 <test__Fv+0xd0>
89000fc: 00000000 nop
8900100: 1000ffe8 b 89000a4 <test__Fv+0xa4>
8900104: 27a40024 addiu a0,sp,36
8900108: 8fb10008 lw s1,8(sp)
890010c: 8fb00004 lw s0,4(sp)
8900110: 03e00008 jr ra
8900114: 27bd0030 addiu sp,sp,48
Стало лучше, но блин
1. массив в стеке должен быть
2. это оператор [] , как минимум одна лишняя операция
89000d0: 8fa20024 lw v0,36(sp)
89000d4: 00101880 sll v1,s0,0x2
89000dc: 00431021 addu v0,v0,v1
89000e0: 8c450000 lw a1,0(v0)
KVaks
уу страшно ))) я последний раз на асме программировал в универе лет 5 назад )))
а кстати, я вот компилю psp_gcc что идет с тулчейном, там реализация такая же стл ?
а ты проверь , и отойди :) (c) реклама какая-то
KVaks
>а ты проверь , и отойди :) (c) реклиама какая-то
В оригинале "Доченька, ты же лопнешь. А ты налей и отойди" (С) Сок "Моя семья".
блин, вот есть же вещи, которыми хорошо пользоваться ))) вот если б писал скажем редактор в pure C я б наверно помер от старости ))))) а так, 2 дня на C# и готовый редактор - красота
bada
Про редакторы вообще никто и слова не говорит. Пользуй на здоровье :). ПеСи большая, ПеСи все стерпит.
По поводу реализаций STL вообще недавно был большой спор. Относительно поведения clear() - освобождает этот вызов память или нет :).
Тема в архиве.