[Kde-imaging] Fwd: On-demand-loading of KIPI plugins

Jesper K. Pedersen blackie at blackie.dk
Mon Nov 28 01:48:17 CET 2005


On Sunday 27 November 2005 18:24, Tom Albers wrote:
| Jesper K. Pedersen wrote:
| > I'm all for this change. Faster start up is a good thing.
|
| I doubt that ;-)
| When it results in unresponsive gui when people choose to do a
| kipi-action, because it has to load the kipi-plugin, I would rather
| think it is a very bad thing. I rather have a small delay in startup
| then delays when using the program.
Well that depends on the pattern of usage, doesn't it?
If people use plugins in almost all invocation of the application, then I 
agree that delayed loading isn't a good thing, on the other hand if they are 
seldom used, then I'm all for delaying loading them.

|  > Having said that, I don't have any time to put into this (just see
|
| how long it
|
| > took to answer this email ;)
|
| That is the problem with the digikam-team at the moment the same. We do
| not have time to change the kipi-interface, so that would form a problem
| for us.
|
| > If you are going for this, I think it would be really good if the two
| > kipi versions could co exists. Also it would be really nice to have a
| > check up on KIPI over all if we break BIC. See the libkipi/TODO for some
| > suggestions.
|
| Yes, I agree. Co existant would give us the flexibility to change
| digiKam in a later stage. I would like to point out that it should be
| done after a final release and that there will be extensive valgrind
| testing to make sure it behaves correctly.
|
| Tom
|
| > Cheers
| > Jesper.
| >
| > On Monday 24 October 2005 16:18, Aurelien Gateau wrote:
| > | Here is my proposal.
| > |
| > | ----------  Message transmis  ----------
| > |
| > | Subject: [Kde-imaging] On-demand-loading of KIPI plugins
| > | Date: Mercredi 12 Octobre 2005 23:51
| > | From: Aurelien Gateau <aurelien.gateau at free.fr>
| > | To: kde-imaging at kde.org
| > |
| > | Hello,
| > |
| > | We (Gwenview developers) have been receiving a few complaints lately
| > | about Gwenview memory usage and startup speed.
| > |
| > | One way to improve on this would be to implement on-demand-loading of
| > | KIPI plugins. That is: instead of dlopening all plugins on application
| > | startup, we would dlopen them only when a plugin action is triggered
| > | from the menu. I decided to have a look at what it would take to
| > | implement this and came up with a simple proof-of-concept
| > | implementation, which you will find attached to this message.
| > |
| > | kipi2-libkipi.diff contains all changes to libkipi.
| > | kipi2-kipi-plugins.diff contains the changes to the kipi-plugins I
| > | ported to (helloworld, calendar, printwizard and jpeglossless).
| > |
| > | I hopefully didn't break source compatibility (I did break binary
| > | compatibility), so if you fill adventurous you can try to rebuild your
| > | app with this new lib (I must confess I only tried it with Gwenview)
| > |
| > |
| > | Some numbers
| > | ------------
| > |
| > | Since measuring memory usage is a difficult art, only mastered by a few
| > | wise people :-) I restricted myself to measuring improvements on
| > | startup time. I hope you will all agree that not dlopening files leads
| > | to less memory usage (I would be interested to get some reliable
| > | numbers on memory usage, nevertheless).
| > |
| > | My machine is a Duron 1200, with 768Mb of RAM and a decent UltraDMA IDE
| > | disk. Here is how I ran my tests:
| > | * Uninstalled my packaged version of kipi-plugins
| > |
| > | * Patched the plugin-loading code of Gwenview like this:
| > | + QTime chrono;
| > | + chrono.start();
| > |  // Sets up the plugin interface, and load the plugins
| > |  KIPIInterface* interface = new KIPIInterface(this, mFileViewStack);
| > |  mPluginLoader = new KIPI::PluginLoader(QStringList(), interface );
| > |  connect( mPluginLoader, SIGNAL( replug() ), this, SLOT( slotReplug() )
| > | ); mPluginLoader->loadPlugins();
| > | + kdDebug() << "Load plugins: " << chrono.elapsed() << endl;
| > |
| > | * Rebuild the current libkipi,kipi-plugins and installed them as well
| > | as Gwenview to $HOME/opt/debug (my usual debug install dir).
| > |
| > | * Ran "export KDEDIRS=$HOME/opt/debug:/usr", then "kbuildsycoca"
| > |
| > | * Started Gwenview three times, results (in milliseconds) are:
| > |     1175 1042 1030 (Mean: 1082.3)
| > |
| > |
| > | Second set of tests, using only the KIPI2 ported plugins:
| > | * cd'ed into share/services/ and rm'ed the .desktop files for the
| > | plugins which was not ported to KIPI2.
| > |
| > | * run kbuildsycoca
| > |
| > | * Started Gwenview three times, results are:
| > |     264 238 308 (Mean: 270)
| > |
| > |
| > | Third set of tests, this time using KIPI2:
| > | * Build KIPI2 version of libkipi,kipi-plugins,gwenview and installed
| > | them to $HOME/opt/kipi2
| > |
| > | * Ran "export KDEDIRS=$HOME/opt/kipi2", then "kbuildsycoca"
| > |
| > | * Started Gwenview three times, results are:
| > |     74 56 55 (Mean: 61.6)
| > |
| > |
| > | As you can see, it's more than 4 times faster.
| > |
| > |
| > | How does it work?
| > | -----------------
| > |
| > | KIPI::Plugin acts as a proxy for the real plugin, which inherits from
| > | KIPI::RealPlugin. KIPI::Plugin objects are instanciated on application
| > |  startup and create KActions based on the action definitions of the
| > | plugin desktop files.
| > |
| > | The desktop file looks like this:
| > |
| > | [Desktop]
| > | ...
| > | Actions=action1;action2
| > |
| > | [Desktop Action action1]
| > | Name=Action1
| > | Name[fr]=Action1 FR
| > | Icon=back
| > | Category=1
| > |
| > | [Desktop Action action2]
| > | Name=Action2
| > | Name[fr]=Action2 FR
| > | Icon=forward
| > | Category=2
| > |
| > |
| > | All actions of a plugin are connected to the same KIPI::Plugin slot
| > | (slotActionActivated() ) which will first load and init the plugin if
| > | necessary, then execute the corresponding plugin slot. To execute the
| > | right slot It uses a little trick like this:
| > |
| > | -------
| > |  // Get the action name: this is the name of the plugin slot to call
| > |  const QObject* obj=sender();
| > |  Q_ASSERT(obj);
| > |  QCString name=obj->name();
| > |
| > |  // Create the slot based on the action name, then call it
| > |  QSignal signaler;
| > |  signaler.connect(d->m_realPlugin, "1" + name + "()");
| > |  signaler.activate();
| > | -------
| > |
| > | On the plugin side there are no KActions, only slots. In my example,
| > | there are two slots named action1() and action2().
| > |
| > |
| > | Limitations
| > | -----------
| > |
| > | There is no support for enabling or disabling actions. This can be
| > | easily implemented through another key in the action group which would
| > | specify what is necessary for the plugin. Some plugins want to have
| > | some images selected, others will work without any selection, letting
| > | the user choose between the application image collections.
| > |
| > | There is also no support for submenus. Again, this could be implemented
| > | using keys in the action group, but from a usability point of view I'm
| > | not sure it's a good idea: deep nested menus are not very handy to use.
| > |
| > | The current code is just a proof of concept, and I tried to avoid
| > | breaking source compatibility so that it's easier to test, but if we go
| > | for this a few things should probably be written in a different way
| > | (for example the PluginInfo and Plugin class should be merged).
| > |
| > |
| > | What do you think about this?
| > |
| > | Regards,
| > |   Aurélien
| > |
| > | -------------------------------------------------------

-- 
Jesper K. Pedersen          |  Klarälvdalens Datakonsult
Senior Software Engineer    |  www.klaralvdalens-datakonsult.se
Prinsensgade 4a st.         |
9800 Hjørring               |  Platform-independent
Denmark                     |  software solutions



More information about the Kde-imaging mailing list