* 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:
@@ -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.
|
* Distributed under the terms of the MIT License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -21,6 +21,15 @@
|
|||||||
#include "ShowImageConstants.h"
|
#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 {
|
struct QueueEntry {
|
||||||
entry_ref ref;
|
entry_ref ref;
|
||||||
int32 page;
|
int32 page;
|
||||||
@@ -60,9 +69,14 @@ ImageCache::ImageCache()
|
|||||||
system_info info;
|
system_info info;
|
||||||
get_system_info(&info);
|
get_system_info(&info);
|
||||||
|
|
||||||
fMaxThreadCount = (info.cpu_count + 1) / 2;
|
fMaxThreadCount = info.cpu_count - 1;
|
||||||
fMaxBytes = info.max_pages * B_PAGE_SIZE / 8;
|
if (fMaxThreadCount < 1)
|
||||||
|
fMaxThreadCount = 1;
|
||||||
|
fMaxBytes = info.max_pages * B_PAGE_SIZE / 5;
|
||||||
fMaxEntries = 10;
|
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;
|
CacheEntry* entry = find->second;
|
||||||
|
|
||||||
// Requeue cache entry to the end of the by-age list
|
// Requeue cache entry to the end of the by-age list
|
||||||
|
TRACE("requeue trace entry %s\n", ref.name);
|
||||||
fCacheEntriesByAge.Remove(entry);
|
fCacheEntriesByAge.Remove(entry);
|
||||||
fCacheEntriesByAge.Add(entry);
|
fCacheEntriesByAge.Add(entry);
|
||||||
|
|
||||||
@@ -96,13 +111,17 @@ ImageCache::RetrieveImage(const entry_ref& ref, int32 page,
|
|||||||
|
|
||||||
if (findQueue == fQueueMap.end()) {
|
if (findQueue == fQueueMap.end()) {
|
||||||
if (target == NULL
|
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))) {
|
|| (fMaxThreadCount == 1 && fQueueMap.size() > 1))) {
|
||||||
// Don't accept any further precaching if we're low on memory
|
// Don't accept any further precaching if we're low on memory
|
||||||
// anyway, or if there is already a busy queue.
|
// anyway, or if there is already a busy queue.
|
||||||
|
TRACE("ignore entry %s\n", ref.name);
|
||||||
return B_NO_MEMORY;
|
return B_NO_MEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TRACE("add to queue %s\n", ref.name);
|
||||||
|
|
||||||
// Push new entry to the queue
|
// Push new entry to the queue
|
||||||
entry = new(std::nothrow) QueueEntry();
|
entry = new(std::nothrow) QueueEntry();
|
||||||
if (entry == NULL)
|
if (entry == NULL)
|
||||||
@@ -127,8 +146,10 @@ ImageCache::RetrieveImage(const entry_ref& ref, int32 page,
|
|||||||
fQueueMap.insert(std::make_pair(
|
fQueueMap.insert(std::make_pair(
|
||||||
std::make_pair(entry->ref, entry->page), entry));
|
std::make_pair(entry->ref, entry->page), entry));
|
||||||
fQueue.push_front(entry);
|
fQueue.push_front(entry);
|
||||||
} else
|
} else {
|
||||||
entry = findQueue->second;
|
entry = findQueue->second;
|
||||||
|
TRACE("got entry %s from cache\n", entry->ref.name);
|
||||||
|
}
|
||||||
|
|
||||||
if (target != NULL) {
|
if (target != NULL) {
|
||||||
// Attach target as listener
|
// Attach target as listener
|
||||||
@@ -143,6 +164,7 @@ ImageCache::RetrieveImage(const entry_ref& ref, int32 page,
|
|||||||
ImageCache::_QueueWorkerThread(void* _self)
|
ImageCache::_QueueWorkerThread(void* _self)
|
||||||
{
|
{
|
||||||
ImageCache* self = (ImageCache*)_self;
|
ImageCache* self = (ImageCache*)_self;
|
||||||
|
TRACE("%ld: start worker thread\n", find_thread(NULL));
|
||||||
|
|
||||||
// get next queue entry
|
// get next queue entry
|
||||||
while (true) {
|
while (true) {
|
||||||
@@ -153,12 +175,11 @@ ImageCache::_QueueWorkerThread(void* _self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QueueEntry* entry = *self->fQueue.begin();
|
QueueEntry* entry = *self->fQueue.begin();
|
||||||
|
TRACE("%ld: got entry %s from queue.\n", find_thread(NULL),
|
||||||
|
entry->ref.name);
|
||||||
self->fQueue.pop_front();
|
self->fQueue.pop_front();
|
||||||
self->fLocker.Unlock();
|
self->fLocker.Unlock();
|
||||||
|
|
||||||
if (entry == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
CacheEntry* cacheEntry = NULL;
|
CacheEntry* cacheEntry = NULL;
|
||||||
entry->status = self->_RetrieveImage(entry, &cacheEntry);
|
entry->status = self->_RetrieveImage(entry, &cacheEntry);
|
||||||
|
|
||||||
@@ -171,6 +192,7 @@ ImageCache::_QueueWorkerThread(void* _self)
|
|||||||
}
|
}
|
||||||
|
|
||||||
atomic_add(&self->fThreadCount, -1);
|
atomic_add(&self->fThreadCount, -1);
|
||||||
|
TRACE("%ld: end worker thread\n", find_thread(NULL));
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,12 +280,17 @@ ImageCache::_RetrieveImage(QueueEntry* queueEntry, CacheEntry** _entry)
|
|||||||
|
|
||||||
fBytes += bitmap->BitsLength();
|
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) {
|
while (fBytes > fMaxBytes || fCacheMap.size() > fMaxEntries) {
|
||||||
if (fCacheMap.size() <= 2)
|
if (fCacheMap.size() <= 2)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// Remove the oldest entry
|
// Remove the oldest entry
|
||||||
entry = fCacheEntriesByAge.RemoveHead();
|
entry = fCacheEntriesByAge.RemoveHead();
|
||||||
|
TRACE("%ld: purge cached entry %s from queue.\n", find_thread(NULL),
|
||||||
|
entry->ref.name);
|
||||||
fBytes -= entry->bitmap->BitsLength();
|
fBytes -= entry->bitmap->BitsLength();
|
||||||
fCacheMap.erase(std::make_pair(entry->ref, entry->page));
|
fCacheMap.erase(std::make_pair(entry->ref, entry->page));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user