Optimized writing of zeroes to files. Instead of allocating a small buffer
on the fly, clearing and writing it each time, we now use an iovec with 32 identical entries pointing to a clear page that we prepare once at initialization. This speeds up clear_image in low memory situations dramatically. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@35304 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
parent
cef3da793a
commit
64a9bd15c8
|
@ -106,7 +106,12 @@ static void add_to_iovec(iovec* vecs, uint32 &index, uint32 max, addr_t address,
|
||||||
|
|
||||||
|
|
||||||
static struct cache_module_info* sCacheModule;
|
static struct cache_module_info* sCacheModule;
|
||||||
static const uint8 kZeroBuffer[4096] = {};
|
|
||||||
|
|
||||||
|
static const uint32 kZeroVecCount = 32;
|
||||||
|
static const size_t kZeroVecSize = kZeroVecCount * B_PAGE_SIZE;
|
||||||
|
static addr_t sZeroPage; // physical address
|
||||||
|
static iovec sZeroVecs[kZeroVecCount];
|
||||||
|
|
||||||
|
|
||||||
// #pragma mark -
|
// #pragma mark -
|
||||||
|
@ -624,22 +629,6 @@ write_to_file(file_cache_ref* ref, void* cookie, off_t offset, int32 pageOffset,
|
||||||
addr_t buffer, size_t bufferSize, bool useBuffer, size_t lastReservedPages,
|
addr_t buffer, size_t bufferSize, bool useBuffer, size_t lastReservedPages,
|
||||||
size_t reservePages)
|
size_t reservePages)
|
||||||
{
|
{
|
||||||
size_t chunkSize = 0;
|
|
||||||
if (!useBuffer) {
|
|
||||||
// we need to allocate a zero buffer
|
|
||||||
// TODO: use smaller buffers if this fails
|
|
||||||
chunkSize = min_c(bufferSize, B_PAGE_SIZE);
|
|
||||||
buffer = (addr_t)malloc(chunkSize);
|
|
||||||
if (buffer == 0)
|
|
||||||
return B_NO_MEMORY;
|
|
||||||
|
|
||||||
memset((void*)buffer, 0, chunkSize);
|
|
||||||
}
|
|
||||||
|
|
||||||
iovec vec;
|
|
||||||
vec.iov_base = (void*)buffer;
|
|
||||||
vec.iov_len = bufferSize;
|
|
||||||
|
|
||||||
push_access(ref, offset, bufferSize, true);
|
push_access(ref, offset, bufferSize, true);
|
||||||
ref->cache->Unlock();
|
ref->cache->Unlock();
|
||||||
vm_page_unreserve_pages(lastReservedPages);
|
vm_page_unreserve_pages(lastReservedPages);
|
||||||
|
@ -648,20 +637,21 @@ write_to_file(file_cache_ref* ref, void* cookie, off_t offset, int32 pageOffset,
|
||||||
|
|
||||||
if (!useBuffer) {
|
if (!useBuffer) {
|
||||||
while (bufferSize > 0) {
|
while (bufferSize > 0) {
|
||||||
if (bufferSize < chunkSize)
|
size_t written = min_c(bufferSize, kZeroVecSize);
|
||||||
chunkSize = bufferSize;
|
|
||||||
|
|
||||||
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
|
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
|
||||||
&vec, 1, 0, &chunkSize);
|
sZeroVecs, kZeroVecCount, B_PHYSICAL_IO_REQUEST, &written);
|
||||||
if (status < B_OK)
|
if (status != B_OK)
|
||||||
break;
|
return status;
|
||||||
|
if (written == 0)
|
||||||
|
return B_ERROR;
|
||||||
|
|
||||||
bufferSize -= chunkSize;
|
bufferSize -= written;
|
||||||
pageOffset += chunkSize;
|
pageOffset += written;
|
||||||
}
|
}
|
||||||
|
|
||||||
free((void*)buffer);
|
|
||||||
} else {
|
} else {
|
||||||
|
iovec vec;
|
||||||
|
vec.iov_base = (void*)buffer;
|
||||||
|
vec.iov_len = bufferSize;
|
||||||
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
|
status = vfs_write_pages(ref->vnode, cookie, offset + pageOffset,
|
||||||
&vec, 1, 0, &bufferSize);
|
&vec, 1, 0, &bufferSize);
|
||||||
}
|
}
|
||||||
|
@ -1090,6 +1080,18 @@ file_cache_init_post_boot_device(void)
|
||||||
extern "C" status_t
|
extern "C" status_t
|
||||||
file_cache_init(void)
|
file_cache_init(void)
|
||||||
{
|
{
|
||||||
|
// allocate a clean page we can use for writing zeroes
|
||||||
|
vm_page_reserve_pages(1, VM_PRIORITY_SYSTEM);
|
||||||
|
vm_page* page = vm_page_allocate_page(PAGE_STATE_CLEAR);
|
||||||
|
vm_page_unreserve_pages(1);
|
||||||
|
|
||||||
|
sZeroPage = (addr_t)page->physical_page_number * B_PAGE_SIZE;
|
||||||
|
|
||||||
|
for (uint32 i = 0; i < kZeroVecCount; i++) {
|
||||||
|
sZeroVecs[i].iov_base = (void*)sZeroPage;
|
||||||
|
sZeroVecs[i].iov_len = B_PAGE_SIZE;
|
||||||
|
}
|
||||||
|
|
||||||
register_generic_syscall(CACHE_SYSCALLS, file_cache_control, 1, 0);
|
register_generic_syscall(CACHE_SYSCALLS, file_cache_control, 1, 0);
|
||||||
return B_OK;
|
return B_OK;
|
||||||
}
|
}
|
||||||
|
@ -1296,16 +1298,12 @@ file_cache_write(void* _cacheRef, void* cookie, off_t offset,
|
||||||
}
|
}
|
||||||
|
|
||||||
// NULL buffer -- use a dummy buffer to write zeroes
|
// NULL buffer -- use a dummy buffer to write zeroes
|
||||||
// TODO: This is not particularly efficient!
|
|
||||||
iovec vec;
|
|
||||||
vec.iov_base = (void*)kZeroBuffer;
|
|
||||||
vec.iov_len = sizeof(kZeroBuffer);
|
|
||||||
size_t size = *_size;
|
size_t size = *_size;
|
||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
size_t toWrite = min_c(size, vec.iov_len);
|
size_t toWrite = min_c(size, kZeroVecSize);
|
||||||
size_t written = toWrite;
|
size_t written = toWrite;
|
||||||
status_t error = vfs_write_pages(ref->vnode, cookie, offset, &vec,
|
status_t error = vfs_write_pages(ref->vnode, cookie, offset,
|
||||||
1, 0, &written);
|
sZeroVecs, kZeroVecCount, B_PHYSICAL_IO_REQUEST, &written);
|
||||||
if (error != B_OK)
|
if (error != B_OK)
|
||||||
return error;
|
return error;
|
||||||
if (written == 0)
|
if (written == 0)
|
||||||
|
|
Loading…
Reference in New Issue