Author: axeld Date: 2011-02-20 16:42:46 +0100 (Sun, 20 Feb 2011) New Revision: 40583 Changeset: http://dev.haiku-os.org/changeset/40583 Modified: haiku/trunk/src/apps/showimage/ImageCache.cpp Log: * Be a bit more generous about the maximum cache size; it filled up pretty quickly with high resolution pictures. * Changed the way how it's determined to reject pre-caching an image; this should work better in practice, and should also fix a potential problem that sometimes the cache wouldn't accept anything beyond the current picture as observed by stippi. * Add optional debug output. Modified: haiku/trunk/src/apps/showimage/ImageCache.cpp =================================================================== --- haiku/trunk/src/apps/showimage/ImageCache.cpp 2011-02-20 15:39:25 UTC (rev 40582) +++ haiku/trunk/src/apps/showimage/ImageCache.cpp 2011-02-20 15:42:46 UTC (rev 40583) @@ -1,5 +1,5 @@ /* - * Copyright 2010, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx + * Copyright 2010-2011, Axel Dörfler, axeld@xxxxxxxxxxxxxxxxx * Distributed under the terms of the MIT License. */ @@ -21,6 +21,15 @@ #include "ShowImageConstants.h" +//#define TRACE_CACHE +#undef TRACE +#ifdef TRACE_CACHE +# define TRACE(x, ...) printf(x, __VA_ARGS__) +#else +# define TRACE(x, ...) ; +#endif + + struct QueueEntry { entry_ref ref; int32 page; @@ -60,9 +69,14 @@ system_info info; get_system_info(&info); - fMaxThreadCount = (info.cpu_count + 1) / 2; - fMaxBytes = info.max_pages * B_PAGE_SIZE / 8; + fMaxThreadCount = info.cpu_count - 1; + if (fMaxThreadCount < 1) + fMaxThreadCount = 1; + fMaxBytes = info.max_pages * B_PAGE_SIZE / 5; fMaxEntries = 10; + TRACE("max thread count: %" B_PRId32 ", max bytes: %" B_PRIu64 + ", max entries: %" B_PRIuSIZE "\n", + fMaxThreadCount, fMaxBytes, fMaxEntries); } @@ -83,6 +97,7 @@ CacheEntry* entry = find->second; // Requeue cache entry to the end of the by-age list + TRACE("requeue trace entry %s\n", ref.name); fCacheEntriesByAge.Remove(entry); fCacheEntriesByAge.Add(entry); @@ -96,13 +111,17 @@ if (findQueue == fQueueMap.end()) { if (target == NULL - && ((fCacheMap.size() < 5 && fBytes > fMaxBytes * 1 / 2) + && ((fCacheMap.size() < 4 && fCacheMap.size() > 1 + && fBytes + fBytes / fCacheMap.size() > fMaxBytes) || (fMaxThreadCount == 1 && fQueueMap.size() > 1))) { // Don't accept any further precaching if we're low on memory // anyway, or if there is already a busy queue. + TRACE("ignore entry %s\n", ref.name); return B_NO_MEMORY; } + TRACE("add to queue %s\n", ref.name); + // Push new entry to the queue entry = new(std::nothrow) QueueEntry(); if (entry == NULL) @@ -127,8 +146,10 @@ fQueueMap.insert(std::make_pair( std::make_pair(entry->ref, entry->page), entry)); fQueue.push_front(entry); - } else + } else { entry = findQueue->second; + TRACE("got entry %s from cache\n", entry->ref.name); + } if (target != NULL) { // Attach target as listener @@ -143,6 +164,7 @@ ImageCache::_QueueWorkerThread(void* _self) { ImageCache* self = (ImageCache*)_self; + TRACE("%ld: start worker thread\n", find_thread(NULL)); // get next queue entry while (true) { @@ -153,12 +175,11 @@ } QueueEntry* entry = *self->fQueue.begin(); + TRACE("%ld: got entry %s from queue.\n", find_thread(NULL), + entry->ref.name); self->fQueue.pop_front(); self->fLocker.Unlock(); - if (entry == NULL) - break; - CacheEntry* cacheEntry = NULL; entry->status = self->_RetrieveImage(entry, &cacheEntry); @@ -171,6 +192,7 @@ } atomic_add(&self->fThreadCount, -1); + TRACE("%ld: end worker thread\n", find_thread(NULL)); return B_OK; } @@ -258,12 +280,17 @@ fBytes += bitmap->BitsLength(); + TRACE("%ld: cached entry %s from queue (%" B_PRIu64 " bytes.\n", + find_thread(NULL), entry->ref.name, fBytes); + while (fBytes > fMaxBytes || fCacheMap.size() > fMaxEntries) { if (fCacheMap.size() <= 2) break; // Remove the oldest entry entry = fCacheEntriesByAge.RemoveHead(); + TRACE("%ld: purge cached entry %s from queue.\n", find_thread(NULL), + entry->ref.name); fBytes -= entry->bitmap->BitsLength(); fCacheMap.erase(std::make_pair(entry->ref, entry->page));