mirror of
https://git.proxmox.com/git/mirror_zfs
synced 2025-05-02 15:59:50 +00:00
Add taskq contention splat test
Add a test designed to generate contention on the taskq spinlock by using a large number of threads (100) to perform a large number (131072) of trivial work items from a single queue. This simulates conditions that may occur with the zio free taskq when a 1TB file is removed from a ZFS filesystem, for example. This test should always pass. Its purpose is to provide a benchmark to easily measure the effectiveness of taskq optimizations using statistics from the kernel lock profiler. Signed-off-by: Brian Behlendorf <behlendorf1@llnl.gov> Issue #32
This commit is contained in:
parent
966e5200d3
commit
cf5d23fa1e
@ -57,9 +57,14 @@
|
|||||||
#define SPLAT_TASKQ_TEST7_NAME "recurse"
|
#define SPLAT_TASKQ_TEST7_NAME "recurse"
|
||||||
#define SPLAT_TASKQ_TEST7_DESC "Single task queue, recursive dispatch"
|
#define SPLAT_TASKQ_TEST7_DESC "Single task queue, recursive dispatch"
|
||||||
|
|
||||||
|
#define SPLAT_TASKQ_TEST8_ID 0x0208
|
||||||
|
#define SPLAT_TASKQ_TEST8_NAME "contention"
|
||||||
|
#define SPLAT_TASKQ_TEST8_DESC "1 queue, 100 threads, 131072 tasks"
|
||||||
|
|
||||||
#define SPLAT_TASKQ_ORDER_MAX 8
|
#define SPLAT_TASKQ_ORDER_MAX 8
|
||||||
#define SPLAT_TASKQ_DEPTH_MAX 16
|
#define SPLAT_TASKQ_DEPTH_MAX 16
|
||||||
|
|
||||||
|
|
||||||
typedef struct splat_taskq_arg {
|
typedef struct splat_taskq_arg {
|
||||||
int flag;
|
int flag;
|
||||||
int id;
|
int id;
|
||||||
@ -990,6 +995,113 @@ splat_taskq_test7(struct file *file, void *arg)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create a taskq with 100 threads and dispatch a huge number of trivial
|
||||||
|
* tasks to generate contention on tq->tq_lock. This test should always
|
||||||
|
* pass. The purpose is to provide a benchmark for measuring the
|
||||||
|
* effectiveness of taskq optimizations.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
splat_taskq_test8_func(void *arg)
|
||||||
|
{
|
||||||
|
splat_taskq_arg_t *tq_arg = (splat_taskq_arg_t *)arg;
|
||||||
|
ASSERT(tq_arg);
|
||||||
|
|
||||||
|
atomic_inc(&tq_arg->count);
|
||||||
|
}
|
||||||
|
|
||||||
|
#define TEST8_NUM_TASKS 0x20000
|
||||||
|
#define TEST8_THREADS_PER_TASKQ 100
|
||||||
|
|
||||||
|
static int
|
||||||
|
splat_taskq_test8_common(struct file *file, void *arg, int minalloc,
|
||||||
|
int maxalloc)
|
||||||
|
{
|
||||||
|
taskq_t *tq;
|
||||||
|
taskqid_t id;
|
||||||
|
splat_taskq_arg_t tq_arg;
|
||||||
|
taskq_ent_t **tqes;
|
||||||
|
int i, j, rc = 0;
|
||||||
|
|
||||||
|
tqes = vmalloc(sizeof(*tqes) * TEST8_NUM_TASKS);
|
||||||
|
if (tqes == NULL)
|
||||||
|
return -ENOMEM;
|
||||||
|
memset(tqes, 0, sizeof(*tqes) * TEST8_NUM_TASKS);
|
||||||
|
|
||||||
|
splat_vprint(file, SPLAT_TASKQ_TEST8_NAME,
|
||||||
|
"Taskq '%s' creating (%d/%d/%d)\n",
|
||||||
|
SPLAT_TASKQ_TEST8_NAME,
|
||||||
|
minalloc, maxalloc, TEST8_NUM_TASKS);
|
||||||
|
if ((tq = taskq_create(SPLAT_TASKQ_TEST8_NAME, TEST8_THREADS_PER_TASKQ,
|
||||||
|
maxclsyspri, minalloc, maxalloc,
|
||||||
|
TASKQ_PREPOPULATE)) == NULL) {
|
||||||
|
splat_vprint(file, SPLAT_TASKQ_TEST8_NAME,
|
||||||
|
"Taskq '%s' create failed\n",
|
||||||
|
SPLAT_TASKQ_TEST8_NAME);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out_free;
|
||||||
|
}
|
||||||
|
|
||||||
|
tq_arg.file = file;
|
||||||
|
tq_arg.name = SPLAT_TASKQ_TEST8_NAME;
|
||||||
|
|
||||||
|
atomic_set(&tq_arg.count, 0);
|
||||||
|
for (i = 0; i < TEST8_NUM_TASKS; i++) {
|
||||||
|
tqes[i] = kmalloc(sizeof(taskq_ent_t), GFP_KERNEL);
|
||||||
|
if (tqes[i] == NULL) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
taskq_init_ent(tqes[i]);
|
||||||
|
|
||||||
|
taskq_dispatch_ent(tq, splat_taskq_test8_func,
|
||||||
|
&tq_arg, TQ_SLEEP, tqes[i]);
|
||||||
|
|
||||||
|
id = tqes[i]->tqent_id;
|
||||||
|
|
||||||
|
if (id == 0) {
|
||||||
|
splat_vprint(file, SPLAT_TASKQ_TEST8_NAME,
|
||||||
|
"Taskq '%s' function '%s' dispatch "
|
||||||
|
"%d failed\n", tq_arg.name,
|
||||||
|
sym2str(splat_taskq_test8_func), i);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
splat_vprint(file, SPLAT_TASKQ_TEST8_NAME, "Taskq '%s' "
|
||||||
|
"waiting for %d dispatches\n", tq_arg.name,
|
||||||
|
TEST8_NUM_TASKS);
|
||||||
|
taskq_wait(tq);
|
||||||
|
splat_vprint(file, SPLAT_TASKQ_TEST8_NAME, "Taskq '%s' "
|
||||||
|
"%d/%d dispatches finished\n", tq_arg.name,
|
||||||
|
atomic_read(&tq_arg.count), TEST8_NUM_TASKS);
|
||||||
|
|
||||||
|
if (atomic_read(&tq_arg.count) != TEST8_NUM_TASKS)
|
||||||
|
rc = -ERANGE;
|
||||||
|
|
||||||
|
out:
|
||||||
|
splat_vprint(file, SPLAT_TASKQ_TEST8_NAME, "Taskq '%s' destroying\n",
|
||||||
|
tq_arg.name);
|
||||||
|
taskq_destroy(tq);
|
||||||
|
out_free:
|
||||||
|
for (j = 0; j < TEST8_NUM_TASKS && tqes[j] != NULL; j++)
|
||||||
|
kfree(tqes[j]);
|
||||||
|
vfree(tqes);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
splat_taskq_test8(struct file *file, void *arg)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = splat_taskq_test8_common(file, arg, 1, 100);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
splat_subsystem_t *
|
splat_subsystem_t *
|
||||||
splat_taskq_init(void)
|
splat_taskq_init(void)
|
||||||
{
|
{
|
||||||
@ -1021,6 +1133,8 @@ splat_taskq_init(void)
|
|||||||
SPLAT_TASKQ_TEST6_ID, splat_taskq_test6);
|
SPLAT_TASKQ_TEST6_ID, splat_taskq_test6);
|
||||||
SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST7_NAME, SPLAT_TASKQ_TEST7_DESC,
|
SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST7_NAME, SPLAT_TASKQ_TEST7_DESC,
|
||||||
SPLAT_TASKQ_TEST7_ID, splat_taskq_test7);
|
SPLAT_TASKQ_TEST7_ID, splat_taskq_test7);
|
||||||
|
SPLAT_TEST_INIT(sub, SPLAT_TASKQ_TEST8_NAME, SPLAT_TASKQ_TEST8_DESC,
|
||||||
|
SPLAT_TASKQ_TEST8_ID, splat_taskq_test8);
|
||||||
|
|
||||||
return sub;
|
return sub;
|
||||||
}
|
}
|
||||||
@ -1029,6 +1143,7 @@ void
|
|||||||
splat_taskq_fini(splat_subsystem_t *sub)
|
splat_taskq_fini(splat_subsystem_t *sub)
|
||||||
{
|
{
|
||||||
ASSERT(sub);
|
ASSERT(sub);
|
||||||
|
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST8_ID);
|
||||||
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST7_ID);
|
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST7_ID);
|
||||||
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST6_ID);
|
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST6_ID);
|
||||||
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST5_ID);
|
SPLAT_TEST_FINI(sub, SPLAT_TASKQ_TEST5_ID);
|
||||||
|
Loading…
Reference in New Issue
Block a user