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

Ваш ответ

Отображаемое имя (по желанию):
Конфиденциальность: Ваш электронный адрес будет использоваться только для отправки уведомлений.
Анти-спам проверка:
Чтобы избежать проверки в будущем, пожалуйста войдите или зарегистрируйтесь.

7 Ответы

0 голосов
от
Я встречал много советов по оптимизации, которые говорят, что вы должны пометить классы как запечатанный, чтобы получить дополнительные преимущества в производительности. Я побежал некоторые тесты, чтобы проверить различия в показателях и не нашел. Я делаю что-то неправильно? Я упустил случай, когда запечатанные классы дадут лучшие результаты? Кто-нибудь запускать тесты и видел разницу? Помогите мне узнать :)
0 голосов
от
Дрожание иногда будут использовать невиртуальные вызовы методов в запечатанных классов, поскольку они никак не может быть продлен. Есть сложные правила, связанные с созывом типа, виртуального/невиртуальная, и я не знаю их все, поэтому я не могу реально обрисовать их для вас, но если вы погуглите запечатанные классы и виртуальные методы, вы могли бы найти некоторые статьи по теме. Обратите внимание, что любой выигрыш в производительности вы хотели получить от такого уровня оптимизации следует рассматривать в качестве последней инстанции, всегда оптимизации на алгоритмическом уровне, прежде чем оптимизировать на уровне кода. Вот еще одна ссылка об этом: бредятина ключевое слово sealed
0 голосов
от
Ответа нет, запечатанные классы не выполняют лучше, чем негерметичные. Вопрос сводится к
call
против
callvirt
ОП коды Ил.
Call
быстрее, чем
callvirt
, и
callvirt
в основном используется, когда вы не знаете, если объект был разделен на подклассы. Поэтому люди считают, что если вы запечатать класса все ОП коды будут меняться от
calvirts
в
calls
и будет быстрее. К сожалению
callvirt
совсем другие вещи, которые делают слишком полезным, как проверка на null ссылки. Это означает, что даже если опечатался класс, ссылка все равно может иметь значение null и, следовательно, требуется
callvirt
это. Вы можете обойти это (без уплотнения классе), но это будет немного бессмысленно. Структуры использовать
call
, поскольку они не могут быть разделены на подклассы и не могут быть нулевыми. Обратитесь к этому вопросу для получения дополнительной информации: Позвоните и инструкция callvirt
0 голосов
от
Обновление: по состоянию на .Объем ядра 2.0 и .Сетка рабочего стола 4.7.1, среда CLR поддерживает Реал. Это может занять методов в запечатанные классы и заменить виртуальные звонки с прямыми призывами - и он также может сделать это для незапечатанных классов, если он может выяснить, что это безопасно. В таком случае (запечатанный класс, что среда CLR не мог иначе определить, как безопасно devirtualise), запечатанный класс на самом деле должны предложить какой-то выигрыш в производительности. Что сказал, Я не думаю, что это будет стоит беспокоиться, если вы уже обрисовали код и определить, что вы были в особенно жаркие путь называют миллионы раз, или что-то вроде этого: https://blogs.msdn.microsoft.com/dotnet/2017/06/29/performance-improvements-in-ryujit-in-net-core-and-net-framework/ Оригинальный Ответ: Я сделал следующее тестовую программу, а затем декомпилировать его, используя отражатель, чтобы увидеть, что код MSIL было испущено.
public class NormalClass {
    public void WriteIt(string x) {
        Console.WriteLine("NormalClass");
        Console.WriteLine(x);
    }
}

public sealed class SealedClass {
    public void WriteIt(string x) {
        Console.WriteLine("SealedClass");
        Console.WriteLine(x);
    }
}

public static void CallNormal() {
    var n = new NormalClass();
    n.WriteIt("a string");
}

public static void CallSealed() {
    var n = new SealedClass();
    n.WriteIt("a string");
}
Во всех случаях компилятор C# (в Visual Studio 2010 в релизе конфигурации сборки) издает идентичный код MSIL, который выглядит следующим образом:
L_0000: newobj instance void
0 голосов
от
Насколько я знаю, нет никаких гарантий производительности. Но есть шанс снизить производительность в некоторых конкретных условиях с герметичным методом. (запечатанного класса делает все методы, чтобы быть запечатаны.) Но это до реализации компилятора и среды выполнения. Детали Многие современные процессоры используют длинные структуре трубопровода для увеличения производительности. Потому что процессор-это невероятно быстрее, чем память, процессор для предварительной загрузки кода из памяти, чтобы ускорить производство. Если код не готов в нужное время, трубопроводы будут простаивать. Есть большое препятствие под названием динамическая диспетчеризация, который нарушает этот 'процесс' оптимизация. Вы можете понимать это как просто условное ветвление.
// Value of `v` is unknown,
// and can be resolved only at runtime.
// CPU cannot know which code to prefetch.
// Therefore, just prefetch any one of a() or b().
// This is *speculative execution*.
int v = random();
if (v==1) a();
else b();
Процессор не может следующий код предварительной загрузки, чтобы выполнить в этом случае, потому что следующая позиция кода это неизвестно до тех пор, пока условие не будет решена. Так что это делает опасность вызывает производство простаивает. И производительность на холостом ходу-это огромный в обычном. Аналогичные вещи происходят в случае переопределения метода. Компилятор может определить правильный метод переопределения для текущего вызова метода, но иногда это невозможно. В данном случае, правильный метод может быть определен только во время выполнения. Это также случай, динамическая диспетчеризация, а также, основная причина динамически типизированных языков, как правило, медленнее, чем статически-типизированных языках. Некоторые процессора (включая чипы последних процессоров Intel х86) использует технику, называемую спекулятивное выполнение, чтобы использовать трубопровод даже на ситуацию. Просто предвыборки один путь выполнения. Но попадание этой техники не так высока. И провал спекуляция причины сваливания трубопровода, что также дает огромную производительность. (это вполне по реализации ЦП. некоторые мобильные ЦП называется не такого рода оптимизация для экономии энергии) В принципе, C# является статически компилируемый язык. Но не всегда. Я не знаю точное состояние, и это полностью зависит от реализации компилятора. Некоторые компиляторы могут исключить возможность динамической диспетчеризации путем предотвращения переопределения метода, если метод помечен как
sealed
. Тупые компиляторы не могут. Это бенефис
sealed
. Этот ответ (почему он быстрее процесс отсортированный массив, чем неотсортированный массив?) описывает предсказания ветвлений намного лучше.
0 голосов
от
Обозначение класса
sealed
должны иметь влияние на производительность. Бывают случаи, когда
csc
может излучать
callvirt
опкод вместо
call
операции. Однако, похоже, эти случаи редки. И мне кажется, что компилятор должен быть в состоянии излучать те же номера-вызов виртуальной функции для
callvirt
, что она для
call
, если он знает, что класс не имеет подклассов (пока). Если существует только одна реализация метода, нет смысла нагружать его адрес из таблицы vtable—просто позвоните по одной реализации. Если на то пошло, Джит даже встроенные функции. Это немного рисковано, на в JIT часть, потому что если подкласс будет загружен позднее, в JIT придется выбрасывать, что машинный код и заново скомпилировать код, испуская настоящий виртуальный вызов. Я думаю, что это не происходит часто на практике. (И да, дизайнеры ВМ действительно агрессивно преследовать эти крошечные производительности выигрывает.)
0 голосов
от
Запечатанные классы должны привести к улучшению производительности. Поскольку запечатанного класса не может быть производных, любые виртуальные члены могут быть превращены в не виртуальных членов. Конечно, мы говорим очень небольшие успехи. Я бы не пометить класс как sealed просто, чтобы получить улучшение производительности, если профилирование показало, что это проблема.
...