реклама на сайте
подробности

 
 
3 страниц V   1 2 3 >  
Reply to this topicStart new topic
> Кто какую реализацию использует для распределения памяти на cortex?
Beginning
сообщение Jun 19 2012, 13:48
Сообщение #1


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Проще говоря вы используете malloc и т.п. из библиотеки или свои? Я вот FreeRTOS изучаю. Решил досконально изучить исходники (heap_2). Честно говоря это треш какой то. Конечно как кому, но для меня такой стиль писания... Все эти x,px и и т.д. километровые имена. Принцип бритвы Оккамы походу не известен разработчикам. Пока всю эту дибилистику не убрал постоянно терялся на середине алгоритма. Как там, мозг не может запомнить одновременно более 7 переменных величин. Но да ладно не об этом. Вобщем мне не понравилась такая реализация - нету дефрагментации кучи. Взял стандартные библиотечные (KEIL RVDS). Но их тоже оказывается 2 реализации http://www.keil.com/support/man/docs/armli...ib_Cihfiabf.htm
Как они толком работают, не поймешь - исходников я не нашёл.
Вобщем кто какой реализацией пользуется? Может кто исходниками поделится. Камень Cortex.


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
shmur
сообщение Jun 19 2012, 13:59
Сообщение #2


Участник
*

Группа: Участник
Сообщений: 55
Регистрация: 28-11-11
Пользователь №: 68 553



Пользуемся tlsf, пока всем устраивает.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jun 19 2012, 14:34
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



Имени zltigo. И на Cortex и на ARM7


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 19 2012, 14:51
Сообщение #4


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Блин, нашёл тему близнец тыц Можно склеить.


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
IgorKossak
сообщение Jun 19 2012, 17:11
Сообщение #5


Шаман
******

Группа: Модераторы
Сообщений: 3 064
Регистрация: 30-06-04
Из: Киев, Украина
Пользователь №: 221



Склеил бы, да руки не достают. Тем более, что здесь часто возникают такие вопросы. Пусть остаётся.
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 19 2012, 22:28
Сообщение #6


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Вот и моя близняшка http://electronix.ru/forum/index.php?showtopic=103157 sm.gif
Юзаю простой best-fit аллокатор с ограничением на минимальный свободный блок, правда не в тех задачах, что в той теме описаны.
Применяется для хранения сообщений для передачи между потоками...
Типа в одном потоке создаем обьект в куче, кидаем указатель на него в FIFO, другие потоки выгребают эти обьекты, выполняют соответствующие методы, возможно передают их дальше другим потокам(в том числе и родителю обратно) и подостижении состояния "final" обьект удаляется(это может произойти в любом потоке). Размер обьектов разный, тип разный. FIFO один. Лучшей реализации,чем использовать кучу пока не придумал.

shmur, про tlsf можно по подробнее, мож где-то толковое описание метода есть или алго? где-то краем глаза читал про него в брошюрке, но так и не понял,инфы мало было.
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 20 2012, 07:18
Сообщение #7


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Я тут немного поразмыслил и пришел к выводу что дефрагментация кучи это практически невыполнимая задача без костылей. Вначале я быстро прикинул алгоритм примерно такой. При выделении памяти в начале кучи выделяется собственно память а с конца (например, можно и в начале) выделяется указатели на понтеры, которые собственно и "получат память". Тогда выделение памяти будет выглядеть не так:
byte *p = alloc(100);
а так
byte *p;
alloc(&p,100);
if(p!=NULL)...
Делается это для того, что бы сохранить адрес понтера, и при дефрагментации кучи мы могли бы занести туда новое значение адреса.
Но поразмыслив я понял что это накладывает кучу ограничений.
Нельзя использовать:
byte *pp,*p = alloc(100);
pp = p;
или
p += x; т.е. изменять адрес
Придётся использовать функции которые грамотно копировали бы поинтеры.
Использовать **p тоже не хочется, усложнение на пустом месте.
Есть ли простой способ, без костылей, дефрагментировать кучу?


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
scifi
сообщение Jun 20 2012, 07:29
Сообщение #8


Гуру
******

Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136



Цитата(Beginning @ Jun 20 2012, 11:18) *
Есть ли простой способ, без костылей, дефрагментировать кучу?

Простых способов нет.
Дефрагментация неизбежно требует, чтобы программа была готова к тому, что выделенные куски памяти могут переместиться (то есть после перемещения должны обновиться указатели). Кроме того, должен быть некий механизм запирания, чтобы дефрагментатор не стал двигать кусок памяти, с которым ещё не закончена работа (есть активный указатель).
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 20 2012, 07:40
Сообщение #9


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Картина собственно ясна. А теперь вопрос. Стоит ли ради дефрагментации накладывать на программу кучу обязательств - для всех манипуляций с указателями пользоваться только специальными функциями, иначе, если вдруг произошла дефрагментация, будет такой глюк, который практически нереально просчитать.
Да же не так, интересует случай из практики, когда применялась дефрагментация и все + и - с этим связанные, и какое такое преимущество вынудило использовать дефрагментацию.


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 20 2012, 09:13
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Beginning @ Jun 20 2012, 13:40) *
Картина собственно ясна. А теперь вопрос. Стоит ли ради дефрагментации накладывать на программу кучу обязательств
Проще наложить одно единственное обязательство - не использовать кучу.
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 20 2012, 09:40
Сообщение #11


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Забудьте про дефраг. Дефрагментация уместна только, если есть страничная адресация(у кортексов-м3 нету), и то не нужна она там обычно.
Если уж других вариантов решить задачу нету - купите проц с внешней шиной и нацепите срам сверху. такие делает STm, на пример.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jun 20 2012, 11:43
Сообщение #12


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Если Вы можете выделить сколь-нибудь детерминированное место под страницу дескрипторов и оперировать не с указателями, а с индексами массива указателей(операция доступа к участку кучи удлиняется) - проблема дефрагментации решается просто.
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 20 2012, 12:05
Сообщение #13


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Я уже писал про **p. Придётся везде лепить. А потом начнётся ***p и т. д.


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
maksimp
сообщение Jun 20 2012, 17:19
Сообщение #14


Местный
***

Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023



Практическая реализация дефрагментации без аппаратной поддержки вполне возможна. Это использовалось в Windows старых версий, в том числе на процессоре 8086.
См. функцию GlobalAlloc с флагом GMEM_MOVEABLE. А также функции GlobalLock, GlobalUnlock, GlobalFree, GlobalReAlloc.
Идея такая. Выделил с помощью GlobalAlloc с флагом GMEM_MOVEABLE кусок памяти - и получил не указатель а дескритор, значение типа HGLOBAL.
Нужно попользоваться - закрепил по дескриптору блок с помощью GlobalLock и получил при этом указатель, залез в блок, и отпустил его GlobalUnlock. Ранее полученный указатель стал недействительным. Когда блок отпущен он можен быть сдвинут. Чтобы ещё раз добраться до блока нужно ещё раз вызвать GlobalLock.
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 20 2012, 18:35
Сообщение #15


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Я так понимаю это компромис. Зарезервировал память. Хочеш попользоваться -получай поинт, пользуйся. Не пользуешся разлочивай. Данные при этом не пропадают, но могут переместится. Отсюда два минуса - надо постоянно получать поинты и лочить/разлочить. Пока все не разлочат кучу, её не дефрагментируешь. Как по мне костыль номер один достаточно геморойный. Ну и как эта система, себя оправдала?


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
aaarrr
сообщение Jun 20 2012, 18:37
Сообщение #16


Гуру
******

Группа: Свой
Сообщений: 10 713
Регистрация: 11-12-04
Пользователь №: 1 448



Цитата(Beginning @ Jun 20 2012, 22:35) *
Пока все не разлочат кучу, её не дефрагментируешь.

Все ее могут и никогда не разлочить. Нужно пользоваться моментом.
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 20 2012, 19:12
Сообщение #17


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Не ну я прикидывал, мол если например кусок не разлочен в конце, а в начале все разлоченные, то можно только начало дефрагментировать, но это такие грабли, что и работать будет соответствующе.


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jun 20 2012, 20:21
Сообщение #18


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Beginning @ Jun 20 2012, 22:12) *
Не ну я прикидывал, мол если например кусок не разлочен в конце, а в начале все разлоченные, то можно только начало дефрагментировать, но это такие грабли, что и работать будет соответствующе.

Если дефрагментация выполняется в потоке с самым низким приоритетом (как и должно быть) - то откуда грабли?
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 20 2012, 20:35
Сообщение #19


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Ну хотябы, если дефрагментация началась, то её уже не остановить наполовину, и в этот момент если более приоритетному потоку надо что то сделать то он этого не сделает - тоесть все остальные потоки автоматически становятся с более низким приоритетом.


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
maksimp
сообщение Jun 21 2012, 04:10
Сообщение #20


Местный
***

Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023



Цитата(Beginning @ Jun 20 2012, 22:35) *
Зарезервировал память. Хочеш попользоваться -получай поинт, пользуйся. Не пользуешся разлочивай. .... Ну и как эта система, себя оправдала?

В старых книгах по Windows писали что о-го-го. Но когда появились процессоры с аппаратной поддержкой страниц памяти (80386) то эту систему отменили.

Цитата(aaarrr @ Jun 20 2012, 22:37) *
Все ее могут и никогда не разлочить. Нужно пользоваться моментом.

Подозреваю что использование памяти должно быть тогда организовано более определённым образом. Например, система реального времени может иметь общий цикл приёма, обработки и передачи информации, например длительностью 100 мс. К концу цикла все блоки обязаны быть разлочены, и производится дефрагментация. Если не все блоки разлочены оказались - то фатальная ошибка, прекращаем сбрасывать сторожевой таймер и уходим в аппаратный сброс.
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jun 21 2012, 05:12
Сообщение #21


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Beginning @ Jun 20 2012, 23:35) *
Ну хотябы, если дефрагментация началась, то её уже не остановить наполовину

Пересылку блока надо делать атомарной laughing.gif
А так - необходимость в том, чтобы к запуску дефрагментации были разлочены все блоки, еще обосновать надо, с точки зрения временнОй эффективности работы дефрагментатора. Очень может быть, что "таская" блоки по одному система ничего не проиграет.
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 21 2012, 06:16
Сообщение #22


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Наверняка так и есть. Но по поводу этого я не сильно переживаю, тут более менее всё понятно. Сильно напрягает наложение специальных требований на программу. Это основной костыль. Любые за уши притянутые паттерны я расматриваю как зло. Программа должна быть максимально естественна (проста) с точки зрения кода.


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jun 21 2012, 07:39
Сообщение #23


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Beginning @ Jun 21 2012, 09:16) *
Программа должна быть максимально естественна (проста) с точки зрения кода.


А вот пример:

Цитата(brag @ Jun 20 2012, 01:28) *
Применяется для хранения сообщений для передачи между потоками...
Типа в одном потоке создаем обьект в куче, кидаем указатель на него в FIFO, другие потоки выгребают эти обьекты, выполняют соответствующие методы, возможно передают их дальше другим потокам(в том числе и родителю обратно) и подостижении состояния "final" обьект удаляется(это может произойти в любом потоке). Размер обьектов разный, тип разный. FIFO один. Лучшей реализации,чем использовать кучу пока не придумал.

Если после генерации сообщения поток блокируется, (у меня лично таких случаев 100%) вплоть до момента обработки, вообще кучу использовать не надо. А всё, что не успевает обрабатываться продюсер/консюмером - вообще выносится за ось, поскольку ставит под сомнение перфоманс этой оси. Я имею ввиду - пытаюсь обходиться одним тредом.

Сообщение отредактировал _Pasha - Jun 21 2012, 07:41
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 21 2012, 08:30
Сообщение #24


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Я не очень понимаю выражения "не использовать кучу". Тут 2 варианта, либо ты резервируешь память раз и навсегда, либо динамически выдаёш, забираеш. В первом варианти торетически память в большинстве случаев будет простаивать.


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
_Pasha
сообщение Jun 21 2012, 09:22
Сообщение #25


;
******

Группа: Участник
Сообщений: 5 646
Регистрация: 1-08-07
Пользователь №: 29 509



Цитата(Beginning @ Jun 21 2012, 11:30) *
Я не очень понимаю выражения "не использовать кучу". Тут 2 варианта, либо ты резервируешь память раз и навсегда, либо динамически выдаёш, забираеш. В первом варианти торетически память в большинстве случаев будет простаивать.

Забыли по вариант 3: объект, например, контент сообщения, создается как локальный, т.е. в стеке, а в очередь записывается указатель на него. Затем отправитель сообщения блокируется до обработки, по окончании обработки работа возобновляется, тело сообщения удаляется из стека при выходе из блока кода.
Go to the top of the page
 
+Quote Post
Beginning
сообщение Jun 21 2012, 09:33
Сообщение #26


Знающий
****

Группа: Свой
Сообщений: 511
Регистрация: 24-08-07
Из: БРЕСТ
Пользователь №: 30 053



Ну тут я вижу потенциальную проблему. Допустим памяти 100 байт. Есть две задачи. Сообщение занимает 100 байт. Какой стек вы выделите каждой задаче? Правильно по 100 байт и того получается 200, уже не влазим. Если есть куча, то система работоспособна. Разумеется память используется по очереди.
Т.е. я хочу сказать что при использовании стека в качестве хранилища данных, мы должны зарезервировать его максимальный размер при старте. Т.е. это первый вариант.


--------------------
Если хочешь вбить гвоздь, не ищи обходных путей, просто бери молоток и бей по этому чёртовому гвоздю!
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 21 2012, 09:58
Сообщение #27


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Цитата
Я уже писал про **p. Придётся везде лепить. А потом начнётся ***p и т. д.

к тому же перегруженные, а возможно и volatile - защищать это все дело надо будет в многопоточном приложении...

Цитата
GlobalUnlock. Ранее полученный указатель стал недействительным. Когда блок отпущен он можен быть сдвинут. Чтобы ещё раз добраться до блока нужно ещё раз вызвать GlobalLock.

Ну да, было дело wink.gif Вероятность схватить Deadlock резко возрастает и тормоза в том числе. в 21 веке никто так не делает...

Цитата
Ну и как эта система, себя оправдала?

а как себя оправдала Windows 3.1 16-bit? :D

Цитата
Если после генерации сообщения поток блокируется....
Если после генерации сообщения поток блокируется...

Это убивает прелесть многопоточности и "естетственности" программы. весь смысл прогонки обьекта по нескольким потокам - избавится от гемора, избавится от локов, упростить программу. попишу немного букавок в качестве примера.
Есть GSM модуль, протокол CMUX - 2 канала GSM & GPRS. Каждий канал обрабатывается только своим потоком.
Допустим GSM опрашівает состояние модуля, что-то там куда-то логирует и принимает и отправляет SMS. В SMS приходят команды. Допустим, пришла команда загрузить какой-то файл s ftp://ftp.murzilka.ru/01.zip. GSM формирует обьект-сообщение и кидает в очередь. GPRS по мере готовности выгребает сообщение и выполняет. в конце кидает его обратно в очередь(вернее само сообщение себя кидает и меняет состояние, эт уже детали реализации иерархии классов) и занимается дальше своими делами.
GSM по мере готовности выгребает сообщение и выполняет(отправляет SMS с отчетом о загрузке файла).
Конечно, можно было лочить каналы(довольно медленные) и делать все действия на месте(не отходя от кассы), но в сложном приложении(в том,которое есть на самом деле, все гораздо сложнее) запаритесь потом и система будет простаивать.на пример, чтобы прочитать следующую смс(вообще не относящуюся к командам связанным с GPRS) или снять следующее состояние модема надо будет ждать, пока тормознутый GPRS что-то там обработает минут так 10-15:))

Цитата
Если есть куча, то система работоспособна. Разумеется память используется по очереди.

Ну чтобы по очереди использовалось нужно это синхронизировать,а это не всегда уследишь на сложном проекте. если не синхронизировать - как уже було сказано в моей теме про кучу: если каждому потоку вероятно понадобится по 100 байт стека, то при реализации на куче и куча должна быть 200 байт(+ оверхед на заголовки):
Цитата
Раз у вас не хватает памяти чтобы распределить её в виде static или на стеке для всех потоков, значит возможна ситуация (и даже с большей вероятностью), когда много потоков запросит больше памяти чем есть. С наличием служебных полей управления блоками в heap и фрагментации это даже более вероятно, чем при static размещении.
Что ваша система должна делать при этом? Выдать отказ потоку (но значит алгоритм всех потоков должен рассчитывать, что может быть получен отказ в памяти)? Или приостановить выполнение потока (но может случиться dead-lock)?
Go to the top of the page
 
+Quote Post
maksimp
сообщение Jun 21 2012, 19:13
Сообщение #28


Местный
***

Группа: Участник
Сообщений: 313
Регистрация: 2-07-11
Пользователь №: 66 023



Цитата(brag @ Jun 21 2012, 13:58) *
Цитата
GlobalUnlock. Ранее полученный указатель стал недействительным. Когда блок отпущен он можен быть сдвинут. Чтобы ещё раз добраться до блока нужно ещё раз вызвать GlobalLock.

Ну да, было дело wink.gif Вероятность схватить Deadlock резко возрастает и тормоза в том числе.

Deadlock - вряд ли. Так как GlobalLock не предоставляет блок в исключительное пользование одному процессу. Много процессов могут вызвать GlobalLock для одного и того же блока одновременно - и получат успешно в ответ один и тот же указатель. GlobalLock блокирует только перемещение блока при дефрагментации.
Цитата(brag @ Jun 21 2012, 13:58) *
а как себя оправдала Windows 3.1 16-bit? :D

Вещь! была для своего времени. Впрочем эта система выделения памяти была действительно актуальна только до Windows 3.0 включительно, на процессоре 8086. Windows 3.1 на таком процессоре уже не могла работать.
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 21 2012, 22:53
Сообщение #29


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Цитата
Deadlock - вряд ли.

легко: Поток 1 занял взял GlobalLock, ожидает сообщение от потока 2. Поток 2 готов давать сообщение, для этого ему надо выделить блок памяти. куча фрагментирована, блока памяти нужного размера нету,другие блоки тоже двигать нельзя. дедлок готов. Такое может произойти,если приложение выделяет память в "peaks"-режиме. допустим wait и GlobalLock в потоке 1 поменять нельзя просто так.
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jun 22 2012, 02:45
Сообщение #30


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Beginning @ Jun 21 2012, 14:30) *
Я не очень понимаю выражения "не использовать кучу". Тут 2 варианта, либо ты резервируешь память раз и навсегда, либо динамически выдаёш, забираеш. В первом варианти торетически память в большинстве случаев будет простаивать.

Во-втором случае будет простаивать как минимум в 2 раза большее кол-во памяти.
Все кучефилы почему-то забывают об элементарной вещи, которая сводит на нет все +-ы кучи в embedded:
если к примеру 2 потока используют периодически каких-то 2 блока памяти и зависимость во времени этих использований невозможно детерминировать и возможны моменты одновременного использования (т.е. - невозможно поместить эти 2 блока в union static), то они совершенно забывают, что если выделять эти блоки на куче, то тоже будут моменты одновременного использования, соответственно - объём памяти в куче должен быть равен не менее чем сумме размеров блоков (а в реальности - более из-за заголовков).
Поэтому в типичном эмбеддед-приложении где нет запускаемых пользователем задач (которым при нехватке памяти можно отказать в запуске) или если нет таких потоков, выполнение которых можно остановить без ущерба функционированию системе при нехватке памяти, использование кучи не приводит к уменьшению требований по памяти, а наоборот - увеличивает требования к памяти + приводит к проблемам фрагментации.
Поэтому обычное static-размещение + union для использований неперекрывающихся по времени, однозначно рулит.
Поймите-же эту простую мысль, кучефилы, и творения ваши станут чуть менее глючными!!! sm.gif
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 22 2012, 11:36
Сообщение #31


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Полностью согласен с jcxz, сам прорабатывал возможность использования кучи и даже есть законченная реализация. там, где испольозвалось сейчас заменил на статик с последующей незначительной переделкой алгоритмов.
Go to the top of the page
 
+Quote Post
Axel
сообщение Jun 22 2012, 13:39
Сообщение #32


Местный
***

Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188



Цитата(jcxz @ Jun 22 2012, 05:45) *
Поэтому в типичном эмбеддед-приложении...
Поймите-же эту простую мысль, кучефилы, и творения ваши станут чуть менее глючными!!! sm.gif

Ну чего уж так брутально... Для меня например уже долгое время типичными являются аппликации с несколькими альтернативными режимами. Динамическое создание и убиение соответствующих классов проходит "со свистом", а наоборот - не всегда... А если еще и компоненты оси присутствуют в качестве полей этих классов, то и перформенс улучшается (не то, чтобы я это ощущал, но сознавать приятно biggrin.gif ).
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 22 2012, 17:23
Сообщение #33


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Цитата
несколькими альтернативными режимами

в моей практике тоже такое часто, обычно весь рижим в итоге упакован в 1 класс(а внутри уже может быть куча обьектов, втч классов общих для разных режимов) и placement new.
Go to the top of the page
 
+Quote Post
Axel
сообщение Jun 23 2012, 06:33
Сообщение #34


Местный
***

Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188



Цитата(brag @ Jun 22 2012, 20:23) *
...и placement new.

В общем случае это безусловно спокойнее, но (опять же, в моей конкретной практике) когда "динамика" испольсуется только для этих альтернативных классов, оба варианта выглядят равноценными.
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 23 2012, 07:43
Сообщение #35


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



практически да. только в моем случаи размер пула определяется на этапе компиляции U32 pool[MAX(sizeof(class1),sizeof(class2),...)/4];
И ни одно слово не простаивает. В случаи с кучей надо иметь запас
Go to the top of the page
 
+Quote Post
Axel
сообщение Jun 24 2012, 04:01
Сообщение #36


Местный
***

Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188



Цитата(brag @ Jun 23 2012, 10:43) *
...размер пула определяется на этапе компиляции...

А как Вы это делаете? Я, поскольку так не умею, делаю это как часть инициализации: определяю макс. размер класса, выделяю пул из кучи, и уже его потом использую для placement new... Кривовато выглядит sad.gif
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jun 24 2012, 06:47
Сообщение #37


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Цитата(Axel @ Jun 24 2012, 07:01) *
А как Вы это делаете?
Ну выше ж написано - pool[ MAX( ) ]
Т.е. цепочака макросов MAX с sizeof() классов, на этом форуме вроде уже не раз placement new обсуждался..
Можно и как-то так, чтобы длинные MAX не писать и условной компиляцией включать/выключать применение (не помню, писал ли раньше):
Код
#define SIZE_IN(class, type)  ((sizeof(class)+sizeof(type)-1)/sizeof(type))

#define POOL_PLACE(class) uint8_t place_for_##class [ sizeof(class) ]

#include "A.h"

#ifdef MODE_B_USED
#   include "B.h"
#endif

#include "C.h"

union pool1_member_sizes
{
    POOL_PLACE(A);
#ifdef MODE_B_USED
    POOL_PLACE(B);
#endif
    POOL_PLACE(C);
};

// автоматически получаем MAX всех размеров
uint32_t pool1[ SIZE_IN(pool1_member_sizes,uint32_t) ];


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post
Axel
сообщение Jun 24 2012, 07:45
Сообщение #38


Местный
***

Группа: Свой
Сообщений: 480
Регистрация: 21-11-04
Пользователь №: 1 188



Цитата(ReAl @ Jun 24 2012, 09:47) *
Можно и как-то так...

Спасибо, технично, уже включил в код.
Go to the top of the page
 
+Quote Post
brag
сообщение Jun 24 2012, 09:10
Сообщение #39


Профессионал
*****

Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046



Тогда уж красивее так вроде, зачем лишний макро?
И ручное выравнивание можно убрать и на 8-/16битных юзать вместо uint32_t соответствующій тип. Хотя, без разницы
Код
#define SIZE_IN(class, type)  (sizeof(class)/sizeof(type))

#include "A.h"

#ifdef MODE_B_USED
#   include "B.h"
#endif

#include "C.h"

union pool1_member_sizes{
    А а;
#ifdef MODE_B_USED
    B b;
#endif
    C c;
};

// автоматически получаем MAX всех размеров
uint32_t pool1[ SIZE_IN(pool1_member_sizes,uint32_t) ];
Go to the top of the page
 
+Quote Post
ReAl
сообщение Jun 24 2012, 12:30
Сообщение #40


Нечётный пользователь.
******

Группа: Свой
Сообщений: 2 033
Регистрация: 26-05-05
Из: Бровари, Україна
Пользователь №: 5 417



Ага, щас.
Заменяем (так быстрее, чем union редактировать):
Код
#define POOL_PLACE(class) class a_##class

Получаем кучу в духе:
Код
pn.cpp:31: error: member ‘A pool1_member_sizes::a_A’ with constructor not allowed in union

Цитата(brag @ Jun 24 2012, 12:10) *
И ручное выравнивание можно убрать и на 8-/16битных юзать вместо uint32_t соответствующій тип.
Да кто его знает...
Вот вдруг «захочется» на CM3 ровнять такие пулы на двойное слово, uint64_t.
А sizeof даст в байтах округлённое вверх до uint32_t.
И у какого-то класса будет их (uint32_t) нечётное количество.
И даст sizeof(отой_union)/sizeof(uint64_t) отбрасывание «лишнего» uint32_t и нехватку места в буфере.
Мне проще каждый раз вместо A/B написать (A+B-1)/B чем думать, где отсутствие округления вверх может вілезти боком.
Лишней памяти такая запись точно никогда не запросит, нехватки тоже гарантированно не будет, в отличие от A/B.


--------------------
Ну, я пошёл… Если что – звоните…
Go to the top of the page
 
+Quote Post

3 страниц V   1 2 3 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 2nd August 2025 - 15:19
Рейтинг@Mail.ru


Страница сгенерированна за 0.01792 секунд с 7
ELECTRONIX ©2004-2016