Ответ 1
Здесь есть два фактора, которые делают этот код медленным. Вы не можете видеть это от IL, только код машины может дать вам понимание.
Сначала это общий, связанный с оператором AndAlso. Это оператор короткого замыкания, правый операнд не получает оценку, если левый операнд оценивается как False. Для этого требуется ветвь в машинный код. Ветвление является одним из самых медленных, что может сделать процессор, он должен догадаться о ветки спереди, чтобы избежать риска сброса трубопровода. Если он догадывается, что это неправильно, то это займет серьезный удар. Очень хорошо описано в этом сообщении. Типичная первичная потеря, если переменная a
является очень случайной, а ветвь, поэтому плохо предсказанная, составляет около 500%.
Вы избегаете этого риска, используя вместо этого оператор И, он не требует ветвления в машинный код. Это всего лишь одна инструкция, И реализована процессором. Нет никакого смысла в пользу AndAlso в таком выражении, ничто не пойдет не так, если будет проверен правый операнд правой стороны. Здесь не применимо, но даже если IL показывает ветку, то дрожание может все еще сделать машинный код без ветвления с инструкцией CMOV (условное перемещение).
Но наиболее важным в вашем случае является то, что класс Form наследуется от класса MarshalByRefObject. Цепочка наследования - MarshalByRefObject > Компонент > Контроль > ПрокруткаСвязь > КонтейнерControl > Форма.
MBRO обрабатывается специально компилятором Just-in-Time, код может работать с прокси для объекта класса с реальным объектом, живущим в другом AppDomain или другом компьютере. Прокси прозрачен для джиттера для почти любого члена класса, они реализованы как простые вызовы методов. Кроме полей, они не могут быть проксимированы, потому что доступ к полю выполняется с помощью чтения/записи памяти, а не вызова метода. Если джиттер не может доказать, что объект является локальным, он вынужден вызывать в CLR, используя вспомогательные методы с именем JIT_GetFieldXxx() и JIT_SetFieldXxx(). CLR знает, является ли ссылка на объект прокси или реальной сделкой и имеет дело с разницей. Накладные расходы довольно значительны, из-за правильного звучания 80 циклов.
Вы не можете этого сделать, если переменные являются членами вашего класса Form. Перемещение их в класс-помощник является обходным путем.