Войти
ФлеймФорумПрограммирование

realloc_t (2 стр)

Страницы: 1 2
#15
15:15, 24 мая 2017

1 frag / 2 deaths
> Ну тогда ещё вариант, на х64 должен работать: выделяешь маллоком террабайт
> оперативы, для векторов отдельный пул, тупо выдаёшь им адреса с разницей в
> гигабайт, то есть чтобы в виртуальном адресном пространстве коллизий не должно
> быть. А дальше кажись система сама догадается, что ты не используешь всю
> запрошенную память, и сама реально будет выделять тебе лишь сколько надо.

Не работает для мелких векторов на десятки-сотни байт. В твоём варианте под такие вектора надо память как минимум страницами (4к) выделять.
Но для векторов от нескольких страниц размером - норм вариант.


#16
15:19, 24 мая 2017

Panzerschrek[CN]
> Не работает для мелких векторов на десятки-сотни байт.
Для мелких векторов на десятки-сотни байт можно заранее резервировать по десятке-сотне байт.

#17
16:12, 24 мая 2017

exchg
> Что? Опять магия? Не взлетит.
да.

struct t_kernel{
  ...
  void*virtual_alloc(size_t size){
    auto va=alloc_virtual_arena(size);
    auto pa=alloc_phys_arena(size);
    a_few_checks_hidden_in_a_macro(va,pa);
    for(size_t i=0;i<va.number_of_pages;i++){
      va.get_page_info(i).phys_page_id=pa.first_phys_page_id+i;
    }
    recs.push_back(t_rec(size,va,pa));
    return va.ptr;
  }
  struct t_realloc_state{
    bool on;
    t_rec*prec;
    t_arena va,pa;
  };
  t_realloc_state rs;
  realloc_t realloc_begin(void*ptr,size_t size){
    auto&rec=get_rec_by_va_ptr(ptr);
    a_few_checks_hidden_in_a_macro1(rec,ptr,size);
    size_t new_phys_space=align_to_page_size(size-rec.size);
    size_t new_phys_pages=new_phys_space/page_size;
    auto va=alloc_virtual_arena(size);
    auto pa=alloc_phys_arena(new_phys_space);
    a_few_checks_hidden_in_a_macro2(va,pa);
    for(size_t i=0;i<rec.va.number_of_pages;i++){
      va.get_page_info(i).phys_page_id=rec.pa.first_phys_page_id+i;
    }
    for(size_t i=0;i<new_phys_pages;i++){
      va.get_page_info(va.number_of_pages-new_phys_pages+i).phys_page_id=pa.first_phys_page_id+i;
    }
    rs.on=true;
    rs.prec=&rec;
    rs.va=va;
    rs.pa=pa;
    realloc_t tmp={va.ptr,size};
    return tmp;
  }
  void realloc_end(realloc_t){
    assert(rs.on); rs.off=true;
    auto va=rs.prec->va;
    for(size_t i=0;i<va.number_of_pages;i++){
      va.get_page_info(i).phys_page_id=0;
    }
    rs.prec->va=rs.va;
    rs.prec->pa=rs. // эм... fail
  }
  ...
};
не взлетит.

1 frag / 2 deaths
> выделяешь маллоком террабайт оперативы,
диверсант
>тупо выдаёшь им адреса с разницей в гигабайт
диверсант

upd: обновил код.

#18
16:17, 24 мая 2017

Adler
> диверсант
> диверсант
Да и пох, лишь бы работало с нормальной скоростью и другим процессам жить не мешало.

#19
17:10, 24 мая 2017

Adler
не, ну пилите, Шура, пилите, она золотая )))

#20
18:04, 24 мая 2017

Зачем нужен этот потрясающий способ выстрела в ногу?
Если при реаллоке часть внутренностей ремапится на новые адреса (а это, емнип, работает только если у тебя в объекте есть целые страницы, т.е. объект как минимум больше 4KiB), то ты огребаешь очень нетривиальный случай. Ты, например, не можешь нормально поменять где-нибудь указатель/pub-sub на новый адрес, т.к. по новому адресу память технически еще не выделена и сегфолтит. Если тебе это действительно нужно, то используй свой кастомный аллокатор с кастомным интерфейсом.
Ну а если получается malloc-free, то и обычного move'а хватит.

#21
18:52, 24 мая 2017

Fla
> Зачем нужен этот потрясающий способ выстрела в ногу?
я просто исхожу из предположения, что время выполнения realloc_ctor почти всегда меньше, чем время выполнения move_ctor. разве нет?

Fla
>т.к. по новому адресу память технически еще не выделена и сегфолтит.
у меня по задумке после realloc_begin одна и та же физическая память доступна по двум диапазонам виртуальных адресов, как на чтение так и на запись. откуда взяться segfault`у?

Fla
>Ты, например, не можешь нормально поменять где-нибудь указатель/pub-sub на новый адрес
я не проверял и поэтому не исключаю существование такой реализации realloc_ctor, которая будет успешного делать realloc для умных следящих указателей. всё остальные объекты которые использую механизм publisher/subscriber в своём устаревшего коде естественно обречены на костыли/переработку/забвение, впрочем им не привыкать.

Fla
> Если при реаллоке часть внутренностей ремапится на новые адреса (а это, емнип,
> работает только если у тебя в объекте есть целые страницы, т.е. объект как
> минимум больше 4KiB),
об этом я ещё не думал, но я не думаю, что тут могут быть какие-то нерешаемые проблемы. в крайнем случае с мелкими массивами можно работать как раньше.

#22
19:26, 24 мая 2017

Adler
> об этом я ещё не думал, но я не думаю, что тут могут быть какие-то нерешаемые
> проблемы. в крайнем случае с мелкими массивами можно работать как раньше.
так получается, что если ты будешь оперировать блоками равными размеру страницы
для увеличения выделенного блока, то копирования не будет в принципе.

#23
19:47, 24 мая 2017

exchg
> так получается, что если ты будешь оперировать блоками равными размеру страницы
> для увеличения выделенного блока, то копирования не будет в принципе.
ну если не считать копирования "физических адресов" из описателей "старых страниц виртуальной памяти" в описатели "новых страниц виртуальной памяти", то похоже что да - никакого копирования не будет, только realloc_ctor вызвать и всё.

#24
20:11, 24 мая 2017
struct t_kernel{
  ...
  void*virtual_alloc(size_t size){
    auto va=alloc_virtual_arena(size);
    a_few_checks_hidden_in_a_macro(va);
    for(size_t i=0;i<va.number_of_pages;i++){
      va.get_page_info(i).phys_page_id=alloc_phys_page(); // freed phys_pages stored in doubly_linked_list
    }
    recs.push_back(t_rec(size,va));
    return va.ptr;
  }
  struct t_realloc_state{
    bool on;
    t_rec*prec;
    t_virtual_arena va;
  };
  t_realloc_state rs;
  realloc_t realloc_begin(void*ptr,size_t size){
    auto&rec=get_rec_by_va_ptr(ptr);
    a_few_checks_hidden_in_a_macro1(rec,ptr,size);
    size_t new_phys_pages=align_to_page_size(size-rec.size)/page_size;
    auto va=alloc_virtual_arena(size);
    a_few_checks_hidden_in_a_macro2(va);
    for(size_t i=0;i<rec.va.number_of_pages;i++){
      va.get_page_info(i).phys_page_id=rec.va.get_page_info(i).phys_page_id;
    }
    for(size_t i=0;i<new_phys_pages;i++){
      va.get_page_info(va.number_of_pages-new_phys_pages+i).phys_page_id=alloc_phys_page();
    }
    rs.on=true;
    rs.prec=&rec;
    rs.va=va;
    realloc_t tmp={va.ptr,size};
    return tmp;
  }
  void realloc_end(realloc_t){
    assert(rs.on); rs.on=false;
    auto va=rs.prec->va;
    for(size_t i=0;i<va.number_of_pages;i++){
      va.get_page_info(i).phys_page_id=0;
    }
    free_virtual_arena(va);
    rs.prec->va=rs.va;
  }
  void virtual_free(void*ptr){
    auto&rec=get_rec_by_va_ptr(ptr);
    a_few_checks_hidden_in_a_macro3(rec);
    for(size_t i=0;i<rec.va.number_of_pages;i++){
      free_phys_page(rec.va.get_page_info(i).phys_page_id);
    }
    free_virtual_arena(va);
  }
  ...
};
+ old_code

upd: случайно стёр текст, когда вставлял код...
upd2: спрятал старый код, добавил новый.

#25
20:12, 24 мая 2017

Adler
> у меня по задумке после realloc_begin одна и та же физическая память доступна по двум диапазонам виртуальных адресов
Так страницы же памяти, а не любой регион. Вот лежит у тебя объект

... | <чужое добро> 16 байт | 4KiB | 3KiB байт <чужое добро> | ...
Ты собираешься:
1. мапить все три страницы на новый адрес
== realloc_ctor ==
2. анмапить крайние
3. мапить на их место новые пустые страницы
4. копировать 16 + 3KiB байт из старых крайних в новые крайние
5. донейтить пустое место на новых страницах в хип маллока
6. анмапить старую центральную (ну или донейтить, не суть)

У тебя два сискола из трех/четырех лишние.
А в случае с одним объектом в 16 байт посередине страницы, так вообще два сисколла из двух.

Если reaclloc_ctor вызывать всегда, то открываются новые горизонты тормозилова. Только в супер редких случаях типа (где ты вообще видел крестовые объекты, которые realloc'чат?), когда объект больше 4KiB, будет какой-то профит. Стоит ли ради этого вводить лишнюю сущность?
Если realloc_ctor вызывать не всегда, а только в этих супер редких случаях, то встает ровно тот же вопрос: стоит ли ради этого вводить лишнюю сущность? Возьми свой кастомный аллокатор, с кастомным интерфейсом, напиши свои operator new и operator delete.

Ты уверен, что профит то будет? Игра стоит свеч?

Ну и, это, как ты это собрался не то что в язык это пропихивать, а хотя бы в glibc этот realloc_begin дописывать?

#26
6:37, 2 авг. 2017

Плюсану ещё раз за запрет использования самоссылающихся объектов и использование обычного realloc.

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

Страницы: 1 2
ФлеймФорумПрограммирование

Тема в архиве.