2014-02-21 3 views
0

Несколько дней назад у меня была помощь членов SO в создании безопасной системы плагинов с использованием интерфейсов для связи между основным приложением и DLL. Это решило некоторые проблемы, с которыми я столкнулся с нарушениями доступа и утечками памяти, и теперь все работает отлично, без ошибок или сбоев.Delphi: Ускорение загрузки интерфейсных плагинов (DLL)

Итак, я создавал некоторые долго из-за плагин для этого проекта, которые приводят меня к другой проблеме: Скорость

Что я делаю сейчас, когда основные старты приложения, загружает все библиотеки DLL в определенную папку, которая следует за определенным именем patern.

код, я использую, чтобы загрузить их заключается в следующем:

if FindFirst(cfg.ExePath+cPathPlugins+'\np*.npl', faAnyFile, SR)<>0 
    then Exit; // npl files are in fact renamed dll's 

PluginHost := TPluginHost.Create as IPluginHost; 
Plugins := TObjectList<TPluginInfo>.Create(True); 

repeat 
    if (SR.Attr <> faDirectory) 
    then begin 
    dll := LoadLibrary(PChar(cfg.ExePath+cPathPlugins+SR.Name)); 
    if dll<>0 
    then begin 
     @PluginInit := GetProcAddress(dll, 'PluginInitialize'); 
     if Assigned(PluginInit) 
     then begin 
     Plugin := TPluginInfo.Create; 
     try 
      Plugin.Dll := dll; 
      Plugin.Intf := PluginInit(PluginHost); 
      Plugins.Add(Plugin); 
     except 
      Plugin.Free; 
     end; 
     end 
     else FreeLibrary(dll); 
    end; 
    end; 
until FindNext(SR)<>0; 
System.SysUtils.FindClose(SR); 

Этот бит кода занимает около 45 секунд для загрузки 7 плагинов. Ни один из этих dll не имеет кода инициализации, а PluginInitialize просто передает интерфейс хоста и извлекает интерфейс плагина.

Мои вопросы:

  1. Может число методов на интерфейсах влияет на скорость загрузки в данный момент? Я так не верю, но хотел бы подтвердить.

  2. Могло ли это время загрузки быть отрезанным, а при загрузке их при запуске?

Я подумал о альтернативы, имеющие имена плагинов для загрузки в базу данных и загрузки DLL сам только при первом использовании, но я предпочел бы не применить это, так как некоторые из этих плагинов должен запускаться автоматически по завершении некоторых событий во время выполнения приложения и не только при выборе опции меню по требованию.

Я подумал, что, возможно, это может быть сделано при загрузке плагинов в фоновом режиме, в другом потоке, но я не знаю, может ли это принести какой-либо риск, так как я никогда не использовал потоки. Я считаю, что основной риск с использованием потоков - это когда вы пытаетесь получить доступ к переменным, которые изменяются другими, верно ли это? В этом случае, как мне кажется, этого не произойдет, поскольку после загрузки плагина происходит захват имени плагина (с использованием одного из его методов) и добавление его в TButtonGroup, которая создается до начала поиска dll. ,

Вы считаете, что это будет хорошим решением? Если нет, вы можете указать мне любую альтернативу?

+1

То же самое, когда не отладка? В любом случае, вы должны определить, что требует времени. [Профиль] (http://stackoverflow.com/questions/368938/delphi-profiling-tools). Но с этим временем вы можете даже вручную профилировать. Просто переходите (F8) к каждой строке, наблюдайте, какое утверждение заметно медленнее. Затем при необходимости перейдите в (F7). Etc .. –

+1

Как @Sertac говорит, мы не можем отлаживать это для вас, потому что у нас нет загружаемых DLL или всего кода, который вы используете для их загрузки. Отлаживайте код самостоятельно или найдите профилировщик («Профилировщик Delphi» Google), который поможет вам найти проблему. В любом случае, ваш вопрос слишком широк; общее правило здесь: «Один конкретный вопрос за сообщение», и вы попросили четыре (два, которые вы пронумеровали, еще два в вашем последнем абзаце), которые не являются конкретными вообще. –

+0

@nunopicado Я предполагаю, что вы можете компилировать свои «плагины» без использования пакетов. Насколько велики DLL-файлы? – Graymatter

ответ

3

Проблема Ваша проблема в том, что DLL большие. Вам нужно создать DLL, используя пакеты времени выполнения. Таким образом, код загружается только один раз. Каждая DLL будет содержать дубликаты одного и того же кода. LoadLibrary загрузит DLL и вызовет код инициализации для каждой DLL. Это означает, что пакет X будет связан с каждым плагином, который использует его, и будет инициализирован при загрузке каждого подключаемого модуля. (исправлено)

Для автономного EXE-файла удалены пакеты времени исполнения. Это упрощает развертывание. Если вы хотите начать использовать систему плагинов, лучше переключиться на систему, включающую пакеты времени исполнения.

Это не означает, что вам необходимо сохранить каждый пакет времени выполнения отдельно. Например, если вы используете только элементы управления Dev Express в основном приложении или в одном плагине, вы можете позволить Delphi скомпилировать этот пакет в App/DLL.

Чтобы изменить, какие пакеты времени выполнения вы хотите сохранить отдельно, а какие из них вы хотите включить в проект, перейдите на страницу «Пакеты-пакеты времени выполнения» в параметрах проекта. Существует флажок, который позволяет вам устанавливать связь с пакетами времени выполнения. Под текстовым полем. В этом текстовом поле вы можете указать имена пакетов, которые вы хотите сохранить отдельно.

+1

Или пропустите ваш общий код из всех подключаемых модулей в библиотеку ресурсов, которую все они могут использовать. Загрузите эту DLL из хост-процесса и передайте ее дескриптор в каждую DLL-плагин, чтобы использовать –

+2

Да, это тоже помогает. Глядя на размер в 12 мегабайт, у меня есть подлый взгляд, что это что-то вроде элементов управления DevExpress, которые добавляют много. – Graymatter

+1

Да, любая подобная библиотека может вызвать раздутый размер файла. Это означает, что вы должны развернуть свои предложения 'uses' всюду и убедиться, что вы не используете ничего, что вам не нужно. –

Смежные вопросы