mirror of
https://git.proxmox.com/git/mirror_zfs.git
synced 2026-05-24 19:28:53 +03:00
OpenZFS 8199 - multi-threaded dmu_object_alloc()
dmu_object_alloc() is single-threaded, so when multiple threads are creating files in a single filesystem, they spend a lot of time waiting for the os_obj_lock. To improve performance of multi-threaded file creation, we must make dmu_object_alloc() typically not grab any filesystem-wide locks. The solution is to have a "next object to allocate" for each CPU. Each of these "next object"s is in a different block of the dnode object, so that concurrent allocation holds dnodes in different dbufs. When a thread's "next object" reaches the end of a chunk of objects (by default 4 blocks worth -- 128 dnodes), it will be reset to the per-objset os_obj_next, which will be increased by a chunk of objects (128). Only when manipulating the os_obj_next will we need to grab the os_obj_lock. This decreases lock contention dramatically, because each thread only needs to grab the os_obj_lock briefly, once per 128 allocations. This results in a 70% performance improvement to multi-threaded object creation (where each thread is creating objects in its own directory), from 67,000/sec to 115,000/sec, with 8 CPUs. Work sponsored by Intel Corp. Authored by: Matthew Ahrens <mahrens@delphix.com> Reviewed-by: Ned Bass <bass6@llnl.gov> Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov> Ported-by: Matthew Ahrens <mahrens@delphix.com> Signed-off-by: Matthew Ahrens <mahrens@delphix.com> OpenZFS-issue: https://www.illumos.org/issues/8199 OpenZFS-commit: https://github.com/openzfs/openzfs/pull/374 Closes #4703 Closes #6117
This commit is contained in:
committed by
Brian Behlendorf
parent
1b7c1e5ce9
commit
dbeb879699
@@ -547,6 +547,9 @@ dmu_objset_open_impl(spa_t *spa, dsl_dataset_t *ds, blkptr_t *bp,
|
||||
mutex_init(&os->os_userused_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
mutex_init(&os->os_obj_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
mutex_init(&os->os_user_ptr_lock, NULL, MUTEX_DEFAULT, NULL);
|
||||
os->os_obj_next_percpu_len = boot_ncpus;
|
||||
os->os_obj_next_percpu = kmem_zalloc(os->os_obj_next_percpu_len *
|
||||
sizeof (os->os_obj_next_percpu[0]), KM_SLEEP);
|
||||
|
||||
dnode_special_open(os, &os->os_phys->os_meta_dnode,
|
||||
DMU_META_DNODE_OBJECT, &os->os_meta_dnode);
|
||||
@@ -842,6 +845,9 @@ dmu_objset_evict_done(objset_t *os)
|
||||
rw_enter(&os_lock, RW_READER);
|
||||
rw_exit(&os_lock);
|
||||
|
||||
kmem_free(os->os_obj_next_percpu,
|
||||
os->os_obj_next_percpu_len * sizeof (os->os_obj_next_percpu[0]));
|
||||
|
||||
mutex_destroy(&os->os_lock);
|
||||
mutex_destroy(&os->os_userused_lock);
|
||||
mutex_destroy(&os->os_obj_lock);
|
||||
|
||||
Reference in New Issue
Block a user