четверг, 6 января 2011 г.

Qyoto, issues for investigation

Я выкачал исходники Qyoto и нашел в них несколько моментов, требующих более глубокого изученения:
  1. P/Invoke. Все managed обертки над Qt-шными классами содержат в себе член SmokeInvokation, через который осуществляются вызовы unmanaged кода и вызовы managed callback функций. Внутри этого класса все вызовы осуществляются через P/Invoke. Насколько это снизит производительность приложения? Предварительные тесты (на .Net Framework 4.0 показали), что вызов unmanaged функции без параметров через P/Invoke при отстутствии нагрузки на GC осуществляются в 50-70 раз медленнее, чем вызов аналогичной managed функции. Если в среднем managed код исполняется в 2-3 раза медленнее чем unmanaged и при этом он будет еще и осуществлять многократные вызовы через P/Invoke, то такой код будет работать в (2..3)*(50..70) = (100..200) раз медленнее чем unmanaged. Для нехитрого GUI со стандартными контролами это все равно кажется некритичным, но если вы, например, собираетесь отображать геоинформационные данные и ваши требования к производительности GUI высоки, то такое замедление видится неприемлемым. Более того, оно будет даже более существенным в случае маршаллинга данных и высоких нагрузок на GC. Тем не менее нужно изучить каковы накладные расходы на P/Invoke в Mono, может статься, что они не так уж велики.
  2. Следующий момент, это вызов деструкторов Qt-шных объектах в файналайзерах их managed оберток. Во-первых файналайзеры создают дополнительную нагрузку на GC и снижают производительность. Во-вторых в классах, поддерживающих интерфейс IDisposable, в методах Dispose() тоже вызываются деструкторы unmanaged объектов, но сами обертки при этом не помечаются как не нуждающиеся в финализации вызовом GC.SuppressFinalize(). В третьих, обращение к reference type объектам (SmokeInvokation) из файналайзеров кажется мне непрвильным, потому, что порядок уничножения reference type объектов недетерменирован и, таким образом, SmokeInvokation объект к моменту обращения уже может оказаться собранным GC. Это тоже нужно проверить.
  3. И наконец, если ref type объект был создан в некоторой функции и начиная с некоторого момента в создавшей его функции больше не будет обращений к нему, то GC разрешено собрать его, не дожидаясь выхода потока управления из данной, создавшей объект функции (я добавлю здесь пояснения). Таким образом может получится, что файналайзер объекта будет вызван из потока GC в то время пока unmanaged код все еще будет работать с его unmanged ресурасами. Чтоб предотвратить такую ситуацию нужно использовать HandleRef или GCHandle совместно с GC.KeepAlive. Нужно также проверить, как в Qyoto разруливается описанная ситуация и предусмотренна ли она вообще.

Комментариев нет:

Отправить комментарий