Один парень работает в серьезной конторе. пишут что-то супер сложное для отслеживания и обработки информации в реальном времени на с++. время обработки пришедшей инфы должно быть гарантированно меньше миллисекунды.
сегодня он обратился с вопросом
у меня есть функция которая должна дико быстро отрабатывать, есть переменная в ней char x[250].
вот где этот массив будет создаваться и где память очищается?
Я объяснил где, как и что это элементарная и очень быстрая операция.
Это как-то его не слишком убедило
но в этой функции на счету каждая микросекунда
мне нужен буффер просто
...
для sprintf нужно
Здравствуйте, WiseAlex, Вы писали:
WA>Я объяснил где, как и что это элементарная и очень быстрая операция.
Ну-ну. Я бы для начала поинтересовался , для каких машин он пишет, что там за процессор и как выделяется память. А то мне в свое время доводилось иметь дело с машиной без аппаратного стека.
WA>Это как-то его не слишком убедило WA>[q] WA>но в этой функции на счету каждая микросекунда
Если и впрямь именно микросекунда, то речь безусловно не идет о Windows, а в таком случае лучше вообще рекомендаций не давать.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>Ну-ну. Я бы для начала поинтересовался , для каких машин он пишет, что там за процессор и как выделяется память. А то мне в свое время доводилось иметь дело с машиной без аппаратного стека.
Под машинами без аппаратного стека подразумеваются процессоры, в которых нет специальных инструкций для добавления/удаления слов в стек с автоматическим инкрементом/декрементом указателя вершины? Так это никак не влияет. В любом случае для резервирования места просто отнимаем (или прибавляем, в зависимости от направления роста) к указателю вершины нужную величину. Инструкции типа enter/leave — те же яйца, только в профиль, и производительности особо не добавят.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, WiseAlex, Вы писали:
WA>для sprintf нужно
Помню, в бытность мою работы в геймдеве (слава богу, всего полгода этого дурдома), один коллега засунул в какой-то цикл где обрабатываются полигоны локальный std::vector с push_back'ом для каждой вершины, скомпилил в дебаге с дебаговой же STL и потом рассказывал мне: "я так и знал шо этот STL такой тормозной".
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>Ну-ну. Я бы для начала поинтересовался , для каких машин он пишет, что там за процессор и как выделяется память. А то мне в свое время доводилось иметь дело с машиной без аппаратного стека.
ДД>Под машинами без аппаратного стека подразумеваются процессоры, в которых нет специальных инструкций для добавления/удаления слов в стек с автоматическим инкрементом/декрементом указателя вершины? Так это никак не влияет. В любом случае для резервирования места просто отнимаем (или прибавляем, в зависимости от направления роста) к указателю вершины нужную величину. Инструкции типа enter/leave — те же яйца, только в профиль, и производительности особо не добавят.
См. архитектуру IBM/360-370. В ней аппаратного стека вообще.
Здравствуйте, Pavel Dvorkin, Вы писали:
PD>См. архитектуру IBM/360-370. В ней аппаратного стека вообще.
Чем в данном случае "аппаратный" стек отличается от "программного"? Только тем, что в первом случае на вершину указывает отдельный регистр, во втором — обычная переменная.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, Pavel Dvorkin, Вы писали:
PD>>См. архитектуру IBM/360-370. В ней аппаратного стека вообще.
ДД>Чем в данном случае "аппаратный" стек отличается от "программного"? Только тем, что в первом случае на вершину указывает отдельный регистр, во втором — обычная переменная.
Я не помню, как там выделялась память (а скорее даже не знаю, так как работал на Фортране, а в нем тогда не было динамического выделения памяти в каком бы то ни было виде). Что я помню — что для выделения памяти использовалась специальная макрокоманда GETMAIN, но вот применялась ли она для выделения только динамической в нынешнем понимании или также и автоматической в нынешнем понимании памяти — сказать не берусь, и тем более утверждать, что для этого использовалась именно фиксированная переменная.
А отличия, конечно, есть. При занесении в стек ESP меняется автоматически, а насчет переменной на это надеяться не приходится. Хотя, конечно, эмулировать аппаратный стек программно можно.
WA>у меня есть функция которая должна дико быстро отрабатывать, есть переменная в ней char x[250].
WA>вот где этот массив будет создаваться и где память очищается?
WA>Я объяснил где, как и что это элементарная и очень быстрая операция. WA>Это как-то его не слишком убедило
может, потому что объяснили не слишком убедительно. а память точно будет очищаться?
WA>
WA>но в этой функции на счету каждая микросекунда
WA>мне нужен буффер просто
WA>...
WA>для sprintf нужно
смотря, что этот sprintf делает. если это "%s\n" то это одно, а если там идет очень сложное форматирование, то не факт, что самопальная реализация будет работать быстрее.
ЗЫ. довелось участвовать в собеседовании одного человека, претендующего на сеньера на руби. я руби не знаю, но что-то умное был спросить просто обязан (иначе на фига я присутствую?!). спросил первое что пришло в голову -- какой порядок оверхида (по расходу памяти) у разряженных массивов? чел сначала не понял вопроса (почему-то он думал, что сколько мы кладем в массив, ровно столько памяти и потребляем), а потом признался, что такое ему вообще не приходило в голову.
ЗЫ.ЗЫ. а если память все-таки очищается, то почему вы думаете, что иницилизация 250 (плюс выравнение) байт займет значительно меньше времени, чем sprintf?
P>ЗЫ.ЗЫ. а если память все-таки очищается, то почему вы думаете, что иницилизация 250 (плюс выравнение) байт займет значительно меньше времени, чем sprintf?
какие нафиг очистки, какие нафиг выравнивания???
sub esp, XXX — одна машинная команда на ВСЕ локальные переменные на входе, это разве новость?
Здравствуйте, vitasR, Вы писали:
R>Здравствуйте, poldhiir, Вы писали:
P>>ЗЫ.ЗЫ. а если память все-таки очищается, то почему вы думаете, что иницилизация 250 (плюс выравнение) байт займет значительно меньше времени, чем sprintf?
R>какие нафиг очистки, какие нафиг выравнивания???
ну напишите char buf[250] = {1,2,3}; сразу увидите какие очистки.
под x86 компилятор выделит 252 байт. потому как 250 не кратно 4м.
Здравствуйте, poldhiir, Вы писали:
P>>>ЗЫ.ЗЫ. а если память все-таки очищается, то почему вы думаете, что иницилизация 250 (плюс выравнение) байт займет значительно меньше времени, чем sprintf?
R>>какие нафиг очистки, какие нафиг выравнивания??? P>ну напишите char buf[250] = {1,2,3}; сразу увидите какие очистки. P>под x86 компилятор выделит 252 байт. потому как 250 не кратно 4м.
в оригинале было char buf[250], без инициализации. инициализировать буфер куда пойдет sprintf — гхм...
Здравствуйте, poldhiir, Вы писали:
p> R>какие нафиг очистки, какие нафиг выравнивания???
p> ну напишите char buf[250] = {1,2,3}; сразу увидите какие очистки. p> под x86 компилятор выделит 252 байт. потому как 250 не кратно 4м.
Ты в курсе, что есть стек? Регистр SP(ESP)и так далее? Если нет, то понятно.
Здравствуйте, ocaml, Вы писали:
O>Здравствуйте, poldhiir, Вы писали:
p>> R>какие нафиг очистки, какие нафиг выравнивания???
p>> ну напишите char buf[250] = {1,2,3}; сразу увидите какие очистки. p>> под x86 компилятор выделит 252 байт. потому как 250 не кратно 4м.
O>Ты в курсе, что есть стек? Регистр SP(ESP)и так далее? Если нет, то понятно.
Здравствуйте, poldhiir, Вы писали:
P>Здравствуйте, ocaml, Вы писали:
O>>Здравствуйте, poldhiir, Вы писали:
p>>> R>какие нафиг очистки, какие нафиг выравнивания???
P>0xFC это 252 байта. почему там объяснять, надеюсь, не надо?
252 байт обяснять не надо. надо обьяснить почему это время займет.
Здравствуйте, ДимДимыч, Вы писали:
ДД>Под машинами без аппаратного стека подразумеваются процессоры, в которых нет специальных инструкций для добавления/удаления слов в стек с автоматическим инкрементом/декрементом указателя вершины? Так это никак не влияет. В любом случае для резервирования места просто отнимаем (или прибавляем, в зависимости от направления роста) к указателю вершины нужную величину. Инструкции типа enter/leave — те же яйца, только в профиль, и производительности особо не добавят.
Все гораздо хуже. Бывают архитектуры, например популярный PIC16, где вообще нет относительной адресации памяти данных. А стек есть только для адресов возврата, фиксированного размера. Компилятор С в такой архитектуре строит т.н. компилированный стек еще в дизайн-тайме. Соответственно, все ф-ии становятся нереентерабельны. Писать трудно, но можно.
Здравствуйте, dudkin, Вы писали:
D>Здравствуйте, poldhiir, Вы писали:
P>>Здравствуйте, ocaml, Вы писали:
O>>>Здравствуйте, poldhiir, Вы писали:
p>>>> R>какие нафиг очистки, какие нафиг выравнивания???
P>>0xFC это 252 байта. почему там объяснять, надеюсь, не надо?
D>252 байт обяснять не надо. надо обьяснить почему это время займет.
где я говорил про время?! а надо бы сказать... если функция критична к времени выполнения, то создавая массив в стеке мы не можем быть уверенными, что он не вылетит на границы текущей страницы и ось не начнет аллоцировать память при первом к ней обращении. и это займет уж точно больше времени, что sprintf
Здравствуйте, sz36, Вы писали:
S>Все гораздо хуже. Бывают архитектуры, например популярный PIC16, где вообще нет относительной адресации памяти данных. А стек есть только для адресов возврата, фиксированного размера. Компилятор С в такой архитектуре строит т.н. компилированный стек еще в дизайн-тайме. Соответственно, все ф-ии становятся нереентерабельны. Писать трудно, но можно.
Да, я немного знаком с PIC'ами, писал несколько проектов под них. И распределение памяти в т.н. компилированном стеке (aka "программном") сводится к изменению значения указателя вершины стека, точно так же, как в случае с "аппаратным" стеком x86. И в данном случае неважно, распределяется ли память для локальных переменных в том же массиве, где хранятся адреса возврата (как в x86) или для адресов возврата есть отдельный стек ("аппаратный"), а для параметров и переменных — своя область памяти со стековой организацией доступа ("программный" стек). Распределение памяти сводится к изменению указателя вершины, будь то регистр процессора или просто переменная в памяти.
Обязательно бахнем! И не раз. Весь мир в труху! Но потом. (ДМБ)
Здравствуйте, ДимДимыч, Вы писали:
ДД>Здравствуйте, sz36, Вы писали:
S>>Все гораздо хуже. Бывают архитектуры, например популярный PIC16, где вообще нет относительной адресации памяти данных. А стек есть только для адресов возврата, фиксированного размера. Компилятор С в такой архитектуре строит т.н. компилированный стек еще в дизайн-тайме. Соответственно, все ф-ии становятся нереентерабельны. Писать трудно, но можно.
ДД> Распределение памяти сводится к изменению указателя вершины, ДД> будь то регистр процессора или просто переменная в памяти.
поддерживаю. и вообще автоматическую память можно "эмулировать" и на си, размещая данные в куче, что упрощает борьбу с утечками. правда тут главное не забыть при выходе из функции перемесить указатель назад, но даже если забыть, то в отличии от malloc/free тут ничего трагичного не случится. допустим, фунция А зовет функцию Б, а функция Б зовет функцию B. допустим, что Б или В (или обе сразу) забывают освободить автоматическую память и в этом случае она освобождается по завершению А.
Здравствуйте, 4UBAKA, Вы писали:
UBA>Здравствуйте, poldhiir, Вы писали:
P>>0xFC это 252 байта. почему там объяснять, надеюсь, не надо?
UBA>Наверное такие опции компилятора выставлены?
у компилятора нет таких опций. кстати, если написать char a,b,c; то компилятор выделит три двойных слова даже если оптимизация отключена. и если выравниванием структур можно хоть как-то управлять, то отключить выравнивание стековых переменных нельзя никак. но это уже тонкости, которые, впрочем, иногда существенны при выборе типов переменных. скажем, если нам нужна переменная для хранения чисел от одного до пяти, то использование char не только не приведет к экономии памяти, а даже увеличит накладные расходы (компилятор выделит двойное слово как для int и расширит char до int, путем манируляций в ран-тайме -- увеличивается размер кода, увеличивается и время его выполнения).