LINUX.ORG.RU

Аллокаторы

 


1

4

Обратил внимание, что все вокруг носятся с кастомными аллокаторами, а я про них толком ничего и не знаю.

Накидайте, плз, годных ссылок о том зачем они нужны, как их правильно использовать и чем они могу помочь простому самаритянину.

Ну или прямо здесь расскажите.


может не в тему, но...

Типа там чтобы систему не мучить, каждый раз вызывая new/malloc, сразу замаллокивают большой кусок памяти и потом быстро выделяют из этого куска кусочки помельче под объекты.

потом прикручивают гарбаж коллекторы и «имена» объектам и получается ЛNCП(недо)

Bad_ptr ★★★★★
()
Последнее исправление: Bad_ptr (всего исправлений: 2)

Изучал сабж на паре проектов (каюсь поверхностно). Ну разве что в отладке и травле насекомых гугловский чем-то помогает (в этом направлении не шевелил, но на то очень похоже). А вот профита в производительности не увидел никакого. Может в проектах что-то используется не так... хз, но хотелось бы присоединиться к вопросу, закаким сабж нужен если «без маркетинга»?

erfea ★★★★★
()

Для массового/быстрого выделения и освобождения объектов.

Используются в основном в ММО или для супертяжёлой динамической графики. Простому смертному о них знать нужно только то, что они существуют (как и о 90% фич C++ и STL).

E ★★★
()

зачем они нужны

Для того, чтобы бороться с фрагментацией адресного пространства. В тех крайне редких случаях, когда проблема фрагментации действительно возникает (обычно-то не возникает: стандартный glibc-шный malloc/free успешно решает эту проблему в 99.9% случаев, у него там под капотом мощная машинерия для этого).

Manhunt ★★★★★
()
Последнее исправление: Manhunt (всего исправлений: 6)

Простому самаритянину, скорее всего, ничем.

Буквально вчера Царя (7-го) опускали по этому поводу. Но модераторы всё потёрли вместе с Царём. Там упоминались «творческие» применения аллокаторов для автомагической записи в файл, например.

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

Исторически же, кастомные аллокаторы были на пике популярности лет 10 назад, когда libc-шные malloc-и во всех популярных ОС были мягко говоря ущербными (как в плане фрагментации, так и в плане блокировок). С тех пор как авторы g- и прочих libc прочитали Solaris Internals, все аллокаторы стали братьями близнецами на slab-ах c arena-ми.

anonymous
()
Ответ на: комментарий от crowbar

По сравнению с чем? Можно прикрутить кран в ущерб производительности.

И не надо оффтопить. Речь идёт о крестовых аллокаторах.

anonymous
()
Ответ на: комментарий от crowbar

Вы будете несколько удивлены... :) но тред как раз о том, как (точнее, зачем) заставить кресты этот самый malloc не дёргать.

anonymous
()

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

anonymous
()
Ответ на: комментарий от Bad_ptr

Мне, кстати, не совсем понятно зачем нужен сборщик мусора. Можно же сделать не только свой быстрый malloc, но и свой быстрый free (если описатели всех блоков памяти отсортированы, то объединять освободившийся блок можно со следующим и/или с предыдущим по списку блоком, а весь список оббегать нет нужды).

KivApple ★★★★★
()
Ответ на: комментарий от crowbar

Заканчиваю беседу с вами по причине полного непонимания матчасти...

anonymous
()
Ответ на: комментарий от KivApple

Здесь вопрос в том, кому нужен. Нужен он тем, кто не ниасилил быстрый free написать (кстати, ваш будет сильно тормознее дефолтного), а кто не знает когда его вызвать.

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

anonymous
()
Ответ на: комментарий от anonymous

ТС, ты?

Аллокаторы (комментарий)

Т.е. если сегодня твой работодатель нанимает людей, которые не понимают как использовать аллокаторы, можешь смело их выпиливать. Скорее всего, станет даже лучше.

anonymous
()
Ответ на: комментарий от anonymous

кстати, ваш будет сильно тормознее дефолтного

Ну я не говорю, что предложил идеальный вариант, просто привёл пример, что можно сделать free со сложностью O(1).

кто не знает когда его вызвать

Что плохого в подсчёте ссылок? При появлении в области видимости компилятор автоматически делает ref_count++, а при выходе ref_count-- и если ref_count == 0, то вызывает реактивный free. Какие потери производительности?

KivApple ★★★★★
()
Ответ на: комментарий от KivApple

Что плохого в подсчёте ссылок?

То, что они могут быть циклическими?

Какие потери производительности?

Сами же их и описали. Кроме того, в многопоточной среде потребуются atomic_inc/dec, которые на amd64 стоят сотню-другую тактов. Способ-то вполне рабочий, но использовать его где попало не стоит.

anonymous
()
Ответ на: комментарий от anonymous

Кроме того, в многопоточной среде потребуются atomic_inc/dec, которые на amd64 стоят сотню-другую тактов

Это чего там такого тяжелого?

AF ★★★
()
Ответ на: комментарий от KivApple

что можно сделать free со сложностью O(1).

А разве дефолтный не O(1)?

При появлении в области видимости компилятор автоматически делает ref_count++, а при выходе ref_count-- и если ref_count == 0, то вызывает реактивный free.

Ты изобрёл Vala. Но подсчёт ссылок — это управление временем жизни объекта; оно ортогонально аллокатору.

i-rinat ★★★★★
()
Ответ на: комментарий от KivApple

Я никогда не задумывался над этим — не нужно было. Но легко нагуглил преимущества и недостатки подсчёта ссылок и сборки мусора.

И потом, что значит не нашёл широкого применения? GLib в сях активно использует подсчёт ссылок, std::shared_ptr и старый std::string используют подсчёт ссылок. Опять-таки, Vala, неявно, через GLib. По-моему, это достаточно широко.

i-rinat ★★★★★
()
Ответ на: комментарий от AF

Это чего там такого тяжелого?

Занимает интерконнект процессоров, выносит линию из кешей других процов, и т.д. Короче нифига не локальная операция, которая очень плохо масштабируется.

Pavval ★★★★★
()
Ответ на: комментарий от anonymous

Буквально вчера Царя (7-го) опускали по этому поводу. Но модераторы всё потёрли вместе с Царём. Там упоминались «творческие» применения аллокаторов для автомагической записи в файл, например.

А можно ссылку на тред?

З.Ы. Царь Кукарек 7-ой. Звучит.

Pavval ★★★★★
()
Ответ на: комментарий от anonymous

Буквально вчера Царя (7-го) опускали по этому поводу.

В чем конкретно? Врёшь ведь.

Мало того, что Царь седьмой был забанен позавчера:

Блокирован 18.08.2014 22:05:33, модератором Pinkbyte по причине: троллинг и провокации

Там упоминались «творческие» применения аллокаторов для автомагической записи в файл, например.

Щито? Пересказать осилишь?

Но модераторы всё потёрли вместе с Царём.

Врёшь ведь. Пересказать осилишь?

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

Сегодня это нужно везде, кто не хочет падать форфан и быть дырявым говном.

Исторически же, кастомные аллокаторы были на пике популярности лет 10 назад, когда libc-шные malloc-и во всех популярных ОС были мягко говоря ущербными (как в плане фрагментации, так и в плане блокировок). С тех пор как авторы g- и прочих libc прочитали Solaris Internals, все аллокаторы стали братьями близнецами на slab-ах c arena-ми.

И где там «slab-ах c arena-ми.»? Можно мне увидеть? Ладно, арена это типа у каждой нити свой хип.

void * ptr0 = malloc(32 * 2);
  void * ptr1 = malloc(32 * 4);
  void * ptr2 = malloc(32 * 8);
  void * ptr3 = malloc(32 * 16);
  fprintf(stderr, "%p\n%p\n%p\n", ptr0, ptr1, ptr2, ptr3);
//
//  0x402030
//  0x402080
//  0x402110

Т.е. никакого слаба тут нет. Т.е. балабол. Это не разные слабы - это один слаб. Даже если это слаб, то в нём нет смысла, когда у всех их константный блок( в данном маллоке 16байт).

Т.е. это обычный блочный фсподный аллокатор с айонодой в ((void *)ptr - 16)(левыйблок), которая хранит флаги и длинну «файла»/«объекта»/«куска» - как это там у вас называется.

Т.е. После удаления проясходят те же дырки. Т.е. нужна таже онлайн дефрагментация. И полный обход кучи для её уплотнения.

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

Только вот фрагментация один хрена есть и такая же как у «10 лет назад». Заполенненость кучи так же влияет на производительность и тянет её на днище.

У слаба такой проблемы нет, ибо там в слабе константный размер блока и он не сливается. Т.е. тут просто не существует фрагментации и жопы при заполнении.

Только вот нужна арена на каждый bloc_size() и совершенно другое api.

Т.е. от слаба тут нет никаких плюсов. Просто балабольство.

carb_blog8
()
Ответ на: комментарий от NegatiV
char *data = new char[10];
char *a    = data + 0;
char *b    = data + 1;
char *c    = data + 2;

data = NULL;

К чему это? Ты же кукарекал, что в крестах не нужны указатели и это для лохов. Вон и рассуждай на уровне своих классиков.

Как компилятор должен освободить data?

В чем проблема отследить локальные производные data?

carb_blog8
()
Ответ на: комментарий от carb_blog8

К чему это? Ты же кукарекал, что в крестах не нужны указатели и это для лохов. Вон и рассуждай на уровне своих классиков.

Пруф? Цитату где я сказал «в С++ указатели не нужны».

В чем проблема отследить локальные производные data?

Проблема как раз в том и состоит что их тоже придется отслеживать. И это отследить:

char *data = new char[10];
char *a    = data + 9;

a = a + 100;
NegatiV
()
Ответ на: комментарий от NegatiV

А у сборщика мусора тут проблем не будет тоже? Ведь счётчик ссылок нужен обоим. Во всяких джавах, где активно используется сборщик мусора, массивы это объекты и таких проблем не может появится.

KivApple ★★★★★
()
Ответ на: комментарий от KivApple

В системах со сборщиком мусора указатели превращаются во что-то вроде:

typedef struct {
    void *addr; /* непосредственно сам адрес, можно еще указывать смещение от "базы" */
    void *base; /* адрес "базы", в нашем случае для a, b, c это data */
    unsigned long size; /* размер блока */
    unsigned long ref_count; /* счетчик ссылок *
} ptr;
В С/С++ такое не провернуть хотя бы поэтому:
char *f(long addr) {
    return (char*)(addr);
}
Придется запретить подобные преобразования иначе от подсчета ссылок толку ноль.

NegatiV
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.