* 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.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@40583 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2011-02-20 15:42:46 +00:00
parent ebd792d8c1
commit f38b8016a8
+35 -8
View File
@@ -1,5 +1,5 @@
/*
* Copyright 2010, Axel Dörfler, [email protected].
* Copyright 2010-2011, Axel Dörfler, [email protected].
* 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 @@ ImageCache::ImageCache()
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 @@ ImageCache::RetrieveImage(const entry_ref& ref, int32 page,
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 @@ ImageCache::RetrieveImage(const entry_ref& ref, int32 page,
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 @@ ImageCache::RetrieveImage(const entry_ref& ref, int32 page,
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::RetrieveImage(const entry_ref& ref, int32 page,
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 @@ ImageCache::_QueueWorkerThread(void* _self)
}
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 @@ ImageCache::_QueueWorkerThread(void* _self)
}
atomic_add(&self->fThreadCount, -1);
TRACE("%ld: end worker thread\n", find_thread(NULL));
return B_OK;
}
@@ -258,12 +280,17 @@ ImageCache::_RetrieveImage(QueueEntry* queueEntry, CacheEntry** _entry)
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));