CLR здесь вообще не задействован, все это должно быть переведено в прямой машинный код без вызовов в CLR.JIT-компилятор отвечает за генерацию этого машинного кода, он имеет оптимизатор, который пытается создать наиболее эффективный код.У него есть ограничения, он не может тратить на это большое количество времени.
Одна из важных вещей, которую он делает, - это выяснить, какие локальные переменные должны храниться в регистрах ЦП.Это то, что изменилось, когда вы поместили свойство Height в локальную переменную.Возможно, он решил сохранить эту переменную в регистре.Но теперь есть еще один доступный для хранения другой переменной.Как и переменная x или y, которая критична для скорости.Да, это замедлит его.
У вас плохая диагностика внешнего цикла.Это может быть вызвано тем, что оптимизатор JIT реорганизовал код цикла, что затрудняет отображение профилировщиком отображения машинного кода обратно в соответствующий оператор C #.
Аналогичным образом, оптимизатор мог бы решить, что вы используете массив неэффективно, и переключить порядок индексации обратно.Не уверен, что это действительно так, но не невозможно.
В любом случае, единственный способ понять это - взглянуть на сгенерированный машинный код.Есть много достойных книг по ассемблерному коду x86, хотя их может быть немного трудно найти в наши дни.Ваша отправная точка - Debug + Windows + Disassembly.
Имейте в виду, однако, что даже машинный код не очень хороший предсказатель того, насколько эффективный код будет выполняться.Современные ядра ЦП чрезвычайно сложны, и машинный код больше не отражает того, что на самом деле происходит внутри ядра.Единственный проверенный и верный способ - это то, что вы уже делали: метод проб и ошибок.