Как правильно закрепить объект в памяти?
От: jim100  
Дата: 18.02.19 12:40
Оценка:
Добрый день!

Есть задача закрепления в памяти массива байтов (на длительное время) для использования оного в unmanaged коде.

После создания объект перемещается в Gen2 с помощью двух вызовов GC.Collect().


byte[] data = File.ReadAllBytes(path);

if (GC.GetGeneration(data) != GC.MaxGeneration)
{
    // Move to 2nd generation (?).
    GC.Collect();
    GC.Collect();
}

// Pin byte array.
GCHandle gcHandleData = GCHandle.Alloc(data, GCHandleType.Pinned);


Но что-то мне все это не нра...
Нормальное ли это решение?
И есть ли какие-нибудь техники избежания фрагментации Gen2? (если таких массивов будт много, и жить они будут долго).

Спасибо!
Отредактировано 18.02.2019 12:41 jim100 . Предыдущая версия .
Re: Как правильно закрепить объект в памяти?
От: BlackEric http://black-eric.lj.ru
Дата: 18.02.19 14:25
Оценка:
Здравствуйте, jim100, Вы писали:

А зачем его вообще закреплять? Ну даже если вдруг сборщик его затрет — прочитаете еще раз. А фрагментацией вот вообще не помню когда интересовался. Зачем?
https://github.com/BlackEric001
Re: Как правильно закрепить объект в памяти?
От: hi_octane Беларусь  
Дата: 18.02.19 19:01
Оценка:
Хоть сто раз GC.Collect() вызови — ни малейшей гарантии что объект попадёт в 2-nd generation нет и быть не может. Всё сломает простейшая эвристика вида "if(памяти ещё дохрена) return;" которых в коде GC _много_.

J>Есть задача закрепления в памяти массива байтов (на длительное время) для использования оного в unmanaged коде.

Может тогда:
1) Выделить память в Unmanaged коде и вернуть его в Managed.
2) В Managed заполнить память нужными данными
3) Отдать заполненное в обработку в Unmanaged
????
Profit

J>И есть ли какие-нибудь техники избежания фрагментации Gen2?

Gen2 не фрагментируется. Фрагментируется LOH, и то на x86. На x64 я не уверен что проблема с этим вообще существует. Вот тут
Автор: hi_octane
Дата: 14.10.14
немного обсуждения и пример от Serginio1 который может помочь с тестированием на фрагментацию.
Re: Как правильно закрепить объект в памяти?
От: Sharowarsheg  
Дата: 21.02.19 03:44
Оценка: +1
Здравствуйте, jim100, Вы писали:


X = GCHandle.Alloc(ARRAY, GCHandleType.Pinned)

и потом

X.AddrOfPinnedObject()

даёт тебе IntPtr указатель, который ты можешь передать в unmanaged как void*

не забудь потом X.Free()
Отредактировано 21.02.2019 3:46 Sharowarsheg . Предыдущая версия . Еще …
Отредактировано 21.02.2019 3:45 Sharowarsheg . Предыдущая версия .
Re[2]: Как правильно закрепить объект в памяти?
От: Serginio1 СССР https://habrahabr.ru/users/serginio1/topics/
Дата: 21.02.19 09:11
Оценка: 23 (2)
Здравствуйте, hi_octane, Вы писали:

_>Хоть сто раз GC.Collect() вызови — ни малейшей гарантии что объект попадёт в 2-nd generation нет и быть не может. Всё сломает простейшая эвристика вида "if(памяти ещё дохрена) return;" которых в коде GC _много_.


J>>Есть задача закрепления в памяти массива байтов (на длительное время) для использования оного в unmanaged коде.

_>Может тогда:
_>1) Выделить память в Unmanaged коде и вернуть его в Managed.
_>2) В Managed заполнить память нужными данными
_>3) Отдать заполненное в обработку в Unmanaged
_>????
_>Profit

J>>И есть ли какие-нибудь техники избежания фрагментации Gen2?

_>Gen2 не фрагментируется. Фрагментируется LOH, и то на x86. На x64 я не уверен что проблема с этим вообще существует. Вот тут
Автор: hi_octane
Дата: 14.10.14
немного обсуждения и пример от Serginio1 который может помочь с тестированием на фрагментацию.


В 4.5 дефрагментируется и LOH. Кстати проще выделять память на стороне натива и удалять на его стороне.
Прошу прощения за руские названия. Был молод
https://habr.com/ru/post/304482/
Посмотри ВыделитьПямять
и солнце б утром не вставало, когда бы не было меня
Отредактировано 21.02.2019 10:16 Serginio1 . Предыдущая версия . Еще …
Отредактировано 21.02.2019 9:30 Serginio1 . Предыдущая версия .
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.