Название: Хранение "хвостиков" Отправлено: Igors от Сентябрь 21, 2015, 10:23 Добрый день
Есть структура Код И все в ней хорошо, если бы не одно "но" - по памяти она может оказаться весьма расходной. Когда mTail содержит приличное число эл-тов - все норм, расходы на вектор (и его пул) оправданы. Но часто тех эл-тов с гулькин "нос", всего 1-2. Часто число эл-тов фиксировано - но становится известным уже в runtime. Какой выход (учитывая что структуры могут интенсивно удаляться/создаваться)? Спасибо Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 21, 2015, 11:42 union?
Название: Re: Хранение "хвостиков" Отправлено: qate от Сентябрь 21, 2015, 13:43 преждевременная оптимизация - зло )
приведи реальные замеры, когда расходы хранения мешают быстродействию, расходу памяти и почему не QList<float> ? Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 21, 2015, 15:22 преждевременная оптимизация - зло ) Ну это давно уже "гимн ленивых" :) приведи реальные замеры, когда расходы хранения мешают быстродействию, расходу памяти Кстати про быстродействие я ничего не говорил - сами догадались :). Ну предположим в структуре всего 2 члена - тогда на ее заполнении время будет тратиться на конструктор вектора, push_back и new->mallocПо памяти: 1 или 2 флота займут 4 или 8 байт. Пустой std::vector - уже 12 байт (больше в 64 бит) + выделит минимум 16 байт, да расходы на сам блок - вот Вам и перерасход в 3-4 раза. А Qt контейнеры еще жирнее и почему не QList<float> ? Потому что при размере float = 4 QList тоже сводится к векторуНазвание: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 21, 2015, 17:21 В принципе, std::vector можно инициализировать константным количеством элементов, и тогда push_back не будет занимать значимое время. Но если кол-во элементов известно заранее, может, есть смысл использовать что-то вроде QPair? Специфики задачи не знаю, но лично я иногда так и делаю.
Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 21, 2015, 17:40 Специфики задачи не знаю, Ну пошли отмазки :) Никогда в С не делали такого?Код Но это некультурно, как то же самое цивильно? Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 21, 2015, 17:55 Почему я про специфику говорю - я не знаю, насколько имеет смысл иметь структуру с переменным кол-вом флоатов, как часто сия конструкция используется и т.д. Если речь только о том, что неохота 1 или 2 флота в вектор паковать, можно сделать, например, базовую структуру вообще без вектора и потом 3 раза от нее наследоваться, расширив либо вектором, либо одним флотом, либо двумя (в итоге получим 4 типа данных, один из которых будет базовым для остальных). Но опять же - я не знаю, как предполагается использовать такие данные.
А что до "некультурного" кода... Ну да, нехорошо как-то, такое все таки имхо через Юнион лучше делать... Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 21, 2015, 18:52 А что до "некультурного" кода... Ну да, нехорошо как-то, такое все таки имхо через Юнион лучше делать... Какой-то странный union Код К чему это? Все равно размер по максимуму, эффект тот же что и Код Ну это проходит только когда максимум известен и достаточно мал. А может быть что все имеют по 1-2, но находится один урод у которого 100. Да и вообще как-то не похоже на решение взрослого дяди :) ..можно сделать, например, базовую структуру вообще без вектора и потом 3 раза от нее наследоваться, расширив либо вектором, либо одним флотом, либо двумя (в итоге получим 4 типа данных, один из которых будет базовым для остальных). И потом у каждого виртуальный доступ к mTail - но классы-то разные, в контейнер их уже не положить, придется через указатели на базовый, не "плодим ли сущности"?Вот если нет интенсивного удаления - тогда можно просто сложить флоты в др контейнер и хранить индекс данных в нем Код Правда для доступа к флотам придется все время иметь под рукой 2-й контейнер (или разориться еще на указатель на него) - но в принципе терпимо. Но что делать если удалять надо, и часто? Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 22, 2015, 00:40 Ну дык идея то хорошая как раз, завести пул объектов, при удалении помечать объект как убитый, но в памяти он останется, так что при повторном использовании сразу доступен :)
Для максимального эффекта можно и несколько пулов завести. Название: Re: Хранение "хвостиков" Отправлено: qate от Сентябрь 22, 2015, 08:45 А Qt контейнеры еще жирнее замеры есть ? не забываем о Copy-On-Write, Implicit Sharing и Growth Strategies Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 22, 2015, 09:45 Ну дык идея то хорошая как раз, завести пул объектов, при удалении помечать объект как убитый, но в памяти он останется, так что при повторном использовании сразу доступен :) Как-то не выглядит "дешевым решением", если городить его для конкретного класса. Вот в общем виде - да, но что-то затрудняюсь выбрать подходящий стандартный контейнер.Для максимального эффекта можно и несколько пулов завести. замеры есть ? Я вижу что Вы много читали :) Но чем мощнее контейнер - тем больше накладные расходы. Это само по себе нормально, но речь как раз о ситуации(ях) когда эти расходы становятся неприятно велики (относительно полезной работы)не забываем о Copy-On-Write, Implicit Sharing и Growth Strategies Название: Re: Хранение "хвостиков" Отправлено: qate от Сентябрь 22, 2015, 10:28 Это само по себе нормально, но речь как раз о ситуации(ях) когда эти расходы становятся неприятно велики (относительно полезной работы) ну хоть один пример будет это подтверждающее ? чтобы я кроме опыта чтения приобрел и практическое подтверждение ) Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 22, 2015, 10:58 Как-то не выглядит "дешевым решением", если городить его для конкретного класса. Вот в общем виде - да, но что-то затрудняюсь выбрать подходящий стандартный контейнер. В этом случае темплейт в руки :) Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 22, 2015, 11:31 ну хоть один пример будет это подтверждающее ? Странно что у Вас проблемы с таким примером. Ну ладно, см. аттач. Рез-тычтобы я кроме опыта чтения приобрел и практическое подтверждение ) Цитировать (член структуры) time = 0.001 RAM = 203.1 Mb Да, и на MSVC в дебаге лучше его не запускать - не дождетесь.(std:vector) tine = 16.785 RAM = 1.38 Gb (QList) time = 17.968 RAM = 1.79 Gb Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 22, 2015, 11:33 В этом случае темплейт в руки :) Каким образом? Ведь число хранимых эл-тов известно в runtime (а не на компиляции), о чем уже говорилось вышеНазвание: Re: Хранение "хвостиков" Отправлено: qate от Сентябрь 22, 2015, 11:44 Ну ладно, см. аттач. Рез-ты test1 = 0.121 test2 = 13.464 test3 = 8.072 Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 22, 2015, 13:10 Ну ладно, см. аттач. Рез-ты test1 = 0.121 test2 = 13.464 test3 = 8.072 Название: Re: Хранение "хвостиков" Отправлено: m_ax от Сентябрь 22, 2015, 13:36 Лёгкое изменение теста (немного нагрузки и плюшек буста), то результаты уже не так разнятся:
Код
Сам тест: Код
Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 22, 2015, 13:56 В этом случае темплейт в руки :) Каким образом? Ведь число хранимых эл-тов известно в runtime (а не на компиляции), о чем уже говорилось вышеМожно сделать темплейт и определить через него пулы на 1, 2 и 3 элемента (например). А объект с данными будет содержать указатель на конкретный элемент в нужном пуле. Либо сделать один пул, который является вектором флотов и имеет на каждый флот флаг "занят"-"свободен", например, через битовую маску. Тогда нужный объект должен будет найти в пуле первые N свободных подряд идущих элементов и заюзать их. Но тут поиск нужен и т.д., имхо несколько пулов лучше. Название: Re: Хранение "хвостиков" Отправлено: xokc от Сентябрь 22, 2015, 14:02 Немного оффтопну. Вот никого не "воротит" от такого?
Код
Сравните с Код
Название: Re: Хранение "хвостиков" Отправлено: qate от Сентябрь 22, 2015, 14:09 Название: Re: Хранение "хвостиков" Отправлено: qate от Сентябрь 22, 2015, 14:12 мне также не ясно - зачем тащить std и буст в qt проект, если в qt есть все из них (имею ввиду то что уже есть)
мы же не заменяем qstring на std::string Название: Re: Хранение "хвостиков" Отправлено: kamre от Сентябрь 22, 2015, 14:15 Вроде бы какие-то реализации для std::string для коротких строк используют inplace буфер, а для больших указатель на память, выделяемую в куче. Вот здесь что-то очень похожее можно использовать.
Вот из MSVC 2012: Код: enum Название: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 22, 2015, 14:18 Ворвусь в тему. QVarLengthArray спасет отца. Краткость - сестра.
Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 22, 2015, 14:35 Немного оффтопну. Вот никого не "воротит" от такого? Та ужасно. И эти имена из одной-двух букв (хрен за что зацепиться моему слабеющему сознанию). Но начнешь критиковать - обзовут "старым ретроградом", "толстым троллем" и.т.п. Так что лучше молчать, мол "молодежный стиль" и все такоеМожно сделать темплейт и определить через него пулы на 1, 2 и 3 элемента (например). Это ничего нового не вносит. Понятно что проблема актуальна/возникает когда хвостиков "много" (мульены), а тогда темплейты создают неприятные проблемы с контейнером.А объект с данными будет содержать указатель на конкретный элемент в нужном пуле. Либо сделать один пул, который является вектором флотов и имеет на каждый флот флаг "занят"-"свободен", например, через битовую маску. Тогда нужный объект должен будет найти в пуле первые N свободных подряд идущих элементов и заюзать их. Но тут поиск нужен и т.д., имхо несколько пулов лучше. Код
Ну вот допустим я захотел хранить 0, 1, 2, 3, 4 флота напрямую (до 16 байт), а для большего числа эл-тов уже вектор. Длинноватая сопля получается в определении такого boost::variant и длинновато его инициализировать зная текущее число эл-тов. А главное - проблем с памятью это не решит. Какой бы ни был вумный boost::variant, а данные он будет хранить в куче (иначе это не variant). Ведь можно и просто так Код Не вижу чем (в данном случае) это хуже boost::variant, скорее лучше На мой взгляд самое естественное - хранить данные в др контейнере, (правда неясно в каком и как). Странно что никто не предложил ничего из этой оперы Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 22, 2015, 14:48 Ворвусь в тему. QVarLengthArray спасет отца. Краткость - сестра. Логика "пользователя Qt": какой класс из букваря похож? Ага, вот этот - ну все, берем :)Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 22, 2015, 15:00 Ну, контейнер (пул) объективно решит проблему частых аллокаций-деаллокаций. Производительность это подымет. Тогда надо так и делать:
int count; float * data; где data будет указывать на count элементов в пуле. Пулы, кстати, можно создавать тоже в рантайме :) В зависимости от кол-ва элементов "хвоста". Это, конечно, не упростит имплементацию, но фурычить будет шустрее. Название: Re: Хранение "хвостиков" Отправлено: m_ax от Сентябрь 22, 2015, 15:32 Цитировать На мой взгляд самое естественное - хранить данные в др контейнере, (правда неясно в каком и как). std::valarray. С ним получаются самые лучшие результаты: Код
Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 22, 2015, 15:41 Цитировать На мой взгляд самое естественное - хранить данные в др контейнере, (правда неясно в каком и как). std::valarray. С ним получаются самые лучшие результаты: Название: Re: Хранение "хвостиков" Отправлено: m_ax от Сентябрь 22, 2015, 15:49 Цитировать Так а что valarray, куда его лепить-то? Ай, нет.. прошу прощения, опечатался там в коде, поэтому такие времена получились.. Название: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 22, 2015, 17:01 Логика "пользователя Qt": какой класс из букваря похож? Ага, вот этот - ну все, берем :) Бля, какой же ты упоротый. Для идиота - это класс, которому можно преаллоцировать какое-то количество элементов на стеке (ваш юзкейз "2 флоата"), либо, при превышении этого лимита, он будет аллоцировать необходимое кол-во памяти в куче. Но почитать "букварь" нам же слабо. Мудила.Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 22, 2015, 17:22 Бля, какой же ты упоротый. Для идиота - это класс, которому можно преаллоцировать какое-то количество элементов на стеке (ваш юзкейз "2 флоата"), либо, при превышении этого лимита, он будет аллоцировать необходимое кол-во памяти в куче. Но почитать "букварь" нам же слабо. Мудила. А может не надо горячиться и примитивно хамить? :) Ведь QVarLengthArray валиден только в текущей области видимости и членом структуры быть не может.Название: Re: Хранение "хвостиков" Отправлено: Old от Сентябрь 22, 2015, 17:50 Ведь QVarLengthArray валиден только в текущей области видимости и членом структуры быть не может. Ну приехали. ::)Название: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 22, 2015, 19:17 Ведь QVarLengthArray валиден только в текущей области видимости и членом структуры быть не может. Может.Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 23, 2015, 08:24 Ведь QVarLengthArray валиден только в текущей области видимости и членом структуры быть не может. Тут я конечно фигню спорол, помнил что "выделяет на стеке" - ну и значит что-то типа "alloca" :). На самом деле все опять сводится к этомуКод QVarLengthArray может хранить др данные (не только float) и добавлять/удалять их - но меня интересует только хранение. В том-то и проблема что воспользоваться такой конструкцией я не могу, т.к. num должно быть известно на компиляции. Название: Re: Хранение "хвостиков" Отправлено: Old от Сентябрь 23, 2015, 08:38 В том-то и проблема что воспользоваться такой конструкцией я не могу, т.к. num должно быть известно на компиляции. Этот num в QVarLengthArray определяет границу.Если данных будет меньше num, то они будут храниться в float data[ num ], а при заполнении этого массива будет алоцирован буфер в куче. Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 23, 2015, 09:25 Пример
Код Т.е. привлечение CVarLengthArray ничего не решает, только тратится еще больше памяти на его служебные поля Вообще какое-то падение скорости можно пережить, в конце-концов есть нагрузка. Но по расходу памяти полный провал - 200Mb vs 1.37Gb :'( Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 23, 2015, 10:14 Расход памяти по сравнению чего с чем?
Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 23, 2015, 10:16 Расход памяти по сравнению чего с чем? См пост #13Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 23, 2015, 10:21 Собственно нужен контейнер (или кастомный аллокатор) который бы не удалял эл-ты, а оставлял "дырки", которые потом могут заполняться. Наверняка в дусте есть такой...
Название: Re: Хранение "хвостиков" Отправлено: m_ax от Сентябрь 23, 2015, 12:26 Цитировать Наверняка в дусте есть такой... Наверное, boost::small_vectorНазвание: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 23, 2015, 18:36 Код
Ну вот допустим я захотел хранить 0, 1, 2, 3, 4 флота напрямую (до 16 байт), а для большего числа эл-тов уже вектор. А уже далее ничто не мешает сделать Код: struct S Название: Re: Хранение "хвостиков" Отправлено: Old от Сентябрь 23, 2015, 18:44 Но по расходу памяти полный провал - 200Mb vs 1.37Gb :'( Вы так им пользовалтсь? :)Код
Название: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 23, 2015, 19:05 Old
Ну вы что, там же огромный оверхед - там есть int alloc и T* хранится не в юнионе. Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 23, 2015, 19:26 Получается, чтобы использовать пул, нужно в структуре хранить адрес свободного элемента (ну или индекс), это как минимум 4 байта для 32 битной системы или 8 байт для 64 битной. Т.е. по размеру эквивалент 1 или 2 флоата. Таким образом, пул для 1-флоатного варианта не имеет смысла на 32 битах. Чтобы уменьшить расход памяти, вариант с 1 флоатом можно тупо паковать в струкуру напрямую. С 2 флоатами - зависит от разрядности. В принципе, я бы тоже паковал в структуру. Для остальных можно делать либо пул, либо вектор.
Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 24, 2015, 09:40 Ну вот допустим я захотел хранить 0, 1, 2, 3, 4 флота напрямую (до 16 байт), а для большего числа эл-тов уже вектор. А уже далее ничто не мешает сделать Код: struct S Код Правда так CData теряет "самодостаточность", чтобы получить данные нужно знать др контейнер - но такого ограничения и не налагалось. Проблема в том что это годится только если нет интенсивного удаления эл-тов CData Наверное, boost::small_vector Это тот же самый QVarLengthArray. Похоже нужен cached_node_allocator, но разобраться там не так уж просто...Название: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 25, 2015, 07:55 Код
Название: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 25, 2015, 09:51 Подумал ещё. Мой вариант занимает 2*8 байт + данные или 8 байт + данные, если данных мало.
Ваш вариант занимает 2*8 байт + данные. Где ж тут "куда меньший оверхед"? Разве что на динамическую аллокацию, ну так это ж еще пул писать надо, фрагментацию учитывать. Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 25, 2015, 10:54 Ну это почти эквивалентно вектору с кастомным аллокатором, к-ый уже предлагали (http://www.prog.org.ru/index.php?topic=29333.msg215281#msg215281). Если Вы имеете ввиду пост #26 то неясно что там предлагалось - упоминалось о "пулах", и что с того?Подумал ещё. Мой вариант занимает 2*8 байт + данные или 8 байт + данные, если данных мало. Если float data1[4], то никак не меньше 16 да плюс счетчик. Да и вообще я могу отпихнуться unsigned int (вместо size_t) и иметь всегда 8Ваш вариант занимает 2*8 байт + данные. Где ж тут "куда меньший оверхед"? Разве что на динамическую аллокацию, ну так это ж еще пул писать надо, фрагментацию учитывать. В этом все дело. Чем поддерживать указатель на float? new/delete лучше вектора но при малых данных оверхед приличный. Напр 5 флотов - сам блок уже 32 байта плюс "обвязки" для кучи. А вот если мы храним данные в отдельном контейнере - они занимают ровно sizeofНазвание: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 25, 2015, 11:16 Я предлагал пулы в виде списка структур для 2, 3 и 4 флотов. При этом данные хранятся в отдельном контейнере, а объект имеет указатель на элемент пула. Убился объект - освободился элемент в пуле (но физически он остался в памяти). Добавился объект - нашли первый свободный элемент пула и связали с объектом. Нету свободных - добавили.
Заимплементировать такой пул несложно. Для 1 флота пул юзать не имеет смылса, т.к. флот займет столько же, сколько и указатель. А для бОльшего кол-ва данных - std::vector пойдет. Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 25, 2015, 11:31 Я предлагал пулы в виде списка структур для 2, 3 и 4 флотов. При этом данные хранятся в отдельном контейнере, а объект имеет указатель на элемент пула. Убился объект - освободился элемент в пуле (но физически он остался в памяти). Добавился объект - нашли первый свободный элемент пула и связали с объектом. Нету свободных - добавили. Позвольте, но ведь это (позорный?) "велосипед" :) Обдумывал в этом направлении, соображения:Заимплементировать такой пул несложно. - почему не для 5 тоже (или произвольного числа)? - почему бОльшая дырка не может заполняться? - в какой-то момент оказалось "почти все в дырках", как "освободиться"? и.т.д По сути это "своя маленькая куча" а раз так - это должна быть хорошо известная задача. Рыпнулся в буст, но.. Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 25, 2015, 12:27 Количество данных, которое имеет смысл держать в пуле, зависит просто от размера указателя на элемент в пуле. Допустим, в 32-битном приложении флоат займет 32 бита, и поинтер на элемент - тоже 32 бита. Т.е. 1 флот можно хранить просто в структуре данных. От 2 до N флотов уже займут больше, чем 1 поинтер - значит, имеет смысл, наверное, "пулить" (но мы всегда будем терять 32 бита из-за поинтера, вопрос в том, какой будет оверхед у вектора флотов std::vector<float>).
Насчет дырок - тут я не понял. Обычно пул - это просто 2 списка преаллоцированных элементов, один из них - "свободный", другой - "занятый". При освобожднии занятого он переходит в список "свободных", и наоборот. Поэтому "дырок" быть не должно в принципе. Да, это по сути велосипед, наверно. Но я не знаю, что еще предложить :) Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 25, 2015, 12:34 Насчет дырок - тут я не понял. Обычно пул - это просто 2 списка преаллоцированных элементов, один из них - "свободный", другой - "занятый". При освобожднии занятого он переходит в список "свободных", и наоборот. Поэтому "дырок" быть не должно в принципе. Я имел ввиду расклад "мульен "свободных" (дырок) и только 10 "занятых" - а память-то распределена для всехДа, это по сути велосипед, наверно. Но я не знаю, что еще предложить :) Да, и, как оно часто бывает, полезешь велосипедить, а оно оказывается не так уж мало/просто как казалось. Да, и заметьте, как красноречиво молчание "бустовских эстетов" :) А ведь задача явно из базовых.. Название: Re: Хранение "хвостиков" Отправлено: Racheengel от Сентябрь 25, 2015, 12:39 Фрагментация памяти - это зло... Сколько мы с ней боролись, ужас :(
Буст не спасает, когда нужен хардкор системного уровня, увы. Тут впору до ассемблера опускаться иногда. "Эстетики" в таком случае мало, к сожалению, когда должно "быстро летать", а не "красиво выглядеть"... Название: Re: Хранение "хвостиков" Отправлено: Old от Сентябрь 25, 2015, 12:47 Буст не спасает, когда нужен хардкор системного уровня, увы. Тут впору до ассемблера опускаться иногда. К сожалению, не все это понимают и поэтому регулярно пытаются там найти решения на все случаи жизни. :)Название: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 26, 2015, 10:55 В этом все дело. Чем поддерживать указатель на float? new/delete лучше вектора но при малых данных оверхед приличный. Напр 5 флотов - сам блок уже 32 байта плюс "обвязки" для кучи. А вот если мы храним данные в отдельном контейнере - они занимают ровно sizeof Шта? Типа float *data - это УЖАС оверхед, а size_t index - нет? Шта?Еще раз, sizeof(T*) == sizeof(size_t). Делая индекс вы ни на чем не экономите. В "другом контейнере" лежит 5 флотов (5*4) + size (8) + index (8). В куче лежит 5 флотов (5*4) + size (8) + указатель в кучу (8). У меня оверхед по памяти в исходном варианте потому что флоатов в структуре 4, ну так это дань скорости, сделайте 2 флоата (1 дабл) и не будет оверхеда. Гибкость же. Ваш вариант только отличается тем, что (по сути) вместо malloc используется кастомный аллокатор на пуле, но это вообще отдельная тема, когда их стоит/не стоит применять. Название: Re: Хранение "хвостиков" Отправлено: Old от Сентябрь 26, 2015, 11:23 Если использовать пулы, то можно сэкономить на хранении размера данных, оставив только указатель.
Т.е. структура будет хранить только указатель на float. Код
Код
Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 26, 2015, 11:37 Шта? Типа float *data - это УЖАС оверхед, а size_t index - нет? Шта? Вот как раз не та же. 4 флота хороши напр для 3D модели, которая чаще всего - треугольники, реже квадранглы, а остальные случаи (1, 2 и > 4) редки. Но в общем случае известно лишь что число флотов ("хвостиков") может быть мало, скажем, меньше 10. Нацеливаясь на какой-то конкретный случай Вы заметно проигрываете в остальных. Да и с uniоn неприятная возня, нужны геттеры/сеттеры. Не проблема конечно, но код явно не украшает.Еще раз, sizeof(T*) == sizeof(size_t). Делая индекс вы ни на чем не экономите. В "другом контейнере" лежит 5 флотов (5*4) + size (8) + index (8). В куче лежит 5 флотов (5*4) + size (8) + указатель в кучу (8). У меня оверхед по памяти в исходном варианте потому что флоатов в структуре 4, ну так это дань скорости, сделайте 2 флоата (1 дабл) и не будет оверхеда. Гибкость же. Ваш вариант только отличается тем, что (по сути) вместо malloc используется кастомный аллокатор на пуле, но это вообще отдельная тема, когда их стоит/не стоит применять. При условии что CData могут интенсивно удаляться - точно стоит (иначе достаточно вектора). Вопрос где взять такой аллокатор. В букваре ж нема... или я ошибаюсь? :)[OFF] Шта? Возможно Вам это кажется остроумным, но читать/понимать трудновато :)[/OFF]Название: Re: Хранение "хвостиков" Отправлено: Old от Сентябрь 26, 2015, 11:52 Вопрос где взять такой аллокатор. В букваре ж нема... или я ошибаюсь? :) Одним алокатором тут не обойтись. :)Есть boost::object_pool, можно взять его или написать свой пул (я бы писал свой). И на пулах пишите свой менеджер памяти, я чуть выше написал его возможности. Код
Буферы для количества элементов менее maxPrealloc будет браться из преалоцированных пулов, все остальные выделяться в куче. Напомню, здесь еще и на размере данных в CData экономиться. Название: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 26, 2015, 16:02 При условии что CData могут интенсивно удаляться - точно стоит (иначе достаточно вектора). Вопрос где взять такой аллокатор. В букваре ж нема... или я ошибаюсь? :) В общем, как обычно, задача сформулирована через жопу. Сначала вы пишете, что вектор ест слишком много памяти. Мы это обсуждаем 5 страниц. Потом оказывается, что "много памяти" - это один (!) лишний указатель, а на самом деле нам важна не память, а скорость аллокации. Собственно, см. мой эмоциональный пост. Название: Re: Хранение "хвостиков" Отправлено: Igors от Сентябрь 26, 2015, 16:27 Сначала вы пишете, что вектор ест слишком много памяти. Мы это обсуждаем 5 страниц. Потом оказывается, что "много памяти" - это один (!) лишний указатель, а на самом деле нам важна не память, а скорость аллокации. Возможно Вас сбило с толку "(иначе достаточно вектора)" - но это имеется ввиду хранить все хвосты в отдельном векторе (а не совать вектор в каждый CData), т.е. никакого противоречия здесь нет.В общем, как обычно, задача сформулирована через жопу. Откуда такая нетерпеливость? Зачем раздражаться и срываться на поросячий визг если Вы не увидели решения моментально? :) Я его тоже пока не вижу, вот и хорошо, есть о чем подумать.... Собственно, см. мой эмоциональный пост. Название: Re: Хранение "хвостиков" Отправлено: Авварон от Сентябрь 26, 2015, 16:49 Потому что вы пишете хрен пойми чем. Мне каждую фразу приходится перечитывать по нескольку раз.
Формулируйте задачу четко. Например: struct Data{ vector<float>;} не подходит 1. потому что жрет много памяти (float[N]+3*sizeof(void *)) 2. Потому что медленно аллоцируется. А дальше - "по 1 я хочу float[N]", "по 2 я хочу 0 malloc'ов". А не как обычно - тут "много" памяти, тут "медленно". А то получается, что вам "медленно", но по памяти есть запас, или наоборот, хоть и "медленно", но надо еще сильнее оптимизировать память. Просто вытягивать из вас 5 страниц нахуй никому не вперлось. И ладно если бы 1 раз такое, каждая ваша тема - только через 20 страниц высняется "ТЗ". Название: Re: Хранение "хвостиков" Отправлено: Old от Сентябрь 26, 2015, 17:37 Зачем раздражаться и срываться на поросячий визг если Вы не увидели решения моментально? :) Я его тоже пока не вижу, вот и хорошо, есть о чем подумать. Печально, а у меня уже есть рабочий прототип. Код
Цитировать Allocate pool 1 Allocate pool 2 Allocate pool 3 Allocate pool 4 Allocate heap 5 Allocate heap 100 Size heap 100 Size heap 5 Size pool 4 Size pool 3 Size pool 2 Size pool 1 Free pool 2 Free pool 1 Free pool 4 Free pool 3 Free heap 5 Free heap 100 |