Boost :: Mutex & Malloc - PullRequest
       17

Boost :: Mutex & Malloc

2 голосов
/ 14 июня 2010

Я пытаюсь использовать более быстрый распределитель памяти в C ++.Я не могу использовать запас из-за лицензирования / стоимости.Я использовал NEDMalloc в однопоточном режиме и получил отличную производительность, но мне интересно, стоит ли переходить на что-то другое - насколько я понимаю, NEDMalloc - это просто замена для malloc () и free () на основе C, не операторы new & delete на основе C ++ (которые я широко использую).

Проблема в том, что теперь мне нужно быть потокобезопасным, поэтому я пытаюсь malloc объектакоторый подсчитывает ссылки (для предотвращения избыточного копирования), но который также содержит указатель мьютекса.Таким образом, если вы собираетесь удалить последнюю копию, вам сначала нужно заблокировать указатель, затем освободить объект и, наконец, разблокировать и освободить мьютекс.

Однако, используя malloc для создания повышения:: mutex кажется невозможным, потому что я не могу инициализировать закрытый объект, так как он вызывает конструктор напрямую. ist verboten.

Так что я остался в этой странной ситуации, где я использую new для выделения блокировки и nedmalloc длявыделить все остальное.Но когда я выделяю большой объем памяти, я сталкиваюсь с ошибками выделения (которые исчезают, когда я переключаюсь на malloc вместо nedmalloc ~, но производительность ужасна).Я предполагаю, что это связано с фрагментацией в памяти и неспособностью nedmalloc и new размещать nice рядом друг с другом.

Должно быть лучшее решение.Что бы вы предложили?

Ответы [ 4 ]

4 голосов
/ 14 июня 2010

Замена Google malloc довольно быстрая, по умолчанию безопасна для потоков и проста в использовании. Просто свяжите это с вашим приложением, оно заменит поведение или malloc / free и new / delete. Это позволяет легко перенастроить ваше приложение, чтобы убедиться, что новый распределитель действительно ускоряет процесс.

2 голосов
/ 14 июня 2010

Вы можете перегрузить глобальные операторы new и delete, чтобы вызвать новые версии malloc и free, которые вы используете.Это должно сделать вещи более приятными вместе, хотя я был бы удивлен, если бы это еще не произошло.

Что касается создания мьютекса, используйте размещение нового - это то, как конструктор вызывается вручную.Статический массив char будет выполняться через буфер.Например, глобальные переменные:

static char buf[sizeof(Mutex)];
static Mutex *m=0;

Затем для инициализации указателя m:

m=new(buf) Mutex;

(Вы также можете выровнять указатель и т. Д., Если необходимо, ипереименуйте переменные и т. д.)

Одна вещь, на которую стоит обратить внимание: если конструктор Mutex сам выделяет больше памяти, это может быть проблемой.Это маловероятно, но возможно.(В этом, вероятно, редком случае, обычно нет проблем со специальной реализацией кроссплатформенной оболочки мьютекса, которая не выполняет никакого выделения - или, хотя это в конечном итоге приведет к путанице,просто используйте #ifdef и используйте типы платформ напрямую. В любом случае, это не так много кода, и любой, имеющий опыт работы с рассматриваемой системой (-ами), может создать соответствующий код без ошибок за очень короткое время.)

Правильная очистка объектов, созданных таким способом, может быть сложной, поэтому я рекомендую не беспокоиться (нет, серьезно).Вполне нормально, чтобы этот материал просочился, когда вы используете его для реализации менеджера памяти;нет смысла сходить с ума по этому поводу.(Если вы работаете в системе, которая имеет представление о выходе из процесса, ОС в значительной степени гарантированно очистит базовый мьютекс для вас.)

1 голос
/ 14 июня 2010

Ну, обычно операторы C ++ new и delete внутренне вызывают простые библиотечные функции C malloc и free (плюс некоторая дополнительная магия, такая как вызов ctors и dtors), поэтому предоставление пользовательской реализации для этих функций может бытьдостаточно (это нередко при разработке встроенного C ++, но требует некоторой работы на уровне компоновщика).На какую систему и на какой компилятор вы ориентируетесь?

1 голос
/ 14 июня 2010

Профилировали ли вы и убедились, что фактическое выделение памяти является достаточно серьезной проблемой, что замена распределителя обеспечивает полезный выигрыш?

Безопасен ли поток NEDMalloc?

Часто стандартные операторы c ++ new / delete по умолчанию используют malloc и free, чтобы выполнить фактическое выделение памяти до / после вызова конструктора / деструктора. Если этого не происходит в вашей конкретной ситуации, вы можете переопределить глобальные операторы new и delete для вызова любой реализации выделения, которую вы пожелаете. Это требует некоторой осторожности, чтобы убедиться, что память всегда выделяется / освобождается одним и тем же распределителем (особенно при работе с библиотеками).

...