summaryrefslogtreecommitdiffstats
path: root/src/server/image.c
diff options
context:
space:
mode:
authorSimon Rettberg2015-12-17 15:58:06 +0100
committerSimon Rettberg2015-12-17 15:58:06 +0100
commit1460b746b6f5482ce1c56a30af232e824e316e56 (patch)
tree12d170ec73fe3eba66db779a38be36e86052be66 /src/server/image.c
parent[SERVER] image_markComplete now handles locking so we remove() unlocked (diff)
downloaddnbd3-1460b746b6f5482ce1c56a30af232e824e316e56.tar.gz
dnbd3-1460b746b6f5482ce1c56a30af232e824e316e56.tar.xz
dnbd3-1460b746b6f5482ce1c56a30af232e824e316e56.zip
[SERVER] Performance: Optimized some functions (gprof)
A run with gprof revealed that background replication is a huge CPU hog. The block selection was very slow and has been improved a lot. Minor improvements were made to other functions that scan the cache map of an image and are thus relatively slow.
Diffstat (limited to 'src/server/image.c')
-rw-r--r--src/server/image.c25
1 files changed, 18 insertions, 7 deletions
diff --git a/src/server/image.c b/src/server/image.c
index 6d486c4..da19b6a 100644
--- a/src/server/image.c
+++ b/src/server/image.c
@@ -50,7 +50,7 @@ static imagecache remoteCloneCache[CACHELEN];
static void image_remove(dnbd3_image_t *image);
static dnbd3_image_t* image_free(dnbd3_image_t *image);
-static bool image_isHashBlockComplete(uint8_t * const cacheMap, const uint64_t block, const uint64_t fileSize);
+static bool image_isHashBlockComplete(const uint8_t * const cacheMap, const uint64_t block, const uint64_t fileSize);
static bool image_load_all_internal(char *base, char *path);
static bool image_load(char *base, char *path, int withUplink);
static bool image_clone(int sock, char *name, uint16_t revision, uint64_t imageSize);
@@ -551,17 +551,21 @@ static dnbd3_image_t* image_free(dnbd3_image_t *image)
return NULL ;
}
-static bool image_isHashBlockComplete(uint8_t * const cacheMap, const uint64_t block, const uint64_t realFilesize)
+static bool image_isHashBlockComplete(const uint8_t * const cacheMap, const uint64_t block, const uint64_t realFilesize)
{
if ( cacheMap == NULL ) return true;
const uint64_t end = (block + 1) * HASH_BLOCK_SIZE;
if ( end <= realFilesize ) {
- for (uint64_t mapPos = block * HASH_BLOCK_SIZE; mapPos < end; mapPos += (DNBD3_BLOCK_SIZE * 8)) {
- if ( cacheMap[mapPos / (DNBD3_BLOCK_SIZE * 8)] != 0xff ) {
+ // Trivial case: block in question is not the last block (well, or image size is multiple of HASH_BLOCK_SIZE)
+ const int startCacheIndex = (int)( ( block * HASH_BLOCK_SIZE ) / ( DNBD3_BLOCK_SIZE * 8 ) );
+ const int endCacheIndex = startCacheIndex + ( HASH_BLOCK_SIZE / ( DNBD3_BLOCK_SIZE * 8 ) );
+ for ( int i = startCacheIndex; i < endCacheIndex; ++i ) {
+ if ( cacheMap[i] != 0xff ) {
return false;
}
}
} else {
+ // Special case: Checking last block, which is smaller than HASH_BLOCK_SIZE
for (uint64_t mapPos = block * HASH_BLOCK_SIZE; mapPos < realFilesize; mapPos += DNBD3_BLOCK_SIZE ) {
const int map_y = mapPos >> 15;
const int map_x = (mapPos >> 12) & 7; // mod 8
@@ -1409,10 +1413,15 @@ json_t* image_getListAsJson()
* Returns: 0-100
* DOES NOT LOCK, so make sure to do so before calling
*/
-int image_getCompletenessEstimate(const dnbd3_image_t * const image)
+int image_getCompletenessEstimate(dnbd3_image_t * const image)
{
assert( image != NULL );
if ( image->cache_map == NULL ) return image->working ? 100 : 0;
+ const time_t now = time( NULL );
+ if ( now < image->nextCompletenessEstimate ) {
+ // Since this operation is relatively expensive, we cache the result for a while
+ return image->completenessEstimate;
+ }
int i;
int percent = 0;
const int len = IMGSIZE_TO_MAPBYTES( image->virtualFilesize );
@@ -1420,11 +1429,13 @@ int image_getCompletenessEstimate(const dnbd3_image_t * const image)
for ( i = 0; i < len; ++i ) {
if ( image->cache_map[i] == 0xff ) {
percent += 100;
- } else if ( image->cache_map[i] > 0 ) {
+ } else if ( image->cache_map[i] != 0 ) {
percent += 50;
}
}
- return percent / len;
+ image->completenessEstimate = percent / len;
+ image->nextCompletenessEstimate = now + 10 + rand() % 30;
+ return image->completenessEstimate;
}
/**