<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Bloggy &#187; KDE</title>
	<atom:link href="http://www.purinchu.net/wp/category/kde/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.purinchu.net/wp</link>
	<description>The answer to life, the universe, and everything</description>
	<lastBuildDate>Fri, 30 Jul 2010 23:05:05 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Big update collection</title>
		<link>http://www.purinchu.net/wp/2010/07/30/big-update-collection/</link>
		<comments>http://www.purinchu.net/wp/2010/07/30/big-update-collection/#comments</comments>
		<pubDate>Fri, 30 Jul 2010 23:05:05 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[KDE]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[kdesvn-build]]></category>
		<category><![CDATA[car repair]]></category>
		<category><![CDATA[documentation]]></category>
		<category><![CDATA[juk]]></category>
		<category><![CDATA[kdesrc-build]]></category>
		<category><![CDATA[name change]]></category>
		<category><![CDATA[qt3support]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=646</guid>
		<description><![CDATA[Unfortunately I haven&#8217;t made any blog updates in awhile. I&#8217;ve been very busy between work and school (and I will likely spend this weekend working on a 20 page project that I&#8217;ve written 0 pages for ;). That doesn&#8217;t mean I have nothing to report though&#8230; First off, I have renamed kdesvn-build to kdesrc-build to [...]]]></description>
			<content:encoded><![CDATA[<p>Unfortunately I haven&#8217;t made any blog updates in awhile. I&#8217;ve been very busy between work and school (and I will likely spend this weekend working on a 20 page project that I&#8217;ve written 0 pages for ;). That doesn&#8217;t mean I have nothing to report though&#8230;</p>
<p>First off, I have renamed kdesvn-build to <a href="http://kdesrc-build.kde.org/">kdesrc-build</a> to reflect the fact that it builds from <a href="http://gitscm.org/">Git</a>-based software repositories. In conjunction I released <a href="http://kdesrc-build.kde.org/releases/kdesrc-build-1.12.php">kdesrc-build 1.12</a> which has various minor improvements, including a few Git improvements.</p>
<p>I&#8217;ve <a href="/wp/2010/07/06/timing-belts/">complained</a> about my car breaking down. It&#8217;s fixed, although I will be selling it now (my wife and I were debating the merits of getting an improved car for awhile before, this incident sealed the decision).</p>
<p>Just today I&#8217;ve committed a new feature to JuK, the sadly neglected KDE Software Compilation music manager. Now you can use the scroll wheel in the track announcement popup to quickly switch tracks without having to use the Next/Prev buttons. It&#8217;s probably already in every other media player with a playlist, but it&#8217;s at least in JuK now. Note that this is a 4.<em>6</em> new feature, not 4.5.</p>
<p>I&#8217;ve also been &#8220;reviewing&#8221; a patch to further remove Qt3 support code from JuK, which I will try to clean up and get comitted this release cycle. The big thing I still need to do is to finally convert from K3ListView to a real Model/View architecture to finally be rid of Qt3Support. Help is always appreciated btw =D</p>
<p>Burkhard Lück, the documentation super-hero, has been improving JuK documentation for me, but I still need to make some changes that he&#8217;s requested to bring the docs closer to 2008-era (let alone 2010) :(</p>
<p>That&#8217;s another good &#8220;intro to KDE Platform&#8221; kind of job by the way, it&#8217;s how I got introducing into coding for JuK myself. ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/07/30/big-update-collection/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Another transition for kdesvn-build</title>
		<link>http://www.purinchu.net/wp/2010/06/24/another-transition-for-kdesvn-build/</link>
		<comments>http://www.purinchu.net/wp/2010/06/24/another-transition-for-kdesvn-build/#comments</comments>
		<pubDate>Fri, 25 Jun 2010 03:00:12 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[KDE]]></category>
		<category><![CDATA[kdesvn-build]]></category>
		<category><![CDATA[amarok]]></category>
		<category><![CDATA[git]]></category>
		<category><![CDATA[kdecvs-build]]></category>
		<category><![CDATA[konversation]]></category>
		<category><![CDATA[name change]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=636</guid>
		<description><![CDATA[So if you have been looking at Planet KDE or the kde-scm-interest mailing list recently you will have noticed that some of our intrepid sysadmins have started setup the systems that will be needed to migrate the KDE source code to . Konversation and Amarok have already switched. kdesvn-build has already supported git (and the [...]]]></description>
			<content:encoded><![CDATA[<p>So if you have been looking at <a href="http://planetkde.org/">Planet KDE</a> or the kde-scm-interest mailing list recently you will have noticed that some of our intrepid sysadmins have started setup the systems that will be needed to migrate the KDE source code to <a href="http://www.git-scm.org/">. Konversation and Amarok have </a><a href="http://konversation.kde.org/">already</a> <a href="http://blog.lydiapintscher.de/2010/06/19/lets-move-that-source-code-so-it-doesnt-get-lazy/">switched</a>.</p>
<p>kdesvn-build has already supported git (and the upcoming 1.12 release has some git improvements), so building and installing konversation and amarok is as simple as fixing your kdesvn-buildrc to refer to the correct git repository. For Amarok and Konversation this means changing gitorious.org to git.kde.org for most users using the read-only clone URL (like git://gitorious.org/amarok/amarok.git). Read-write access occurs with a separate URL, lookup the TechBase entry for more info.</p>
<p><em>If you have already built a gitorious version of Amarok or Konversation</em> then you have two options to correct the downloaded source:</p>
<ol>
<li>Remove the source directory, and kdesvn-build will clone it again from the updated repository, or</li>
<li>Use the a manual git remote URL updating command as described on the <a href="http://konversation.kde.org/">Konversation homepage</a>.</li>
</ol>
<p>It has been awhile since a release of kdesvn-build, and the kdesvn-build <a href="http://kdesvn-build.kde.org/">website</a> was recently effectively offline due to an IP address change, so I&#8217;ll probably move to more stable KDE-hosted servers if possible. With all that in mind, it&#8217;s probably time to change the name again! (Who remembers <a href="http://cia.vc/stats/project/kde/kdenonbeta/kdecvs-build">kdecvs-build</a>? ;)</p>
<p>My initial plan for the name is kdesrc-build. I figure there&#8217;s no way this one won&#8217;t be future-proof (and besides, svn will still be supported for some time probably). ;) If anyone has better ideas for a name that is descriptive, relatively future-proof, and catchy, please leave me a suggestion in the comments.</p>
<p>While I&#8217;m polling the audience, I&#8217;ve been thinking about the design of kdesvn-build. Right now it is a 217 KiB single-file Perl script, with no external dependencies required aside from Perl 5.8. This is mainly to make it as easy to install and upgrade as possible. Does this ease of upgrading actually make a big difference for you all? It hasn&#8217;t been very difficult keeping the script in one file (I even managed to get Perl&#8217;s weird object orientation to work in one file) so I can keep that going if it&#8217;s worth it.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/06/24/another-transition-for-kdesvn-build/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Loading an icon with KIconLoader</title>
		<link>http://www.purinchu.net/wp/2010/06/08/loading-an-icon-with-kiconloader/</link>
		<comments>http://www.purinchu.net/wp/2010/06/08/loading-an-icon-with-kiconloader/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 05:18:04 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[KDE]]></category>
		<category><![CDATA[kiconloader]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=631</guid>
		<description><![CDATA[Given that I&#8217;ve recently been mucking about in the internals of KIconLoader and gaining more knowledge about its inner workings, I&#8217;ve learned a bit about how the icon loading mechanisms work in the KDE platform. I thought it would make for an interesting entry so here I go: First thing to keep in mind is [...]]]></description>
			<content:encoded><![CDATA[<p>Given that I&#8217;ve recently been mucking about in the internals of KIconLoader and gaining more knowledge about its inner workings, I&#8217;ve learned a bit about how the icon loading mechanisms work in the KDE platform. I thought it would make for an interesting entry so here I go:</p>
<p>First thing to keep in mind is that there is a relevant specification regarding icon themes, the <a href="http://standards.freedesktop.org/icon-theme-spec/icon-theme-spec-latest.html">FreeDesktop.org Icon Theme Specification</a>. Our implementation is intended to be compatible with this specification.</p>
<p>The basic idea of that spec is given a list of possible icon theme directory install locations (e.g. $XDG_DATA_DIRS, $KDEDIRS, etc.) and an icon theme (such as &#8220;Oxygen&#8221;), it gives definitions of how to install the icon theme metadata, including where it goes, what file names to use for the metadata, etc. It then defines how to use that icon theme metadata and a given icon name (such as &#8220;media-stop&#8221; or &#8220;dolphin&#8221;) to actually find an appropriate image to display to the user.</p>
<p>Each installed icon theme is described by an &#8220;index.theme&#8221; file installed at the top directory of the installed theme. This file contains obvious things like the name of the theme (including translations), but also a list of subdirectories, where each subdirectory has a specific size (e.g. 32&#215;32) and type (fixed size, scalable, etc.). In theory each installed theme can also be spread amongst locations in the icon search prefix (so that the user can override system icons for instance, by using $HOME/.icons)</p>
<h3>How KIconLoader works</h3>
<p>KIconLoader is typically accessed through KIconLoader::loadIcon(), although there are helper functions such as SmallIcon(), DesktopIcon(), etc. KIconLoader is also used even if you use KIcon directly. <strike>Qt can use KIconLoader for QIcons as well when run under a KDE Plasma desktop</strike>. (Edit: Olivier Goffart from Nokia has left a comment letting me know I was incorrect, Qt does not use KIconLoader). In most all cases KIconLoader::loadIcon() is where the action is actually taking place.</p>
<p>Of course, first you actually have to construct a KIconLoader, and that involves the following:</p>
<ul>
<li>Connecting to the shared data cache.</li>
<li>Loading a list of the cached &#8220;icon themes&#8221; (as represented by KIconTheme, and cached by KIconCache). KIconCache is one of the few (if not the only) remaining instances of KPixmapCache usage.</li>
<li>If the icon themes were not cached, they are initialized now (described below under &#8220;initializing the icon themes&#8221;).</li>
<li>Finally, some relevant metadata for each of the six possible icon groups (such as Desktop, Toolbar, MainToolbar, etc.) is loaded from the global configuration.</li>
</ul>
<p>The icon themes themselves are hopefully not forced to initialize at this point, but it could happen in the worst-case scenario, so let&#8217;s look at what that consists of:</p>
<h4>Initializing the icon themes</h4>
<p>Each icon theme is described by a KIconTheme, which can deal with a single icon theme. KIconLoader uses KIconThemeNodes to manage created KIconThemes. So, for each individual KIconTheme, the following occurs:</p>
<ul>
<li>If the theme is the default theme or the fallback theme (called &#8220;hicolor&#8221;) then any application-specific icons are added to the list of paths to search. This way applications can provide their own theme-specific icons.</li>
<li>In any event, the list of paths to search for our theme is then created, containing at least the KStandardDirs &#8220;icon&#8221; and &#8220;xdgdata-icon&#8221; resources, /usr/share/pixmaps, and &#8220;xdgdata-pixmap&#8221; resource (for GNOME compatibility).</li>
<li>The paths created in the first two steps are then searched, looking for the required index.theme for the requested theme, and also collating all the locations where icons for the theme are installed (recall that icons can be installed over multiple theme directories).</li>
<li>The index.theme is then read, and the list of subdirectories contained within is examined (e.g. 48&#215;48/apps, 32&#215;32/actions, etc.). Every possible subdirectory is verified to exist (or not) and its size requirements are read in. In KDE 4.4 my desktop would have had 106 paths to search, I&#8217;ve committed a patch for 4.5 that reduces that to approximately 78 by eliminating duplicate paths.</li>
<li>Any of the aforementioned subdirectories that contain Scalable icons then have every possible size (from the minimum to the maximum) added to the list of possible sizes for a requested size. For instance if the minimum size for a scalable directory type was 128 and the maximum was 256, then every integer size from 128 to 256 would be listed as a possibility for both 128 and 256 pixel-sized icon requests. Obviously the matching size would be preferred though.</li>
<li>Finally, the theme&#8217;s icon group definitions are read in (again, Desktop, Toolbar, etc.)</li>
</ul>
<p>At this point KIconLoader is still initializing its themes. In order to meet the icon theme spec, KIconLoader has to support icon theme inheritance, and falling back to the &#8220;hicolor&#8221; theme. To do this, KIconLoader has to load every theme that the selected theme inherits, and when that chain is over, inherit the &#8220;hicolor&#8221; theme as well. When I typed this with the default Oxygen icon theme selected, this resulted in three total themes: &#8220;Oxygen&#8221;, &#8220;Oxygen$app&#8221;, &#8220;hicolor$app&#8221;, where $app is the currently running application. I suspect that Oxygen and Oxygen$app were meant to be joined but I&#8217;m not sure.</p>
<p>KIconLoader will at this point finally have the selected theme, and all inherited themes, loaded. At this point KIconLoader does one more thing: It loads all of those icon theme search paths I mentioned earlier into its own KStandardDirs under an &#8220;appicon&#8221; resource type, along with a few others.</p>
<h4>Loading the icon</h4>
<p>At this point KIconLoader::loadIcon() is ready to actually do something. After my changes prior to KDE SC 4.5 it searches as follows (this should be very similar to 4.4&#8242;s behavior):</p>
<ul>
<li>If we are not searching for a &#8220;user&#8221; type of icon, which means that the icon is probably supposed to be already part of the desktop, then we use a function called findMatchingIconWithGenericFallbacks to look for the icon. That function uses a base function simply called findMatchingIcon, which itself searches all KIconThemes for 4 types of icons (PNG, SVGZ, SVG, XPM) first looking for &#8220;exact&#8221; matches, then for &#8220;best&#8221; matches. (The definition of &#8220;exact&#8221; depends on the icon theme, it doesn&#8217;t always mean pixel-perfect). If no icon was found, then the rightmost &#8220;dashed&#8221; chunk of the name is removed and the search done again (i.e. if no video-play-webm, then video-play would be searched, then simply video). The difference with findMatchingIconWithGenericFallbacks is that if findMatchingIcon fails, the search is done all over again, this time looking for &#8220;$name-x-generic&#8221;. findMatchingIcon is smart enough to not do the full search if it didn&#8217;t find the &#8220;-x-generic&#8221; type of icon.</li>
<li>Whew! We&#8217;re still in ::loadIcon. If findMatchingIconWithGenericFallbacks didn&#8217;t find anything, or a &#8220;user&#8221; icon is being searched for, then we use KIconLoader::iconPath instead. KIconLoader::iconPath() does a bit of work, but when looking for &#8220;user&#8221; icons is fairly simple, simply using the &#8220;appicon&#8221; resource I mentioned earlier to search for a named icon of the 4 image types allowed.</li>
<li>If no icon was found, the dreaded &#8220;unknown&#8221; icon is used (which is what led to a lot of the &#8220;question mark&#8221; icons in earlier KDE desktops).</li>
<li>Either way we have an icon now, which gets loaded and has an initial effects pass (such as desaturation for unselectable icons).</li>
<li>From there, favicons (for KHTML/Konqueror) are special-cased, and any icon overlays are applied.</li>
<li>To minimize future work for the loadIcon method, the result is added to the shared memory cache, and the icon is returned.</li>
</ul>
<p>Needless to say, that&#8217;s a <em>lot</em> of work to load one simple icon (assuming the caches were empty at least). In the common case the icon you want will already be in the cache. But even that only works if the icon you want has the exact same size and effects applied as what you&#8217;re looking for. (The cache is smart enough to store more than one size of a given icon however).</p>
<p>Probably the biggest takeaway is to not call KIconLoader::loadIcon() if you can avoid it, or any of its moral equivalents such as KIcon or QIcon. When you do call it, save the value if you&#8217;re going to need it later, unless you&#8217;re not going to need it for much later. If at all possible, use the global KIconLoader since it has already been constructed. Don&#8217;t use weird icon sizes, always prefer a standard size since it is likely to be found during the &#8220;exact match&#8221; phase instead of requiring a &#8220;best match&#8221; second-chance. Finally, it is probably possible to simply construct a suitable cache of available icons (perhaps in a background thread) so motivated individuals are encouraged to research that possibility. ;)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/06/08/loading-an-icon-with-kiconloader/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Implementing a shared cache: Part 4</title>
		<link>http://www.purinchu.net/wp/2010/05/20/implementing-a-shared-cache-part-4/</link>
		<comments>http://www.purinchu.net/wp/2010/05/20/implementing-a-shared-cache-part-4/#comments</comments>
		<pubDate>Fri, 21 May 2010 01:21:10 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[Implementing KSharedDataCache]]></category>
		<category><![CDATA[KDE]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[kshareddatacache]]></category>
		<category><![CDATA[series]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=628</guid>
		<description><![CDATA[Almost two weeks since I posted Part 3, which means it&#8217;s probably time to wrap up my series on implementing KSharedCache with this post. As a recap for those who don&#8217;t want to skip to the end of Part 3, I said I&#8217;d talk about having to defragment the shared cache and porting KIconLoader. Defragmentation [...]]]></description>
			<content:encoded><![CDATA[<p>Almost two weeks since I posted <a href="/wp/2010/05/08/implementing-a-shared-cache-part-3/">Part 3</a>, which means it&#8217;s probably time to wrap up my series on implementing KSharedCache with this post. As a recap for those who don&#8217;t want to skip to the end of Part 3, I said I&#8217;d talk about having to defragment the shared cache and porting KIconLoader.</p>
<h3>Defragmentation</h3>
<p>One of the sub-optimal parts of my implementation of KSharedDataCache is the fact that the data must be contiguous in memory. It would actually be fairly simple to change this due to the existing page design, but right now this is what we&#8217;ve got.</p>
<p>The reason this is sub-optimal is due to an effect called fragmentation (more precisely, external fragmentation). The effect is illustrated in the following diagram:</p>
<p><center><img src="/images/kshareddatacache-fragmentation.png" width="580" height="465"/></center></p>
<p>The problem with fragmentation can be seen in the cache layout at the bottom. The maroon blocks indicate allocated pages. In the bottom cache layout, even though the overall allocation is less than in the other cache, it is not possible to fit the new block in memory because there is no solid block of free memory of sufficient size.</p>
<p>This problem could be solved if only there were a way to move the allocated memory around. In the case of KSharedDataCache this can be done, because only the cache records the location of each data block (when an item is returned to an application, it is actually a copy). This process is called defragmentation, and is essentially the same idea as what disk-based defragmenters do.</p>
<p>My defragmentation is probably fairly naïve but does the job, simply looking for used pages of memory and moving them as far to the beginning as possible. The more interesting part is deciding when to defragment. Right now defragmentation is performed as follows:</p>
<ul>
<li>When we are having to remove currently-used pages due to insufficient consecutive memory when total free space is higher than a certain threshold, before pages are actually removed.</li>
<li>After evicting cache entries, since there are probably more holes in memory, and the reason we evicted things from the cache was due to insufficient consecutive free memory.</li>
</ul>
<p>As I said my defragmentation routine is very simple and could probably be easily improved. I haven&#8217;t noticed issues with it becoming a problem during desktop usage but that&#8217;s perhaps attributable to not coming into use very often (if at all) due to the cache aging I mentioned in Part 3.</p>
<h3>Porting KIconLoader</h3>
<p>Perhaps the largest impetus driving me to do all this work in the first place was due to KIconLoader, which used to use KPixmapCache to cache loaded icons. KIconLoader is used everywhere in KDE and so many KPixmapCache-related crashes were first noticed in seemingly very-unrelated applications when trying to load icons.</p>
<p>Porting KIconLoader to KSharedDataCache was not a direct method name replacement unfortunately, as one of the things KIconLoader stored was the path that the icon was found at. (This used to be done by using the custom data API for KPixmapCache I mentioned in <a href="/wp/2010/04/25/implementing-a-shared-cache-part-1/">Part 1</a>). I had first intended to use KImageCache (an image-related subclass of KSharedDataCache) for KIconLoader, but I ended up using KSharedDataCache directly, to hold cache entries that simply contained the pixmap and the path.</p>
<p>One problem that came up that I only fixed a few minutes ago was that KIconLoader would not only cache loaded icons, but it would also cache failed icon lookups, which was a behavior I had not ported over. This was especially notable in Dolphin browsing in large directories apparently. Either way, that is now fixed.</p>
<h3>Future Directions</h3>
<p>I&#8217;m proud of the work I put into KSharedDataCache, and especially since it has been running in trunk for about 4 weeks now with no major issues that seem to have popped up. However there are quite a few things that could be improved about it:</p>
<ul>
<li>Cache corruption: Although in my opinion the risk of crashes from a corrupted cache is less right now due to the cache layout and non-usage of QDataStream, the possibility is not zero. Because of the serious consequences of cache corruption leading to crashes, it would be nice to have an efficient way to mark that a disk cache should be deleted because it is corrupt. I&#8217;ve thought of some things but have no concrete plans at this point.</li>
<li>The page table/index table method of storing data is very simplistic. There is surely a more appropriate method buried in some ACM or IEEE publication somewhere, even in the limits of fixed memory size. As it stands my method blends some of the disadvantages of 1960&#8242;s-era memory allocators with paged memory allocators, without all of the benefits.</li>
<li>Assuming defragmentation remains required, the defragmenter could probably be made faster as well.</li>
<li>It is not at this point possible to resize a cache once it has been created. There&#8217;s no reason in theory that it can&#8217;t be done, it&#8217;s just not implemented. (Note that implementing this is more complicated than simply changing a size flag in the cache&#8230;)</li>
<li>The cache could possibly be made more concurrent with lock-free algorithms or finer-grained locking. This is not something I&#8217;d like to touch until I have a way to verify correctness of the result, however.</li>
<li>Finally, it possible that someone has done this way better and that I simply missed it, in which event we should look at whether we should just adopt that library as a dependency and make KSharedDataCache a wrapper around it.</li>
<li>Should we remove old KPixmapCache caches after starting up a shiny new 4.5 desktop?</li>
</ul>
<p>So, this concludes my series on implementing a shared cache. I&#8217;ve got to get working on other efficiency improvements, new kdesvn-build releases, classes, etc. It&#8217;s been fun writing though!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/05/20/implementing-a-shared-cache-part-4/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Implementing a shared cache: Part 3</title>
		<link>http://www.purinchu.net/wp/2010/05/08/implementing-a-shared-cache-part-3/</link>
		<comments>http://www.purinchu.net/wp/2010/05/08/implementing-a-shared-cache-part-3/#comments</comments>
		<pubDate>Sun, 09 May 2010 02:20:03 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[Implementing KSharedDataCache]]></category>
		<category><![CDATA[KDE]]></category>
		<category><![CDATA[collateral evictions]]></category>
		<category><![CDATA[kshareddatacache]]></category>
		<category><![CDATA[pointers]]></category>
		<category><![CDATA[pthreads]]></category>
		<category><![CDATA[ramped entry aging]]></category>
		<category><![CDATA[series]]></category>
		<category><![CDATA[spinlocks]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=623</guid>
		<description><![CDATA[So it has been a few days since Part 2, where I promised I&#8217;d talk about some issues that go with using pointers in shared memory, initial cache setup, and my arbitrary methods I use to handle various scenarios. Pointing to things in shared memory First I&#8217;ll talk about pointers. Essentially all you need to [...]]]></description>
			<content:encoded><![CDATA[<p>So it has been a few days since <a href="/wp/2010/04/30/implementing-a-shared-cache-part-2/">Part 2</a>, where I promised I&#8217;d talk about some issues that go with  using pointers in shared memory, initial cache setup, and my arbitrary methods I use to handle various scenarios.</p>
<h3>Pointing to things in shared memory</h3>
<p>First I&#8217;ll talk about pointers. Essentially all you need to know about them is that a pointer holds a memory address, namely the address of the data you&#8217;re really interested in.</p>
<p>Now, every process in modern operating systems has its own &#8220;address space&#8221;, which defines where things are in memory. So, memory addresses in process 1 have no relation to addresses used in process 2, or any other process.</p>
<p>What this means for shared memory algorithms is that you cannot use normal pointers, since they rely on pointing to a specific spot in a process&#8217;s address space. See below for an example:</p>
<p><center><img src="/images/kshareddatacache-pointers.png" width="641" height="469" alt="Demonstration of address space for three processes shared a cache"/></center></p>
<p>Three KSharedDataCache-using processes are running, and let&#8217;s say that kcalc was the first to create that cache, so the pointers are created from the perspective of kcalc&#8217;s address space. If KSharedDataCache used normal pointers to point to the data in the cache (from the cache header) then things would fail to work right in kate where we point into the middle of the data. The case of krunner is even worse, as we point into the krunner process&#8217;s private data!</p>
<p>The solution is not too hard. The memory map call that creates the connection will tell you where the connection starts. So instead of saying &#8220;the data is at address 0&#215;400000&#8243;, use pointers that say &#8220;the data is 1024 bytes past the start&#8221;. These are called offsets. For example, the pthread library that is standard in POSIX could use this type of technique to implement &#8220;process-shared&#8221; mutexes (mutexes are by default merely thread-shared).</p>
<h3>Initial cache setup</h3>
<p>Taking that first step in creating a cache is hard. Once the cache is setup we can rely on having some means of locking, entry tables that are setup, and other niceties. Creating that in the face of race conditions is another matter though.</p>
<p>My decision to use pthreads for the mutex made this part harder than it could have been otherwise, as the mutex has to be stored with the cache. But you can&#8217;t use the mutex without initializing it first (remember that pthread mutexes default to not being process-shared). If two processes try to create a non-existing cache at the same time, they would both try to initialize the mutex, and the process that initializes the mutex the second time could potentially cause logic errors in the first process.</p>
<p>So, I went with a simpler solution for this rare case: A <a href="http://en.wikipedia.org/wiki/Spinlock">spinlock</a>, using Qt&#8217;s built-in atomic operations. It is not quite a pure spinlock because there are a couple of possibilities (numbered as they are in the code):</p>
<p>Case 0 is that the cache has just been created, without ever having been attached to. (0 because that is the default value for an initially empty file that has just been mapped into shared memory).</p>
<p>Case 1 is that there is a process which has noticed that the cache is not initialized, and is initializing it (in other words, it atomically switched the 0 flag to 1). This is a locking condition: No other process will attempt to initialize the cache. But the cache is not initialized yet!</p>
<p>Case 2 occurs when the cache has been finally initialized, and can have the standard locks and methods used. To access a cache that is in this condition you must use the cache mutex.</p>
<p>I don&#8217;t use a spinlock all the time because my implementation does not do any magical non-locking algorithms, and therefore some operations might take some significant time with the lock held. Using a mutex allows threads that are waiting to sleep and save CPU and battery power, which would not work with a spinlock.</p>
<h3>Cache handling</h3>
<p>Any cache needs a method of deciding when to remove old entries. This is especially vital for hash-based caches that use probing, like KSharedDataCache, where allowing the cache to reach maximum capacity will make it very slow since probing becomes both more common, and more lengthy. I use several techniques to try to get rid of old entries. I make no promises as to their effectiveness, but I felt it was better to try something than to do nothing. The techniques are:</p>
<ul>
<li>Limited Quadratic Probing: One standard method of handling items that hash to the same location in a hash table is to use &#8220;probing&#8221;, where the insertion/find algorithms look at the next entry, then the next, and so on until a free spot is found. Obviously this takes longer, <em>especially</em> if the hash function tends to make entries cluster anyways. In the case of KSharedDataCache it&#8217;s perfectly acceptable to simply give up after a certain number of attempts, and I quite willingly do so (but see the next technique). On the other hand if you can avoid colliding you don&#8217;t have to worry about finding empty spots, so to that end I use the &#8220;<a href="http://www.isthe.com/chongo/tech/comp/fnv/index.html">FNV</a>&#8221; hash function by Fowler, Yo, and Noll.</li>
<li>Ramped Entry Aging&trade;: The basic idea is that as the amount of entries in the cache goes up, it becomes more likely that the insertion method will, instead of probing past a colliding entry, artificially decrease its use count, and kick it out if it becomes unused. There are competing effects here: There&#8217;s no point having a cache if you&#8217;re not going to employ it, so this aging never happens if the cache is lightly loaded. On the other hand entries that get added to the cache and only ever used once could cause collisions for weeks afterwards in the long-lived scenarios I envision so it is important to make entries justify their use. So as the cache load increases, there is a higher and higher chance of entries being evicted if unused. I simply divide the use count in half, so an entry can be quickly evicted even if used a million times a month ago.</li>
<li>Collateral Evictions&reg;: In the event that the first two options don&#8217;t work, then some entries have to be kicked out to make room for new ones. This process is called eviction. In my Collateral Evictions plan, anytime we kick entries out, we kick <em>even more</em> entries out on top of that (I chose twice as many, for no particular reason). The idea is that if we&#8217;re running of out space we&#8217;ll probably have to kick someone else out on the very next insert call anyways, so since it&#8217;s a time-consuming operation we might as well make it effective. The exact entries that get kicked out are decided based on the developer-configurable eviction policy.</li>
</ul>
<p>Next time I&#8217;ll talk about defragmentation, porting KIconLoader, and any other random things I can think up. I hope it hasn&#8217;t been deathly boring so far!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/05/08/implementing-a-shared-cache-part-3/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>If trunk is broken for you&#8230;</title>
		<link>http://www.purinchu.net/wp/2010/05/06/if-trunk-is-broken-for-you/</link>
		<comments>http://www.purinchu.net/wp/2010/05/06/if-trunk-is-broken-for-you/#comments</comments>
		<pubDate>Thu, 06 May 2010 23:38:59 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[KDE]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[kiconloader]]></category>
		<category><![CDATA[kshareddatacache]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=620</guid>
		<description><![CDATA[It might be because I completed the port of KIconLoader to use the KSharedDataCache class I recently introduced. Everything should be fine if it&#8217;s not broken yet though, as Plasma was ported over a few days ago. The cache files are stored under $(kde4-config &#8211;path cache)/*.kcache (Normally this is /var/tmp/kdecache-$USER/*.kcache). You shouldn&#8217;t need the old [...]]]></description>
			<content:encoded><![CDATA[<p>It might be because I completed the port of KIconLoader to use the <a href="http://api.kde.org/4.x-api/kdelibs-apidocs/kdecore/html/classKSharedDataCache.html">KSharedDataCache</a> class I recently introduced.</p>
<p>Everything should be fine if it&#8217;s not broken yet though, as Plasma was ported over a few days ago.</p>
<p>The cache files are stored under $(kde4-config &#8211;path cache)/*.kcache (Normally this is /var/tmp/kdecache-$USER/*.kcache). You shouldn&#8217;t need the old plasma_theme*.index or plasma_theme*.data files anymore, and you can delete those if you&#8217;d like.</p>
<p>I&#8217;m not done with the series I had going on making KSharedDataCache, I just haven&#8217;t had a lot of time recently. There&#8217;s 1 or 2 more parts I&#8217;d like to add, stay tuned&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/05/06/if-trunk-is-broken-for-you/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Today I learned&#8230;</title>
		<link>http://www.purinchu.net/wp/2010/05/02/today-i-learned/</link>
		<comments>http://www.purinchu.net/wp/2010/05/02/today-i-learned/#comments</comments>
		<pubDate>Mon, 03 May 2010 02:06:13 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[Computing Troubles]]></category>
		<category><![CDATA[KDE]]></category>
		<category><![CDATA[qpixmap]]></category>
		<category><![CDATA[todayilearned]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=615</guid>
		<description><![CDATA[&#8230; that the ~QX11PixmapData(): QPixmap objects must be destroyed before the QApplication object, otherwise the native pixmap object will be leaked. warning most KDE applications display when exiting is actually false. The X server will cleanup any opened resources, including pixmaps, automatically when the client exits. This is much like how the kernel automatically closes [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230; that the <quote><tt>~QX11PixmapData(): QPixmap objects must be destroyed before the QApplication object, otherwise the native pixmap object will be leaked.</tt></quote> warning most KDE applications display when exiting is actually false.</p>
<p>The X server will cleanup any opened resources, including pixmaps, automatically when the client exits. This is much like how the kernel automatically closes files and memory allocations when an application exits.</p>
<p>(The QPixmaps in question are the ones cached by KIconLoader as best as I can tell. They <em>are</em> cleaned up, just not before QApplication&#8217;s destructor runs.)</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/05/02/today-i-learned/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Implementing a shared cache: Part 2</title>
		<link>http://www.purinchu.net/wp/2010/04/30/implementing-a-shared-cache-part-2/</link>
		<comments>http://www.purinchu.net/wp/2010/04/30/implementing-a-shared-cache-part-2/#comments</comments>
		<pubDate>Sat, 01 May 2010 00:54:29 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[Implementing KSharedDataCache]]></category>
		<category><![CDATA[KDE]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[kpixmapcache]]></category>
		<category><![CDATA[kshareddatacache]]></category>
		<category><![CDATA[mmap]]></category>
		<category><![CDATA[series]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=611</guid>
		<description><![CDATA[In my last post, I gave some background on what a shared-memory cache is, and how KDE already uses one (KPixmapCache) to save memory and make the desktop more efficient. I also noted how the current implementation leaves some things to be desired, and hinted at a new implementation I was working on. In this [...]]]></description>
			<content:encoded><![CDATA[<p>In my last post, I <a href="/wp/2010/04/25/implementing-a-shared-cache-part-1/">gave some background</a> on what a shared-memory cache is, and how KDE already uses one (<code>KPixmapCache</code>) to save memory and make the desktop more efficient. I also noted how the current implementation leaves some things to be desired, and hinted at a new implementation I was working on.</p>
<p>In this second part, I&#8217;ll discuss some of the basic design principles of the new class, which I called <code>KSharedDataCache</code>.</p>
<h3>Why a new class?</h3>
<p>If you didn&#8217;t read Part 1, you may be wondering why I don&#8217;t just fix the current implementation, KPixmapCache, instead of writing new code. It&#8217;s a good question, but the short story is that due to the public API used by KPixmapCache, it is non-trivial (to say the least :) to improve KPixmapCache and take some necessary steps to improve its performance. The penalty of getting it wrong is pretty severe as well, as there have been probably hundreds of reported crash bugs already due to KPixmapCache.</p>
<p>So, someone on IRC gave me the idea that, why don&#8217;t I just make my improvements in a different class, like a KPixmapCache2 and move the majority of the current users of KPixmapCache to use that instead? It sounded like a good option to me, so that&#8217;s what I started on, eventually settling on a generic cache layer under a slightly more specialized image-handling cache.</p>
<h3>KSharedDataCache</h3>
<p>KSharedDataCache is a class that manages a cache, keyed by QString values, and holding QByteArrays for generality. The cache is held in shared memory, which is accessed across multiple processes based on the cache name (which is converted internally to a file name).</p>
<p>The central data structure is the cache itself. Everything that is needed to be able to insert items, find items, and otherwise manage the cache is kept in the same memory segment, instead of being split into two different files like in KPixmapCache. A very ugly drawing of the layout would look like this:</p>
<p><center><img src="/images/kshareddatacache-layout.png" width="585" height="124" alt="Block diagram of the KSharedDataCache memory layout"/></center></p>
<p>Starting from the left, we have the header for the shared cache itself. This contains several important pieces of data, including the cache size, the page size (which is adjustable), the number of free pages, and the mutex which protects against concurrent access to the shared data.</p>
<p>One note about the mutex, is that it is used instead of KLockFile. It requires support for process-shared POSIX thread primitives (which is required for XSI-conformant systems, but was not present in Linux/glibc until NPTL IIRC). As long as your system tells the truth about whether it supports process-shared primitives KSharedDataCache will still work (even if it can&#8217;t use shared memory).</p>
<p>After the cache header, the entry index table is located (starting from the first byte meeting alignment criteria to avoid crashing on non-x86 systems&#8230; although I have none to test!). This table is a fixed-size table, based on the total cache size and page size. Entries are placed into the entry table based on the hash of the entry key, and each entry contains information such as the item size, hash code, use count, time of last access, and location of its data.</p>
<p>Collisions are possible with any hash table. The standard answer to handling collisions is to use a method called &#8220;chaining&#8221; to just make a list of entries which share the same hash code. Unfortunately dynamic memory allocation is much more involved when you&#8217;re dealing with a fixed-size block of shared memory, so currently quadratic probing is used to try to seek out other, hopefully empty candidates. Since this is just a cache, the probing is only continued for a small number of attempts.</p>
<p>Following the entry table is the page table, which simply records the entry currently using every page in memory. It is possible to compress the page table by using a bit vector, and making a full page table only when needed (currently only during defragmenting) but I didn&#8217;t have time to implement that.</p>
<p>Finally, the rest of the shared memory is devoted to a paged memory allocation system (this is probably the most suboptimal part of my current implementation, but at least it can be fixed later this time ;). Every entry is stored in this data area, with the key that is used followed by the actual QByteArray data.</p>
<p>Resolving an access for an item with a key of &#8220;juk_128x128.png&#8221; would work something like this:</p>
<ol>
<li>Lock the cache. If unable to acquire the lock, assume the cache is corrupt, unlink it on disk, and create it all over again.</li>
<li>Convert the key to a byte array using the UTF-8 encoding, then determine the hash code.</li>
<li>Use the hash code to find the appropriate entry index. Compare the hash code to the candidate entry&#8217;s hash code, and if they don&#8217;t match, use quadratic probing to find another candidate. Give up if the entry is not found within several attempts.</li>
<li>If the hash codes match, search the matching data area to determine the saved key value, and make sure the keys also match. If they don&#8217;t match then go back to before, using quadratic probing to find a match.</li>
<li>If the keys did match, we found our entry. Update the entry&#8217;s use count and last access time, and then copy the data out of the page or pages to return to the caller. Since this all happened in shared memory this should be much much faster than loading it from disk (assuming of course that the operating system hasn&#8217;t paged out the shared memory to disk in the meantime).</li>
</ol>
<p>You might have noticed that I possibly unlink the cache with reckless abandon in step 1. I actually do this in many more places, the idea being that a corrupt cache can lead to bugs that are very hard for the end user to diagnose and correct, and by definition a cache can be expected to drop entries <em>at any time</em>. The only danger would be tampering with a cache that other processes are currently using in shared memory. By unlinking (and <em>only</em> unlinking) the cache, the other processes can continue to use the inode that used to be associated with the file, and the kernel will finish the cleanup when the other processes exit.</p>
<p>Of course I&#8217;m up past a thousand words now, so I&#8217;ll continue in Part 3, where I&#8217;ll discuss how pointers work in shared memory, how initial cache setup is performed, and my attempts at handling cache pressure, defragmentation, etc.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/04/30/implementing-a-shared-cache-part-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Implementing a shared cache: Part 1</title>
		<link>http://www.purinchu.net/wp/2010/04/25/implementing-a-shared-cache-part-1/</link>
		<comments>http://www.purinchu.net/wp/2010/04/25/implementing-a-shared-cache-part-1/#comments</comments>
		<pubDate>Mon, 26 Apr 2010 02:45:00 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[Implementing KSharedDataCache]]></category>
		<category><![CDATA[KDE]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[cairo]]></category>
		<category><![CDATA[kpixmapcache]]></category>
		<category><![CDATA[kshareddatacache]]></category>
		<category><![CDATA[mmap]]></category>
		<category><![CDATA[series]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=606</guid>
		<description><![CDATA[So awhile ago I mentioned that I was trying to add a new shared-memory cache for the next version of the KDE platform. It&#8217;s almost done now, and has been submitted for review (both old-skool on kde-core-devel, and all Web 2.0-style on our review board). Given the number of things I had to think about [...]]]></description>
			<content:encoded><![CDATA[<p>So awhile ago I mentioned that I was trying to add a new shared-memory cache for the next version of the KDE platform. It&#8217;s almost done now, and has been submitted for review (both old-skool on kde-core-devel, and all Web 2.0-style on our <a href="http://reviewboard.kde.org/r/3809/">review board</a>).</p>
<p>Given the number of things I had to think about while implementing it (and I promise you that even still it&#8217;s not fully as thought-out as it could be), I decided that I could probably make a half-decent, if very technical series of posts about the implementation process.</p>
<p>I&#8217;ve got a basic outline set out, but without further ado, I&#8217;ll go over in this post what exactly a shared-memory cache is, why KDE has one now, and why I&#8217;m trying to make a different one.</p>
<h3>Why a shared-memory cache?</h3>
<p>Most of the programmer types are already familiar with the idea of a cache: You have some input that isn&#8217;t particularly helpful right now, you have a function to turn that non-helpful input into something you can use, but that function takes awhile to run. So, you save the output of that function (the <em>value</em>) once, somewhere where you can refer to it later (by a <em>key</em>) if you need it. The idea is to trade some extra memory usage for reduced time requirements. Caching is used everywhere, in your CPU, in your Web browser, the operating system, and more.</p>
<p>Now, the shared-memory part allows this cache to be shared between running processes (if you don&#8217;t know what a process is, just think of it as an instance of a running program. Each different instance, even of the same program, would be a different process). The operating system normally does a very good job of making sure that different processes can&#8217;t interfere with each other, but there are times when it makes sense to open a couple of gateways between them to let them share the burden. In KDE&#8217;s case, many of the icons used by a standard KDE application will be used unchanged by other KDE programs, so it makes sense for us to cache generated icons for use by other KDE program. We could simply write the icons out to disk where other programs could read them, but putting them into shared memory allows for the near-immediate transfer of that data without any disk I/O.</p>
<p>I&#8217;d like to find examples of current shared-memory caches (besides our current KPixmapCache), but the only ones I can find are the fully distributed type like memcached. Cairo has a cache for glyphs, but that seems to be done per-process. GTK+ has a cache which is designed to be read in directly using mmap(2), but not necessarily to be accessed via shared memory. Let me know if you find any though!</p>
<p>So again, in our case we use a shared-memory cache in large part to handle icon loading and Plasma themes (both potentially heavy users of SVG icons). This gives us two speedups: 1) We don&#8217;t always have to re-generate a pixmap from the source data (a very big speedup when the source is an SVG), and 2) If one process generates a pixmap, every other KDE process can get access to the results nearly instantly.</p>
<h3>What KDE currently does</h3>
<p>My interest in shared-memory caching came about from looking into some bugs reported against our current cache, KPixmapCache, which was developed in conjunction with the lead-up to KDE 4.0 to allow the new Plasma subsystem and the existing icon subsystem to use the fancy SVG graphics without taking forever.</p>
<p>In addition, KPixmapCache had a feature where not only could it cache the image data (the 0&#8242;s and 1&#8242;s that make up the image itself), but also the resulting QPixmap handle to the image as it exists in &#8220;the graphics memory&#8221; (I&#8217;ll gloss over the distinction for now, it will be important in a future part).</p>
<p>KPixmapCache is implemented by hosting two different files in a known location, one ending in .index and the other ending in .data. Respectively these files hold the index metadata needed for the cache to work, and the actual image data.</p>
<p>Anytime you talk about shared resources, you also need to think about how to protect access to those shared resources to keep everything consistent. KPixmapCache uses the trusty KLockFile to protect against concurrent access (this has the benefit of being safe if the partition is mounted on NFS, although I think the reason is more because that&#8217;s what already existed in kdelibs).</p>
<p>From there, KPixmapCache uses a sorted binary tree (sorted by the hash code) to manage the index, and treats the .data file as a simple block of memory. Every time a new item is entered into the cache, a new chunk of free space is allocated from the .data file, even if there already exists empty space. Likewise, if a new index entry is required to insert an item, it is always added at the end of the index (with one exception, when overwriting an existing index entry due to a hash collision). I said the index was sorted earlier, but that might seem incompatible with always adding new entries at the end. What the implementer did to solve this problem is hold pointers to the actual children and parent in each index item, that way a virtual hierarchy could be arranged. The binary tree is never re-arranged (like in AVL trees or red-black trees), so the initial root node is always the root node. The overall structure looks like this figure:</p>
<p><center><img src="/images/kpixmapcache-layout.png" width="339" height="399" alt="Schematic of KPixmapCache layout"/></center></p>
<p>One disadvantage to this architecture is that it is difficult and inefficient to delete entries that should be expired out of the cache. Properly removing an entry would require possibly having to move entries in the data file in order to minimize fragmentation. This alone wouldn&#8217;t be a large deal (I end up having to do the same thing in KSharedDataCache), but updating the .index file is even harder, since it requires updating information for both parent and children (although again, not impossible by any means). Avoiding fragmentation in the index would require either moving nodes around in the index file (possibly recursively), or having to scan for the first free node when adding items. None of these are big problems, but it does make the implementation more annoying.</p>
<p>KPixmapCache worked around all of this by punting the problem: No entries ever got removed until the cache filled up. At this point the entries would be ranked by whatever the expiration policy in effect was (i.e. least recently used preferred, newest preferred, etc.), a new (smaller) cache would be constructed holding the most-desired entries, and the old cache would be deleted. Although infrequent, this could possibly take a not-insignificant amount of time when it did happen.</p>
<h3>So why a new implementation?</h3>
<p>Probably the one thing that led to me starting from a different architecture however, was the interface to KPixmapCache: It is designed to be subclassed, and to allow subclasses access to both the index and individual data items through a QDataStream (see KIconCache for an example usage). Doing this meant the internal code had to use a QIODevice to interface to the data and index, and so what ends up happening is that even though KPixmapCache tries to place all of the data in shared memory, it always ends up accessing it like it was a disk file anyways (even though a memory-to-QIODevice adapter is used).</p>
<p>Having to support subclassing (in the public API no less) makes changing many of the implementation details a journey fraught with hazard, and it&#8217;s bad enough that any little problem in KPixmapCache seemingly guarantees a crash. Since KPixmapCache is used in very core desktop platform code (Plasma and KIconLoader) I knew I wanted to go a different direction.</p>
<p>So, I started work on a &#8220;KIconCache&#8221;. However all the work I was doing was hardly specific to icons, and when I&#8217;d heard of a developer that was abusing KPixmapCache to hold non-image-data somehow, I decided to make a generic shared-memory cache, KSharedDataCache. Next post I&#8217;ll try to explain the direction I decided to take with KSharedDataCache.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/04/25/implementing-a-shared-cache-part-1/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>API Docs</title>
		<link>http://www.purinchu.net/wp/2010/04/08/api-docs/</link>
		<comments>http://www.purinchu.net/wp/2010/04/08/api-docs/#comments</comments>
		<pubDate>Fri, 09 Apr 2010 00:03:23 +0000</pubDate>
		<dc:creator>mpyne</dc:creator>
				<category><![CDATA[KDE]]></category>
		<category><![CDATA[apidox]]></category>

		<guid isPermaLink="false">http://www.purinchu.net/wp/?p=603</guid>
		<description><![CDATA[I&#8217;ve added a mirror of the kdelibs API documentation, with some exceptions: No class inheritance diagrams. No annotated source code. Perhaps worst, no classmapper.php, so no search. Hopefully it&#8217;s still useful for somebody until EBN and api.kde.org are restored.]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve added <a href="/kdelibs-apidocs/">a mirror</a> of the kdelibs API documentation, with some exceptions:</p>
<ul>
<li>No class inheritance diagrams.</li>
<li>No annotated source code.</li>
<li>Perhaps worst, no classmapper.php, so no search.</li>
</ul>
<p>Hopefully it&#8217;s still useful for somebody until EBN and api.kde.org are restored.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.purinchu.net/wp/2010/04/08/api-docs/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
<!-- WP Super Cache is installed but broken. The path to wp-cache-phase1.php in wp-content/advanced-cache.php must be fixed! -->