У бокса и распаковки одинаковый удар по производительности?

У бокса и распаковки одинаковый удар по производительности? Или распаковка происходит быстрее, скажем?

(Если да, можете ли вы кратко объяснить основную причину.)

Спасибо

3 ответа

Решение

Отчасти это зависит от того, что вы подразумеваете под "распаковкой". В терминах IL распаковка на самом деле делает немного меньше, чем в C#. В C# "распаковка" всегда подразумевает копирование значения куда-либо, тогда как в IL это означает только проверку типа поля и предоставление значения таким образом.

Хотя у них разные характеристики производительности: бокс требует выделения нового объекта, но не проверяет тип.

Распаковка на уровне IL действительно требует только проверки того, что объект, который вы пытаетесь распаковать, действительно является коробочным значением того же типа (или совместимого). Затем вам нужно добавить операцию копирования значения в C# версии распаковки.

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

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

В общих чертах, существуют некоторые фундаментальные факторы, определяющие производительность упаковки и распаковки в среде сбора мусора.

Предположим, что мы говорим о 64-разрядном целом числе (например, long в C#) на машине x64. Предположим далее, что это происходит внутри виртуальной машины, основанной на стеке, с использованием трассировки сборки мусора.

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

Во-вторых, в случае с боксом ссылочный тип должен быть выделен в куче, которая будет содержать наше значение. Это включает в себя достаточное количество служебных операций, таких как поиск резервной памяти, запись соответствующего заголовка объекта в память, а также значение нашего целого числа.

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

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

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

Насколько я знаю, распаковка намного дешевле, чем бокс. Учти это:

Int32 v1 = 5;

v1 размещается в стеке.

Object r = v1; // boxing

Компилятор принимает значение v1 и создает объект на его основе. Это занимает некоторое время (по нескольким причинам).

Тем не менее, когда этот код выполняется:

Int32 v2 = r; //unboxing

что происходит, что компилятор получает указатель на значение в штучной упаковке r сам, а затем копирует его в v2,

Другие вопросы по тегам