[prev in list] [next in list] [prev in thread] [next in thread] 

List:       kde-commits
Subject:    koffice/krita/core/tiles
From:       Bart Coppens <kde () bartcoppens ! be>
Date:       2005-08-09 18:25:14
Message-ID: 1123611914.337571.15290.nullmailer () svn ! kde ! org
[Download RAW message or body]

SVN commit 444323 by coppens:

Some changes to the tile manager:
 * Now each pixelsize has its own freelist
 * Some changes to the way swappable tiles are handled
A quick performance test indicates that the filling on RGBA8 is about 3 times faster \
than before (not really noticeable since it was already quite fast, but still a nice \
improvement)

 M  +58 -36    kis_tilemanager.cc  
 M  +15 -4     kis_tilemanager.h  


--- trunk/koffice/krita/core/tiles/kis_tilemanager.cc #444322:444323
@@ -52,24 +52,35 @@
 	m_maxInMem = config.maxTilesInMem();
 	m_swappiness = config.swappiness();
 
+	m_tileSize = KisTile::WIDTH * KisTile::HEIGHT;
+	m_freeLists.reserve(8);
+
 	counter = 0;
 }
 
 KisTileManager::~KisTileManager() {
 	kdDebug(DBG_AREA_TILES) << "Destructing TileManager: unmapping everything" << endl;
 
-	if (!m_freeList.empty()) { // Let's see if there is an item in the freelist that \
                fits
-		FreeList::iterator it = m_freeList.begin();
-		FreeList::iterator end = m_freeList.end();
+	if (!m_freeLists.empty()) { // See if there are any nonempty freelists
+		FreeListList::iterator listsIt = m_freeLists.begin();
+		FreeListList::iterator listsEnd = m_freeLists.end();
+		
+		while(listsIt != listsEnd) {
+			if ( ! (*listsIt).empty() ) {
+				FreeList::iterator it = (*listsIt).begin();
+				FreeList::iterator end = (*listsIt).end();
 
-		while (it != end) {
-			// munmap it
-			munmap((*it) -> pointer, (*it) -> size);
-			delete *it;
-			++it;
+				while (it != end) {
+					// munmap it
+					munmap((*it) -> pointer, (*it) -> size);
+					delete *it;
+					++it;
+				}
+				(*listsIt).clear();
+			}
+			++listsIt;
 		}
-		
-		m_freeList.clear();
+		m_freeLists.clear();
 	}
 
 	kdDebug(DBG_AREA_TILES) << "Destructing TileManager: deleting file" << endl;
@@ -92,9 +103,11 @@
 	info -> filePos = -1;
 	info -> size = tile -> WIDTH * tile -> HEIGHT * tile -> m_pixelSize;
 	info -> fsize = 0; // the size in the file
+	info -> validNode = true;
 
 	m_tileMap[tile] = info;
 	m_swappableList.push_back(info);
+	info -> node = -- m_swappableList.end();
 
 	m_currentInMem++;
 	m_bytesTotal += info -> size;
@@ -117,7 +130,10 @@
 		freeInfo -> pointer = tile -> m_data;
 		freeInfo -> filePos = info -> filePos;
 		freeInfo -> size = info -> fsize;
-		m_freeList.push_back(freeInfo);
+		int pixelSize = (info -> size / m_tileSize);
+		if (m_freeLists.capacity() <= pixelSize)
+			m_freeLists.resize(pixelSize);
+		m_freeLists[pixelSize].push_back(freeInfo);
 
 		madvise(info -> tile -> m_data, info -> fsize, MADV_DONTNEED);
 
@@ -129,7 +145,10 @@
 		m_currentInMem--;
 	}
 
-	m_swappableList.remove(info);
+	if (info -> validNode) {
+		m_swappableList.erase(info -> node);
+		info -> validNode = false;
+	}
 
 	m_bytesTotal -= info -> size;
 
@@ -142,7 +161,10 @@
 
 void KisTileManager::ensureTileLoaded(KisTile* tile) {
 	TileInfo* info = m_tileMap[tile];
-	m_swappableList.remove(info);
+	if (info -> validNode) {
+		m_swappableList.erase(info -> node);
+		info -> validNode = false;
+	}
 
 	if (!info -> inMem) {
 		fromSwap(info);
@@ -150,7 +172,11 @@
 }
 
 void KisTileManager::maySwapTile(KisTile* tile) {
-	m_swappableList.push_back(m_tileMap[tile]);
+	TileInfo* info = m_tileMap[tile];
+	m_swappableList.push_back(info);
+	info -> validNode = true;
+	info -> node = -- m_swappableList.end();
+	
 	doSwapping();
 }
 
@@ -175,28 +201,17 @@
 		// ### check return values of mmap functions!
 		KisTile *tile = info -> tile;
 		Q_UINT8* data = 0;
+		int pixelSize = (info -> size / m_tileSize);
+		if (m_freeLists.capacity() > pixelSize) {
+			if (!m_freeLists[pixelSize].empty()) {
+				// found one
+				FreeList::iterator it = m_freeLists[pixelSize].begin();
+				data = (*it) -> pointer;
+				info -> filePos = (*it) -> filePos;
+				info -> fsize = (*it) -> size;
 
-		if (!m_freeList.empty()) { // Let's see if there is an item in the freelist that \
                fits
-			FreeList::iterator it = m_freeList.begin();
-			FreeList::iterator end = m_freeList.end();
-
-			while (it != end) {
-				if ( (*it) -> size >= info -> size ) {
-					// found one
-					data = (*it) -> pointer;
-					info -> filePos = (*it) -> filePos;
-					info -> fsize = (*it) -> size;
-
-					delete *it;
-					m_freeList.erase(it);
-
-					kdDebug(DBG_AREA_TILES) << "found in freelist\n";
-
-					break;
-				} else {
-					kdDebug(DBG_AREA_TILES) << (*it) -> size << " < " << info -> size << endl;
-				}
-				++it;
+				delete *it;
+				m_freeLists[pixelSize].erase(it);
 			}
 		}
 
@@ -245,6 +260,7 @@
 
 	for (Q_INT32 i = 0; i < count; i++) {
 		toSwap(m_swappableList.front());
+		m_swappableList.front() -> validNode = false;
 		m_swappableList.pop_front();
 	}
 #endif
@@ -254,7 +270,13 @@
 	kdDebug(DBG_AREA_TILES) << m_bytesInMem << " out of " << m_bytesTotal << " bytes in \
memory\n";  kdDebug(DBG_AREA_TILES) << m_currentInMem << " out of " << \
m_tileMap.size() << " tiles in memory\n";  kdDebug(DBG_AREA_TILES) << \
                m_swappableList.size() << " elements in the swapable list\n";
-	kdDebug(DBG_AREA_TILES) << m_freeList.size() << " elements in the freelist\n";
+	kdDebug(DBG_AREA_TILES) << "Freelists information\n";
+	for (int i = 0; i < m_freeLists.capacity(); i++) {
+		if ( ! m_freeLists[i].empty() ) {
+			kdDebug(DBG_AREA_TILES) << m_freeLists[i].size()
+					<< " elements in the freelist for pixelsize " << i << "\n";
+		}
+	}
 	kdDebug(DBG_AREA_TILES) << endl;
 }
 
--- trunk/koffice/krita/core/tiles/kis_tilemanager.h #444322:444323
@@ -27,7 +27,15 @@
 class KisTiledDataManager;
 
 /**
- * Provides a way to store tiles on disk to a swap file, to reduce memory usage.
+ * This class keeps has the intention to make certain tile-related operations faster \
or more + * efficient. It does this by keeping lots of info on KisTiles, and manages \
the way they are + * created, used, etc.
+ * It mainly does the following more visible things
+ *  * provide a way to store tiles on disk to a swap file, to reduce memory usage
+ *  * keep a list of previously swapped (but now unused) tiles, to reuse these when \
we want + *    to swap new tiles.
+ *  * tries to preallocate and recycle some tiles to make future allocations faster
+ *    (not done yet)
  */
 class KisTileManager  {
 public:
@@ -40,7 +48,7 @@
 	void ensureTileLoaded(KisTile* tile);
 	void maySwapTile(KisTile* tile);
 
-public slots:
+public:
 	void configChanged();
 
 private:
@@ -53,18 +61,21 @@
 	KTempFile m_tempFile;
 	int m_fileSize;
 
-	typedef struct { KisTile *tile; bool inMem; int filePos; int size; int fsize; } \
TileInfo; +	struct TileInfo { KisTile *tile; bool inMem; int filePos; int size; int \
fsize; +		bool validNode; QValueList<TileInfo*>::iterator node; };
 	typedef struct { Q_UINT8 *pointer; int filePos; int size; } FreeInfo;
 	typedef QMap<KisTile*, TileInfo*> TileMap;
 	typedef QValueList<TileInfo*> TileList;
 	typedef QValueList<FreeInfo*> FreeList;
+	typedef QValueVector<FreeList> FreeListList;
 
 	TileMap m_tileMap;
 	TileList m_swappableList;
-	FreeList m_freeList;
+	FreeListList m_freeLists;
 	Q_INT32 m_maxInMem;
 	Q_INT32 m_currentInMem;
 	Q_INT32 m_swappiness;
+	Q_INT32 m_tileSize; // size of a tile if it used 1 byte per pixel
 	unsigned long m_bytesInMem;
 	unsigned long m_bytesTotal;
 


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic