Я знаю, что это старый вопрос, но есть несколько вещей, которые, кажется, все упускают.
Во-первых, это умножение на 2: размер << 1. Это умножение на <em>что угодно между 1 и 2: int (float (size) * x), где x - это число, * является математикой с плавающей точкой, и процессор должен запустить дополнительные инструкции для приведения между float и int. Другими словами, на уровне машины удвоение требует одной очень быстрой инструкции, чтобы найти новый размер. Для умножения на что-то от 1 до 2 требуется не менее одна инструкция для приведения размера к плавающей запятой, одна инструкция для умножения (это умножение с плавающей запятой, поэтому, вероятно, потребуется как минимум вдвое больше циклов, если не 4 или даже в 8 раз больше) и одна инструкция для приведения обратно к int, и это предполагает, что ваша платформа может выполнять вычисления с плавающей запятой для регистров общего назначения, вместо того, чтобы требовать использования специальных регистров. Короче говоря, вы должны ожидать, что математика для каждого распределения займет как минимум в 10 раз больше времени, чем простой сдвиг влево. Если вы копируете много данных во время перераспределения, это может не иметь большого значения.
Во-вторых, и, вероятно, главный кикер: все, кажется, предполагают, что освобождаемая память является как смежной с самим собой, так и смежной с вновь выделенной памятью. Если вы предварительно не распределяете всю память, а затем используете ее в качестве пула, это почти наверняка не так. Операционная система может иногда в конечном итоге делать это, но большую часть времени будет достаточно фрагментации свободного пространства, чтобы любая наполовину приличная система управления памятью могла найти маленькую дыру, где ваша память просто поместиться. Как только вы доберетесь до по-настоящему кусочков, у вас будет больше шансов получить смежные фрагменты, но к тому времени ваши ассигнования станут достаточно большими, и вы не будете делать их достаточно часто, чтобы это больше имело значение. Короче говоря, интересно представить, что использование некоторого идеального числа позволит наиболее эффективно использовать свободное пространство памяти, но на самом деле этого не произойдет, если ваша программа не работает на голом железе (как, например, нет ОС под ним принимаются все решения).
Мой ответ на вопрос? Нет, идеального числа не существует. Это настолько специфично для приложения, что никто даже не пытается. Если вашей целью является идеальное использование памяти, вам не повезло. Что касается производительности, то менее частые распределения лучше, но если бы мы пошли именно с этим, мы могли бы умножить на 4 или даже 8! Конечно, когда Firefox переходит от использования 1 ГБ к 8 ГБ за один раз, люди будут жаловаться, так что это даже не имеет смысла. Вот некоторые практические правила, по которым я бы следовал:
Если вы не можете оптимизировать использование памяти, по крайней мере, не тратьте время процессора. Умножение на 2, по крайней мере, на порядок быстрее, чем математика с плавающей запятой. Это может не иметь большого значения, но, по крайней мере, будет иметь некоторое значение (особенно на ранних этапах, при более частых и меньших распределениях).
Не задумывайтесь над этим. Если вы потратили 4 часа, пытаясь понять, как сделать то, что уже сделано, вы просто потратили впустую свое время. Честно говоря, если бы был лучший вариант, чем * 2, это было бы сделано в векторном классе C ++ (и во многих других местах) десятилетия назад.
Наконец, если вы действительно хотите оптимизировать, не беспокойтесь о мелочах. В наши дни никому нет дела до потери 4 КБ памяти, если только они не работают на встроенных системах. Когда вы получаете 1 ГБ объектов размером от 1 до 10 МБ каждый, удвоение, вероятно, слишком много (я имею в виду, что между 100 и 1000 объектов). Если вы можете оценить ожидаемую скорость расширения, вы можете выровнять ее до линейной скорости роста в определенной точке. Если вы ожидаете около 10 объектов в минуту, то вполне вероятно, что рост от 5 до 10 размеров объектов за шаг (один раз каждые 30 секунд до минуты) вполне подойдет.
Все это сводится к тому, чтобы не переоценивать это, оптимизировать то, что вы можете, и настраивать для своего приложения (и платформы), если необходимо.