Каковы издержки фиксированного оператора при использовании в неуправляемой структуре? - PullRequest
0 голосов
/ 24 июля 2010

В частности, я думаю о таком сценарии:

    unsafe struct Foo
    {
        public int Bar;

        public Foo* GetMyAddr()
        {
            fixed (Foo* addr = &this)
                return addr;
        }
    }

Предполагая, что Foo хранится в неуправляемой памяти, я пытаюсь выяснить, что входит в оценку фиксированного оператора в GetMyAddr. Как программист, я знаю, что эта структура никогда не находится в управляемой куче, мне просто нужно получить ее адрес в неуправляемой памяти наиболее эффективным способом. Меня особенно беспокоит, используются ли здесь какие-либо блокирующие или атомарные операции, так как это сделало бы их совершенно неподходящими.

Ответы [ 4 ]

7 голосов
/ 24 июля 2010

Это не будет делать то, что вы думаете, что будет делать.Оператор «fixed» только закрепляет управляемый объект (this) на время самого оператора «fixed» , который заканчивается, как только вы «возвращаетесь».Подробности см. В MSDN документах .

Вы уже говорите, что ваш "Foo" находится в неуправляемой памяти, что означает, что управляемый GC не будет перемещать его на вас.В таком случае, вы не можете просто вернуть «& this» напрямую?В качестве альтернативы вы можете рассмотреть возможность взять свой неуправляемый объект и упорядочить его как управляемый.Дайте немного больше информации о том, что вы делаете, и мы все сможем дать более конкретный совет.

2 голосов
/ 24 июля 2010

Выражение & не имеет смысла, когда структура присутствует в неуправляемой памяти.Там нет способа выделить его там.Ключевым свойством управляемых структур является то, что их макет памяти не обнаруживается и не совместим с неуправляемым представлением этой структуры.CLR переупорядочивает поля так, как считает нужным, чтобы получить минимальный размер при выравнивании элементов.Фактически он поменяет поля, если более поздние могут поместиться в заполнение.

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

0 голосов
/ 28 июля 2010

Я установил микро-бенчмарк и измерил издержки фиксированного значения при использовании структуры в неуправляемой памяти, она очень низкая, возвращение фиксированного (это) всего в 10 раз дороже, чем просто возвращение этого. Это приемлемо для моего варианта использования (хеширование с использованием адреса структуры.) Я не смог узнать, как это было реализовано, но в данном случае это выглядит достаточно быстро.

0 голосов
/ 24 июля 2010

В основном нет никаких накладных расходов. Исправлено означает «закрепить местоположение, на которое указывает указатель в памяти, не перемещать его». Любой другой управляемый указатель может быть «согнут» сборщиком мусора по желанию, если он решит переместить память. Исправлено предотвратит это, поэтому в основном это «сохранит» эти (возможные) накладные расходы.

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

С другой стороны, он предотвращает все виды оптимизаций, которые GC может решить выполнить с точки зрения управления памятью, такие как увеличение локализации, уменьшение фрагментации и т. Д.

...