C ++ / cli распознает переходы между управляемым / неуправляемым и измеряет их стоимость - PullRequest
2 голосов
/ 18 ноября 2010

Я все еще довольно новичок в C ++ / cli и не всегда уверен, когда пишу что-то, делаю ли я что-то, что создает переход между управляемым и неуправляемым временем выполнения. Например, я не могу добавить LARGE_INTEGER или std :: vector в качестве члена управляемого класса, но я могу использовать любой из них в середине управляемого метода, но я не знаю, создает ли это переход между управляемым и неуправляемым Время автономной работы. Как я могу увидеть каждую точку, в которой я вынужден сделать переход, и как я могу измерить стоимость этих переходов?

Одна возможность, которая приходит мне в голову, заключается в том, что я ожидаю, что в Windows будет «переход к неуправляемому» и «переход к управляемому» блоку кода. Существуют ли символы для тех, на кого я могу поставить контрольные точки, например, с windbg, чтобы я мог видеть каждый переход? Есть ли способ заставить визуальную студию показывать вам каждый переход во время выполнения?

Чтобы измерить результат при большом количестве переходов, существует ли соответствующая трассировка событий для событий Windows, которую я вижу с помощью xperf, или счетчики производительности для них, которые я вижу с помощью perfmon?

Ответы [ 2 ]

6 голосов
/ 18 ноября 2010

«Неуправляемая среда выполнения» - это немного оксюморон. Неуправляемый код не запускается на виртуальной машине. Кроме того, управляемая среда выполнения сама по себе является неуправляемым кодом. Я думаю, что вы заинтересованы в коде в целом, а не только в CLR и стандартных библиотеках, но, в конечном счете, все является нативным кодом, некоторые из них были созданы CLR JIT, а некоторые - нативным компилятором, но все это нативный код в конце. Существует даже общая модель обработки исключений (SEH) как для .NET, так и для собственных исключений (или, точнее, .NET использует предоставляемую ОС модель исключений).

После запуска JIT нет особых признаков управляемых-> неуправляемых переходов, поскольку они представляют собой простой вызов функции (отладчик может определить разницу, потому что неуправляемый код находится в адресном пространстве собственной библиотеки, и JIT-скомпилированный управляемый код находится в динамическом адресном пространстве, принадлежащем JIT). Обратное направление немного сложнее, поскольку инструкция вызова была создана перед кодом, который она вызывает, это должен быть косвенный вызов (через указатель на функцию). Но это по-прежнему указатель на JIT-скомпилированный код, а не на какой-то один неуправляемый -> управляемый thunk, где вы можете поставить точку останова. На самом деле указатель на функцию, вероятно, начинает указывать на сам JIT, который выясняет, какой метод вызывается, компилирует его, обновляет указатель на функцию и, наконец, вызывает конечный вызов, как если бы он был вызван в первую очередь. .

Это магия взаимодействия C ++. Это также означает, что управляемые -> неуправляемые переходы действительно даже не стоит беспокоиться. Профилируйте и узнайте, какие пути кода дороги, и если это окажется вызовом между управляемым и неуправляемым кодом, оптимизируйте его тогда. Но не ищите случайно управляемые / неуправляемые переходы.

Теперь есть и другие причины, по которым вы можете искать все управляемые / неуправляемые переходы. Например, сборщик мусора может прерывать любой поток, выполняющий управляемый код (опять же, код, который фактически выполняется, является нативным кодом, но GC может идентифицировать его, поскольку он находится внутри пространства памяти, используемого JIT, и таблицы использования объектов, созданные JIT, подробно описывают, что переменные стека являются достижимыми объектами при любом указателе инструкций). Поэтому, если вы хотите гарантировать, что определенный поток НИКОГДА не останавливается сборщиком мусора, вам нужно выследить и устранить все неуправляемые-> управляемые переходы в функциях, которые выполняются в этом потоке. Инъекция точки останова по-прежнему не будет правильным подходом, даже если бы было место для установки точки останова, так как она ловит только фактически выполненные переходы, а не условные.

0 голосов
/ 18 ноября 2010

Профилировщик - это тот, кто может дать вам ответ.Вы можете использовать VS2010 Profiler для измерения переходов.

Вы также можете использовать трассировку ETW, но анализировать их намного сложнее. PerfMonitor может помочь вам с трассировкой ETW.

К вашему сведению, даже профилировщик VS2010 использует только трассировку ETW, но у него есть лучший способ представить его.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...