From 5af13da19d6957cf659ad0b863bb8dfc1706380a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Mon, 21 Jan 2008 20:34:06 +0000 Subject: [PATCH] * The block cache now sorts the blocks before synchronizing a transaction. * This should speed up writing a transaction considerably. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@23694 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/cache/block_cache.cpp | 43 +++++++++++++++++++++++-- 1 file changed, 41 insertions(+), 2 deletions(-) diff --git a/src/system/kernel/cache/block_cache.cpp b/src/system/kernel/cache/block_cache.cpp index 0d3dd706c6..baef02b68c 100644 --- a/src/system/kernel/cache/block_cache.cpp +++ b/src/system/kernel/cache/block_cache.cpp @@ -275,6 +275,20 @@ lookup_transaction(block_cache *cache, int32 id) // #pragma mark - cached_block +int +compare_blocks(const void *_blockA, const void *_blockB) +{ + cached_block *blockA = (cached_block *)_blockA; + cached_block *blockB = (cached_block *)_blockB; + + off_t diff = blockA->block_number - blockB->block_number; + if (diff > 0) + return 1; + + return diff < 0 ? -1 : 0; +} + + /* static */ int cached_block::Compare(void *_cacheEntry, const void *_block) @@ -1145,8 +1159,33 @@ cache_sync_transaction(void *_cache, int32 id) // write back all of their remaining dirty blocks T(Action("sync", cache, transaction)); while (transaction->num_blocks > 0) { - status = write_cached_block(cache, transaction->blocks.Head(), - false); + // sort blocks to speed up writing them back + // TODO: ideally, this should be handled by the I/O scheduler + block_list::Iterator iterator = transaction->blocks.GetIterator(); + uint32 maxCount = transaction->num_blocks; + cached_block *buffer[16]; + cached_block **blocks = (cached_block **)malloc(maxCount + * sizeof(void *)); + if (blocks == NULL) { + maxCount = 16; + blocks = buffer; + } + + uint32 count = 0; + for (; count < maxCount && iterator.HasNext(); count++) { + blocks[count] = iterator.Next(); + } + qsort(blocks, count, sizeof(void *), &compare_blocks); + + for (uint32 i = 0; i < count; i++) { + status = write_cached_block(cache, blocks[i], false); + if (status != B_OK) + break; + } + + if (blocks != buffer) + free(blocks); + if (status != B_OK) return status; }