[Xfce4-commits] r30417 - in xfconf/trunk: . xfconf
Brian J. Tarricone
brian at tarricone.org
Thu Jul 30 00:24:15 CEST 2009
Hey all,
I added transparent caching support for libxfconf in svn trunk. It
seems to work ok for me, but it's likely there are bugs, and possible
there are some weird behaviors I haven't encountered yet.
See the log message below for a short explanation of how it works.
There are a couple of open questions about behavior that I haven't quite
figured out yet, so comments would be appreciated.
1. Currently XfconfChannel asks the XfconfCache to prefetch *all*
properties in the channel on creation (this does at least respect the
property_base for restricted channels). For larger channels this may be
a bad idea. However, there's no way to request a max number of channels
from the daemon, or a particular list of properties in one go; the only
way you can restrict it is by a property subtree.
2. There's an annoying bit when setting properties: if the property you
want to set isn't in the cache, it first fetches the property
(blocking), saves the old property value, stores the new value in the
cache, and sets the new property (non-blocking). The idea is that if
there's an error in the async property set, the cache can synthesize a
property-changed signal to return the property back to its original
state in the client. However, the blocking property get (to handle the
case where the property isn't cached) defeats one of the important
purposes of the cache: to avoid blocking. There are a couple options to
'fix' this:
a) Remove the blocking property get entirely. If the set fails, the
client just doesn't ever find out about the failure. This is kinda lame.
b) Remove the blocking property get and turn it into a non-blocking get.
Then queue up the non-blocking set to occur after the get returns.
This delays the set somewhat, but that might be ok. It increases
complexity quite a bit, which is not great.
c) Remove the blocking property get, and immediately send off the
non-blocking set. If an error occurs, *then* we do a non-blocking
property get, and do a property-changed signal to return the client's
view of the property back to its pre-set-failure value. This
presupposes that the only kind of error we care about is where the
client attempted to set a locked value, or some other kind of error
where a set would fail but a get would still succeed. If both the set
and get fail, we're kinda royally screwed anyway, so it might not matter
that the client has an inconsistent view of the world.
I have future plans that make these issues mostly moot. I'd like to
have xfconfd create a mmap()able cache file after properties get
changed, and libxfconf can read the cache directly for property values,
entirely avoiding dbus for property lookups (property setting and
checking locking status will still go through the daemon). I dislike
that this ties libxfconf to the daemon, but I think it's a reasonable
tradeoff for performance. libxfconf can always fall back to dbus if the
cache file isn't present. This bit is probably for 4.10 though.
3. XfconfCache has internal API for setting the max age (in seconds) of
items in the cache before they get evicted, as well as a max total
number of items in the cache. Does that seem useful at all? For apps
that use xfconf_channel_get(), the XfconfCache (and all its items) for
that channel effectively never gets destroyed (at least until you call
xfconf_shutdown()). That might be a bad thing. If you only use
xfconf_channel_new() and xfconf_channel_new_with_property_base(), then
the caches will get destroyed when the channels are destroyed. But if
you even make one xfconf_channel_get() call with the same channel name,
that will keep the cache alive forever, because while some XfconfChannel
objects are destroyable, and some are singletons, all XfconfCache
objects are singletons (every XfconfChannel with the same channel name,
regardless of property base, will share the same XfconfCache instance).
So... I'm still not sure if expiring stuff from the cache is useful.
Anyway, thoughts? Please test this if you can. In theory you shouldn't
notice anything different, except possibly desktop startup might be a
little bit faster, and the settings dialogs might come up a little
faster too. I suppose I should really attempt to benchmark these
things... maybe later.
-brian
On 07/29/2009 02:42 PM, Brian Tarricone wrote:
> Author: kelnos
> Date: 2009-07-29 21:42:58 +0000 (Wed, 29 Jul 2009)
> New Revision: 30417
>
> Added:
> xfconf/trunk/xfconf/xfconf-cache.c
> xfconf/trunk/xfconf/xfconf-cache.h
> Modified:
> xfconf/trunk/NEWS
> xfconf/trunk/xfconf/Makefile.am
> xfconf/trunk/xfconf/xfconf-channel.c
> xfconf/trunk/xfconf/xfconf-private.h
> Log:
> add transparent property prefetching and caching
>
> XfconfCache is a transparent cache that sits behind XfconfChannel,
> and, so far, involves no new API. this moves most of the dbus code
> from XfconfChannel to XfconfCache. on creation, XfconfChannel gets
> an XfconfCache object for that channel (the cache objects are
> per-channel-name singletons, regardless of property_base or whether
> or not the XfconfChannel is a singleton).
>
> on creation, XfconfChannel prefetches all properties in the channel.
> this might turn out to be a bad idea for large channels.
>
> property setting does not block if the setting is already in the cache.
> i may change this in the future to not block at all ever, but that
> might make reporting certain kinds of errors impossible. property
> resets are completely non-blocking. lookups are non-blocking if
> the setting is already in the cache. the cache automatically
> updates itself if another application modifies a property.
>
> the cache has hooks to set the maximum age of entries (in seconds)
> and the max number of entries to store in the cache. currently
> these two are unimplemented, and i'm not sure if there's value to
> exposing these in the public API.
More information about the Xfce4-dev
mailing list