[Freeipa-devel] [PATCH] 1 Do lazy initializiation ipalib
Jan Cholasta
jcholast at redhat.com
Wed Nov 9 10:24:17 UTC 2011
Dne 3.11.2011 12:43, Alexander Bokovoy napsal(a):
> On Thu, 03 Nov 2011, Jan Cholasta wrote:
>> The problem with the API class is that it creates all the plugin
>> instances every time. Both mine and your patch don't change that,
>> they deal only with finalization, which is the easier part of the
>> lazy initialization problem. Additionally, in your patch finalize()
>> is called only on Command subclasses, so non-Command plugins are not
>> ReadOnly-locked like they should (currently this is done only when
>> production mode is off).
> I ended up with explicitly finalizing Object, Property, and Backend
> objects. This, by the way, proved that major slowdown is brought by
> the Command and Method instances as I've got statistically negligible
> variations of execution time, within less than 1%.
>
>> We could change API so that the plugins are initialized on-demand.
>> That way we could probably get rid off finalize() on plugins
>> altogether and move the initialization code into __init__() (because
>> all the required information would be available on-demand) and the
>> locking into API. The flaw of this approach is that it would require
>> a number of fundamental changes, namely changing the way API class
>> handles plugin initialization and moving the initialization of
>> "static" Plugin properties (name, module, fullname, bases, label,
>> ...) from instance level to class level. (Nonetheless, I think API
>> would't suffer from a facelift - currently it is messy, hard to read
>> code, with bits nobody ever used or uses anymore, some of the
>> docstrings and comments aren't correct, etc.)
> A review of API class is a good idea. However, I think it is currently
> enough what is in proposed patch as it gets you 2-3x speed increase
> already.
I've already started experimenting with the API class, hopefully it will
result in something useful :)
>
> One important feature I'd like to still keep in FreeIPA is ability to
> extend any object and action during plugin import phase regardless of
> the python source file it comes from. So far our split between 'user
> methods' and 'dnsrecord methods' is mostly utilitarian as they are
> implemented in their own source code files. However, nobody prevents
> you from implementing all needed modifications to all classes in the
> single source file and I expect this to be fairly typical to
> site-specific cases.
>
> This is something I'd like to keep as it has great value for all
> end-users and it requires loading all Python files in ipalib/plugins
> (and in ipaserver/plugins for server side).
I'm not suggesting we should skip importing the modules. The plugin
initialization process consists of these 3 steps:
1. import plugin modules
2. create plugin instances
3. finalize plugin instances
What I'm suggesting is that we do steps 2 and 3 on-demand. We can't do
step 1 on-demand, because we have no way of knowing what plugins are
available without importing the modules. (Both your and my patch does
only step 3 on-demand, but I think we can do better than that.)
>
>> Anyway, if we decide to go with your solution, please make sure
>> *all* the plugins that are used are finalized (because of the
>> locking) and add a new api.env attribute which controls the lazy
>> finalization, so that the behavior can be overriden (actually I have
>> already done that - see attached patch - just use
>> "api.env.plugins_on_demand" instead of "api.env.context == 'cli'").
> Done.
>
+ if not self.__dict__['_Plugin__finalized']:
+ self.finalize()
This doesn't seem right, coding style-wise. If you want to access the
property from outside the Plugin class, why did you name-mangle it in
the first place?
def finalize(self):
"""
"""
+ if not self.__finalized:
+ self.__finalized = True
+ else:
+ return
if not is_production_mode(self):
lock(self)
Finalize is supposed to be called just once, so IMO it would be better
not to do the check and let it throw the exception.
+ for i in ('Object', 'Property', 'Backend'):
+ if i in self:
+ namespaces.append(self[i])
AFAIK the framework is supposed to be generally usable for other
projects in the future. With that in mind, I think we can't afford to
hard-code things like this.
Anyway, I've made a patch that uses data descriptors for the trap
objects (which is IMHO more elegant than what you do). I've also managed
to add on-demand finalization to Object and Attribute subclasses by
moving the set-up code from set_api() to finalize() (it doesn't add much
performance, though). See attachment.
The numbers from my VM:
master abbra jcholast
$ time ipa
real 0m1.288s 0m0.619s 0m0.601s
user 0m1.103s 0m0.478s 0m0.451s
sys 0m0.161s 0m0.126s 0m0.133s
$ time ipa user-find
real 0m1.897s 0m1.253s 0m1.235s
user 0m1.119s 0m0.486s 0m0.488s
sys 0m0.160s 0m0.160s 0m0.136s
$ time ipa help
real 0m1.299s 0m0.629s 0m0.600s
user 0m1.094s 0m0.477s 0m0.446s
sys 0m0.183s 0m0.136s 0m0.140s
Honza
--
Jan Cholasta
-------------- next part --------------
A non-text attachment was scrubbed...
Name: freeipa-jcholast-57.1-lazy-finalize.patch
Type: text/x-patch
Size: 13780 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20111109/eb894df8/attachment.bin>
More information about the Freeipa-devel
mailing list