Здравствуйте!
Обновился с версии 2.12 до последней версии VMProtect. Заметил одну неприятную особенность: моя программа стала работать намного медленее, причём в тех местах, где защита не применяется вовсе (например, при построении дерева оргструктуры). При тех же настройках проекта в версии 2.12 никаких тормозов нет.
Эксперементальным путём выяснил, что тормоза появляются при активации опции "Защита ресурсов". Из руководства пользователя я не понял до конца, какие именно ресурсы имеются в виду. Если программа шифрует, например, иконки и bitmap`ы, то это может объяснить тормоза при построении графических элементов. Влияет ли эта опция на саму защиту приложения от взлома или просто прячет ресурсы от любопытных глаз?
Тормоза при активации опции "Защита ресурсов"
-
- Posts: 7
- Joined: Fri Jan 22, 2016 8:41 pm
Re: Тормоза при активации опции "Защита ресурсов"
Защита ресурсов шифрует все ресурсы (битмапы, диалоги и т.д.) и возвращает указатель на них только по требованию программы, таким образом злоумышленник не сможет добраться до этой информации. В вашем случае скорее всего необходима оптимизация в плане работы с ресурсами (например все необходимые иконки можно было бы кешировать на старте или в процессе построения дерева).
-
- Posts: 7
- Joined: Fri Jan 22, 2016 8:41 pm
Re: Тормоза при активации опции "Защита ресурсов"
Если честно, я не понимаю что именно можно оптимизировать в моём случае. Для примера я взял процедуру загрузки должностей в таблицу TcxTreeList (компонент DexExpress).
Ниже упрощённый вариант моей процедуры.
Обращаю внимание, что процедура LoadPosts не включена в перечень процедур для защиты.
Запаковуем EXE и измеряем производительность:
Чистый EXE без VMProtect - 3,226 сек.
EXE с VMProtect 2.12 без защиты ресурсов - 3,328 мсек
EXE с VMProtect 3.0 без защиты ресурсов - 3,282 мсек
EXE c VMProtect 2.12 и защитой ресурсов - 10,688 мсек
EXE c VMProtect 3.0 и защитой ресурсов - прождал более 5 мин, и закрыл программу
Как видно тормозит именно защита ресурсов, остальные измерения в пределах погрешности.
Выдвигаю предположение, что тормоза из-за работы с иконками. Отвязываю таблицу от TImageList для чистоты эксперемента.
Теперь в таблице никакая графика не используеются. Перекомпилирую EXE и делаю повторные замеры:
Чистый EXE без VMProtect - 3,719 сек.
EXE c VMProtect 2.12 и защитой ресурсов - 12,859 мсек
EXE c VMProtect 3.0 и защитой ресурсов - снова не дождался
Как видим дело не в иконках.
Второе предположние - дело в скинах DevExpress, возможно при построении таблицы идёт запрос к каким-то графическим элементам, которые VMProtect зашифровал.
Отключаю скины (ставлю в настройках NativeStyle = TRUE) и перекомпилирую проект.
Чистый EXE без VMProtect - 3,250 сек.
EXE c VMProtect 3.0 и защитой ресурсов - без изменений
Теперь я в тупике. В таблице всего-то около 500 должностей, что там шифруется и расшифровуется так долго понять не могу. Все необходимые файлы готов сбросить куда скажите.
Ниже упрощённый вариант моей процедуры.
Code: Select all
Procedure LoadPosts;
Begin
// очищаем таблицу
c := GetTickCount; // измеряем производительность
PostsList.BeginUpdate;
PostsList.Clear;
// считывает элементы из БД
Results := Manager.CreateCriteria<TLiteOrgTree>.AddOrder(TOrder.Asc('ElementOrder')).List;
if Results.Count > 0 then
for i := 0 to Results.Count - 1 do
Begin
Node := PostsList.AddChild(nil); // Добавляем строчку в таблицу
// В зависимости от доступа и типа каждому элементу присваивается одна из иконок в TImageList.
// В ImageList всего загружено 9 иконок размером 16х16.
Node.ImageIndex := Results.Items[i].ElementType;
Node.Texts[0] := Results.Items[i].ElementName; // название должности
End;
Results.Free;
PostsList.EndUpdate;
ShowMessage(FloatToStr(GetTickCount - c) + ' мсек'); // выводим результат, сколько заняло построение таблицы
End.
Запаковуем EXE и измеряем производительность:
Чистый EXE без VMProtect - 3,226 сек.
EXE с VMProtect 2.12 без защиты ресурсов - 3,328 мсек
EXE с VMProtect 3.0 без защиты ресурсов - 3,282 мсек
EXE c VMProtect 2.12 и защитой ресурсов - 10,688 мсек
EXE c VMProtect 3.0 и защитой ресурсов - прождал более 5 мин, и закрыл программу
Как видно тормозит именно защита ресурсов, остальные измерения в пределах погрешности.
Выдвигаю предположение, что тормоза из-за работы с иконками. Отвязываю таблицу от TImageList для чистоты эксперемента.
Теперь в таблице никакая графика не используеются. Перекомпилирую EXE и делаю повторные замеры:
Чистый EXE без VMProtect - 3,719 сек.
EXE c VMProtect 2.12 и защитой ресурсов - 12,859 мсек
EXE c VMProtect 3.0 и защитой ресурсов - снова не дождался
Как видим дело не в иконках.
Второе предположние - дело в скинах DevExpress, возможно при построении таблицы идёт запрос к каким-то графическим элементам, которые VMProtect зашифровал.
Отключаю скины (ставлю в настройках NativeStyle = TRUE) и перекомпилирую проект.
Чистый EXE без VMProtect - 3,250 сек.
EXE c VMProtect 3.0 и защитой ресурсов - без изменений
Теперь я в тупике. В таблице всего-то около 500 должностей, что там шифруется и расшифровуется так долго понять не могу. Все необходимые файлы готов сбросить куда скажите.
Last edited by Petrov Dmitriy on Mon Jan 25, 2016 9:40 pm, edited 1 time in total.
-
- Posts: 7
- Joined: Fri Jan 22, 2016 8:41 pm
Re: Тормоза при активации опции "Защита ресурсов"
После дальнейших экспериментов нашёл конкретный кусок кода, который томозит. Вот он:
В этом куске я просто проверяю чтобы элементы в таблице не дублировались, нахожу дубли и удаляю. В StateIndex хранится не иконка, а ID элемента, мне так удобнее.
Да, код немного топорный, но проблем с быстродействием не возникало. Каким образом шифрование ресурсов на него влияет непонятно.
Естественно, я могу искать дубликаты более эффективно, например, при помощи TStringList и dupIgnore, но всёже, мне кажеться, что в любом случае, VMProtect не должен замедлять выполнение данного куска кода более чем в 100 раз.
Code: Select all
if PostsList.Count > 0 then
Begin
for i := PostsList.Count - 1 downto 0 do
for z := PostsList.Count - 1 downto 0 do
if (PostsList.Items[i].StateIndex = PostsList.Items[z].StateIndex) and
(i <> z) then
PostsList.Items[i].StateIndex := -1;
for i := PostsList.Count - 1 downto 0 do
if PostsList.Items[i].StateIndex = -1 then
PostsList.Items[i].Delete;
End;
Да, код немного топорный, но проблем с быстродействием не возникало. Каким образом шифрование ресурсов на него влияет непонятно.
Естественно, я могу искать дубликаты более эффективно, например, при помощи TStringList и dupIgnore, но всёже, мне кажеться, что в любом случае, VMProtect не должен замедлять выполнение данного куска кода более чем в 100 раз.
Re: Тормоза при активации опции "Защита ресурсов"
Присылайте минимальный пример (оригинальный EXE+VMP+MAP файлы), на котором можно воспроизвести проблему.
-
- Posts: 7
- Joined: Fri Jan 22, 2016 8:41 pm
Re: Тормоза при активации опции "Защита ресурсов"
Отправил пример на почту
Re: Тормоза при активации опции "Защита ресурсов"
В отладчике видно, что программа постоянно формирует текст ошибки "Index %d out of bounds". Почему она не показывается пользователю - вопрос или к вам или к разработчикам грида. В процессе формирования текста ошибки идет запрос к ресурсам в результате получаются вот такие тормоза.
Стек вызовов:
Unit1.TForm1.cxButton1Click
cxTL.TcxCustomTreeList.GetItem
cxTL.TcxTreeListNode.GetItem
dxCore.cxGetResourceString
System.LoadResString
Поставьте точку останова в незащищенном приложении на System.LoadResString и по стеку посмотрите из-за чего идет обращение к невалидному индексу.
Тормоза возникают конкретно здесь: if cxTreeList1.Items.StateIndex = cxTreeList1.Items[z].StateIndex
Стек вызовов:
Unit1.TForm1.cxButton1Click
cxTL.TcxCustomTreeList.GetItem
cxTL.TcxTreeListNode.GetItem
dxCore.cxGetResourceString
System.LoadResString
Поставьте точку останова в незащищенном приложении на System.LoadResString и по стеку посмотрите из-за чего идет обращение к невалидному индексу.
Code: Select all
for i := 0 to cxTreeList1.Count - 1 do
for z := 0 to cxTreeList1.Count - 1 do
if cxTreeList1.Items[i].StateIndex = cxTreeList1.Items[z].StateIndex
then
Begin
cxTreeList1.Items[i].StateIndex := -1;
End;
-
- Posts: 7
- Joined: Fri Jan 22, 2016 8:41 pm
Re: Тормоза при активации опции "Защита ресурсов"
Спасибо большое за ответ. Вы абсолютно правы! Ошибка в компоненте DevExpress. Код этого компонента очень запутанный, я не смог найти причину, по которой возникает ошибка, но зато я устранил тормоза, зайдя в файл cxTL.pas и в процедуре TcxTreeListNode.GetItem закоментировал строчку:
Это информация может быть полезна другим программистам, так как DevExpress один из самых популярных компонентов для Delphi.
Code: Select all
cxError((AIndex < 0) or (AIndex >= FCount), cxGetResourceString(@scxIndexOutOfBounds), [AIndex]); // <!-- здесь происходит загрузка ресурсов, которая тормозит
if Parent <> nil then
Parent.AdjustIndexes;
if (FLast.Index shr 1) <= AIndex then
begin
Result := FLast;
while Result.FIndex <> AIndex do
Result := Result.FPrev;
end
else
begin
Result := FFirst;
while Result.FIndex <> AIndex do
Result := Result.FNext;
end;
Re: Тормоза при активации опции "Защита ресурсов"
На самом деле можно было не лазить в чужие компоненты. Достаточно завести локальный ObjectList под создаваемые ноды и бегать уже по нему (шаблонный тип для TObjectList добавить по вкусу):
Code: Select all
var Nodes: TObjectList;
...
Nodes := TObjectList.Create();
for i := 0 to 300 do
Begin
Node := cxTreeList1.AddChild(nil);
Node.StateIndex := i;
Node.Texts[0] := 'Элемент ' + IntToStr(i);
Nodes.Add(Node);
End;
for i := 0 to Nodes.Count - 1 do
for z := 0 to Nodes.Count - 1 do
if Nodes[i].StateIndex = Nodes[z].StateIndex
then
Begin
Nodes[i].StateIndex := -1;
End;
Nodes.Free;