Как определиться с распределением стека и кучи против Boost:: Pool в таком случае?
У меня есть класс, который использует Boost:: Вариант для хранения двойной или строки, например:
class value
{
boost::variant<double, std::string> val;
};
Это должен быть неизменный тип значения для игрушечного интерпретатора, с которым я играю. Сначала казалось хорошей идеей передавать его по константной ссылке и возвращать по значению, и всегда размещать его в стеке, поскольку я хотел, чтобы он рассматривался как примитив. Однако потом я увидел, что его размер составляет 40 байт (в основном из-за размера std::string), и я немного волновался. Я знаю, что не следует выделять большие куски памяти в стеке, но насколько большой размер слишком велик?
Кроме того, копирование 40 байт каждый раз, когда я возвращаюсь, тем более что значение является неизменным и даже не требует копирования, выглядит как пустая трата.
Опция регулярного выделения кучи не кажется слишком привлекательной, поскольку у меня может быть тысячи таких распределений / освобождений в секунду.
Последний вариант, который я придумал, это иметь boost::pool для размещения этих объектов, когда это необходимо, и использовать boost::shared_ptr для управления их временем жизни. Однако, поскольку интерпретатор отвечает за выделение памяти (тип выделения памяти будет политикой, передаваемой интерпретатору в качестве аргумента шаблона), это будет означать, что класс значения должен знать о интерпретаторе, что немного усложняет ситуацию.,
Итак, вот вопросы:
- Что мне делать в этом случае и почему?
- Насколько большой "слишком большой" для размещения в стеке? Я уверен, что это зависит от того, как часто он выделяется и как часто его нужно копировать.
Благодарю.
2 ответа
- Что мне делать в этом случае и почему?
Как всегда, напишите программу, чтобы ее было проще понять. Если профилирование позже обнаружит, что это действительно проблема, вы всегда можете включить value::val
в некоторый динамически размещенный объект позже. (Конечно, это предполагает val
быть абстрагированным достаточно хорошо, чтобы это не затронуло ни одного из клиентов класса.)
- Насколько большой "слишком большой" для размещения в стеке? Я уверен, что это зависит от того, как часто он распределяется и как часто его нужно копировать.
Это также зависит от того, на какой платформе вы находитесь. Мы говорим о 8-битном встроенном чипе, работающем на вашем тостере или 64-битной рабочей станции?
ИМО, в конце концов, сводится к следующему: он слишком большой, если создает проблемы из-за своего размера.
Если вам действительно нужно оптимизировать это, я бы рекомендовал не использовать std::string
на винде.
Для неизменяемых строк реализация типа копирования при записи (в основном, все копии строки совместно используют один и тот же внутренний буфер) может быть легко реализована поверх shared_ptr
,
С тех пор вам понадобится только один указатель в вашем ConstString
класс, вам не придется беспокоиться о передаче по копии.