/** ******************************************************************************** ** \brief ** query the io stats from the ark *******************************************************************************/ void get_stats(ARK *ark, uint32_t *ops, uint32_t *ios) { uint64_t ops64 = 0; uint64_t ios64 = 0; (void)ark_stats(ark, &ops64, &ios64); *ops = (uint32_t)ops64; *ios = (uint32_t)ios64; }
/** ******************************************************************************* * \brief ******************************************************************************/ void kv_async_job_perf(uint32_t jobs, uint32_t klen, uint32_t vlen,uint32_t len) { long int wr_us = 0; long int rd_us = 0; long int mil = 1000000; float wr_s = 0; float rd_s = 0; float wr_mb = 0; float rd_mb = 0; uint64_t mb64_1 = (uint64_t)KV_1M; uint64_t wr_bytes = 0; uint64_t rd_bytes = 0; uint64_t ops = 0; uint64_t post_ops = 0; uint64_t ios = 0; uint64_t post_ios = 0; float wr_ops = 0; float wr_ios = 0; float rd_ops = 0; float rd_ios = 0; uint32_t secs = 5; uint32_t job = 0; struct timeval stop, start; kv_async_init_ctxt(0, secs); for (job=0; job<jobs; job++) { kv_async_init_job(KV_ASYNC_CB_SGD|KV_ASYNC_CB_WRITE_PERF, ASYNC_SINGLE_CONTEXT, job, klen+job, vlen, len); } pCTs->flags |= KV_ASYNC_CT_PERF; /* do writes */ (void)ark_stats(kv_async_get_ark(ASYNC_SINGLE_CONTEXT), &ops, &ios); KV_TRC(pFT, "PERF wr: ops:%"PRIu64" ios:%"PRIu64"", ops, ios); gettimeofday(&start, NULL); kv_async_run_jobs(); /* run write jobs */ KV_TRC(pFT, "writes done"); gettimeofday(&stop, NULL); wr_us += (stop.tv_sec*mil + stop.tv_usec) - (start.tv_sec*mil + start.tv_usec); (void)ark_stats(kv_async_get_ark(ASYNC_SINGLE_CONTEXT),&post_ops,&post_ios); KV_TRC(pFT, "PERF wr: ops:%"PRIu64" ios:%"PRIu64"", post_ops, post_ios); wr_ops += post_ops - ops; wr_ios += post_ios - ios; /* calc bytes written */ for (job=0; job<jobs; job++) { wr_bytes += (klen+vlen+job)*len*(pCTs->pCBs+job)->perf_loops; } /* do reads */ for (job=0; job<jobs; job++) { if ((pCTs->pCBs+job)->perf_loops) { (pCTs->pCBs+job)->perf_loops = 0; (pCTs->pCBs+job)->flags = KV_ASYNC_CB_GET | KV_ASYNC_CB_QUEUED | KV_ASYNC_CB_READ_PERF; } } pCTs->flags |= KV_ASYNC_CT_RUNNING; (void)ark_stats(kv_async_get_ark(0), &ops, &ios); KV_TRC(pFT, "PERF rd: ops:%"PRIu64" ios:%"PRIu64"", ops, ios); gettimeofday(&start, NULL); kv_async_run_jobs(); /* run read jobs */ gettimeofday(&stop, NULL); KV_TRC(pFT, "reads done"); rd_us += (stop.tv_sec*mil + stop.tv_usec) - (start.tv_sec*mil + start.tv_usec); (void)ark_stats(kv_async_get_ark(0), &post_ops, &post_ios); KV_TRC(pFT, "PERF rd: ops:%"PRIu64" ios:%"PRIu64"", post_ops, post_ios); rd_ops += post_ops - ops; rd_ios += post_ios - ios; ASSERT_EQ(0, ark_delete(pCTs->ark)); /* calc bytes read */ for (job=0; job<jobs; job++) { rd_bytes += vlen*len*(pCTs->pCBs+job)->perf_loops; kv_db_destroy((pCTs->pCBs+job)->db, (pCTs->pCBs+job)->len); if ((pCTs->pCBs+job)->gvalue) free((pCTs->pCBs+job)->gvalue); } /* calc and print results */ wr_s = (float)((float)wr_us/(float)mil); wr_mb = (float)((double)wr_bytes / (double)mb64_1); rd_s = (float)((float)rd_us/(float)mil); rd_mb = (float)((double)rd_bytes / (double)mb64_1); printf("ASYNC %dx%dx%d writes: %.3d jobs %2.3f mb in %.1f secs at ", klen, vlen, len, jobs, wr_mb, wr_s); printf("%2.3f mbps, %6.0f op/s, %.0f io/s\n", wr_mb/wr_s, wr_ops/wr_s, wr_ios/wr_s); printf("ASYNC %dx%dx%d reads: %.3d jobs %2.3f mb in %.1f secs at ", klen, vlen, len, jobs, rd_mb, rd_s); printf("%2.3f mbps, %6.0f op/s, %.0f io/s\n", rd_mb/rd_s, rd_ops/rd_s, rd_ios/rd_s); }
/** ******************************************************************************* * \brief ******************************************************************************/ void kv_async_run_jobs(void) { async_CB_t *pCB = NULL; uint32_t ctxt_running = 0; uint32_t jobs_running = 0; uint32_t i = 0; uint32_t next = 0; uint32_t elapse = 0; uint32_t inject = 0; uint32_t secs = 0; uint32_t log_interval = 600; uint64_t ops = 0; uint64_t ios = 0; uint32_t tops = 0; uint32_t tios = 0; uint32_t perf = 0; KV_TRC(pFT, "ASYNC START: 0 minutes"); if (!(pCTs->pCBs->flags & KV_ASYNC_CB_RUNNING)) start = time(0); next = log_interval; do { ctxt_running = FALSE; if (elapse > next) { KV_TRC(pFT, "ASYNC RUNNING: %d elapsed minutes", elapse/60); next += log_interval; } for (i=0; i<KV_ASYNC_MAX_CONTEXTS; i++) { if (! (pCTs[i].flags & KV_ASYNC_CT_RUNNING)) continue; jobs_running = kv_async_dispatch_jobs(i); if (!jobs_running) { pCTs[i].flags &= ~KV_ASYNC_CT_RUNNING; pCTs[i].flags |= KV_ASYNC_CT_DONE; KV_TRC(pFT, "ASYNC DONE ctxt %d %x", i, pCTs[i].flags); continue; } else { ctxt_running = TRUE; } elapse = time(0) - start; if (elapse >= inject && pCTs[i].flags & KV_ASYNC_CT_ERROR_INJECT) { KV_TRC_FFDC(pFT, "FFDC: INJECT ERRORS"); FVT_KV_INJECT_READ_ERROR; FVT_KV_INJECT_WRITE_ERROR; FVT_KV_INJECT_ALLOC_ERROR; ++inject; } if (elapse >= pCTs[i].secs) { for (pCB=pCTs[i].pCBs;pCB<pCTs[i].pCBs+KV_ASYNC_JOB_Q;pCB++) { if ((pCB->flags & KV_ASYNC_CB_RUNNING || pCB->flags & KV_ASYNC_CB_QUEUED) && (!(pCB->flags & KV_ASYNC_CB_SHUTDOWN)) ) { pCB->flags |= KV_ASYNC_CB_SHUTDOWN; KV_TRC_IO(pFT, "SHUTDOWN pCB %p (%d >= %d)", pCB, elapse, pCTs[i].secs); } } } usleep(100); } } while (ctxt_running); stop = time(0); secs = stop - start; KV_TRC(pFT, "ASYNC RUNNING DONE: %d minutes", elapse/60); /* log cleanup, since the first ark_delete closes the log file */ for (i=0; i<KV_ASYNC_MAX_CONTEXTS; i++) { if (pCTs[i].flags & KV_ASYNC_CT_DONE) KV_TRC(pFT, "ASYNC CLEANUP: ctxt:%d ark:%p", i, pCTs[i].ark); } /* check for MULTI_CTXT_IO, destroy common kv dbs */ for (pCB=pCTs->pCBs;pCB<pCTs->pCBs+KV_ASYNC_JOB_Q;pCB++) { if (pCB->flags & KV_ASYNC_CB_MULTI_CTXT_IO) { kv_db_destroy(pCB->db, pCB->len); } } for (i=0; i<KV_ASYNC_MAX_CONTEXTS; i++) { /* if this context didn't run any I/O */ if (! (pCTs[i].flags & KV_ASYNC_CT_DONE)) continue; pCTs[i].flags &= ~KV_ASYNC_CT_DONE; /* if perf then don't delete the ark here */ if (pCTs[i].flags & KV_ASYNC_CT_PERF) { perf = TRUE; continue; } (void)ark_stats(pCTs[i].ark, &ops, &ios); tops += (uint32_t)ops; tios += (uint32_t)ios; KV_TRC(pFT, "PERF ark%p ops:%"PRIu64" ios:%"PRIu64"", pCTs[i].ark, ops, ios); EXPECT_EQ(0, ark_delete(pCTs[i].ark)); } if (!perf) { tops = tops / secs; tios = tios / secs; printf("op/s:%d io/s:%d secs:%d\n", tops, tios, secs); KV_TRC(pFT, "PERF op/s:%d io/s:%d secs:%d", tops, tios, secs); } }
/** ******************************************************************************** ** \brief ** do an ark asynchronous IO performance run *******************************************************************************/ void kv_async_io(char *dev, uint32_t ctxts, uint32_t jobs, uint32_t vlen, uint32_t len, uint32_t read) { async_context_t *pCT = NULL; async_CB_t *pCB = NULL; uint32_t job = 0; uint32_t ctxt = 0; uint32_t ctxt_running = 0; uint32_t i = 0; uint32_t e_secs = 0; uint64_t ops = 0; uint64_t ios = 0; uint32_t tops = 0; uint32_t tios = 0; if (read == 75) read100 = FALSE; else read100 = TRUE; printf("ASYNC: ctxt:%-2d QD:%-3d size:%2dk read:%3d%% ", ctxts, jobs, vlen/1000, read); fflush(stdout); init_kv_db(jobs, KLEN, vlen, len); pCTs = (async_context_t*) malloc(ctxts*sizeof(async_context_t)); assert(0 != pCTs); for (ctxt=0; ctxt<ctxts; ctxt++) { ARK *ark = NULL; pCT = pCTs+ctxt; memset(pCT, 0, sizeof(async_context_t)); NEW_ARK(dev, &ark); pCT->ark = ark; for (job=0; job<jobs; job++) { pCB = pCT->pCBs+job; pCB->itag = SET_ITAG(ctxt,job); pCB->ark = pCT->ark; pCB->flags = KV_ASYNC_SET; pCB->db = dbs+job; pCB->len = len; } } testcase_start = time(0); /* start all jobs for all contexts */ for (ctxt=0; ctxt<ctxts; ctxt++) { for (pCB=pCTs[ctxt].pCBs; pCB<pCTs[ctxt].pCBs+jobs; pCB++) { pCB->flags |= KV_ASYNC_RUNNING; kv_async_SET_KEY(pCB); } } /* loop until all jobs are done or until time elapses */ do { ctxt_running = FALSE; /* loop through contexts(arks) and check if all jobs are done or * time has elapsed */ for (i=0; i<ctxts; i++) { /* check if all jobs are done */ for (pCB=pCTs[i].pCBs;pCB<pCTs[i].pCBs+jobs;pCB++) { if (pCB->flags & KV_ASYNC_RUNNING) { ctxt_running = TRUE; } } if (!ctxt_running) continue; /* check if time has elapsed */ if (time(0) - testcase_start < KV_MIN_SECS) continue; for (pCB=pCTs[i].pCBs;pCB<pCTs[i].pCBs+jobs;pCB++) { if (pCB->flags & KV_ASYNC_RUNNING && (!(pCB->flags & KV_ASYNC_SHUTDOWN)) ) { pCB->flags |= KV_ASYNC_SHUTDOWN; } } } } while (ctxt_running); testcase_stop = time(0); e_secs = testcase_stop - testcase_start; /* sum perf ops for all contexts/jobs and delete arks */ for (i=0; i<ctxts; i++) { (void)ark_stats(pCTs[i].ark, &ops, &ios); tops += (uint32_t)ops; tios += (uint32_t)ios; } tops = tops / e_secs; tios = tios / e_secs; printf("op/s:%-7d io/s:%-7d secs:%d\n", tops, tios, e_secs); /* sum perf ops for all contexts/jobs and delete arks */ for (i=0; i<ctxts; i++) { assert(0 == ark_delete(pCTs[i].ark)); } free_kv_db(jobs, len); }
void fvt_kv_utils_perf(ARK *ark, uint32_t vlen, uint32_t mb, uint32_t LEN) { kv_t *db = NULL; uint64_t mb64_1 = (uint64_t)KV_1M; uint64_t bytes = mb64_1*mb; uint32_t i = 0; uint32_t klen = 16; uint64_t lchunk = LEN*vlen; uint32_t loops = mb; long int wr_us = 0; long int rd_us = 0; long int mil = 1000000; float wr_s = 0; float rd_s = 0; float wr_mb = 0; uint64_t ops = 0; uint64_t post_ops = 0; uint64_t io = 0; uint64_t post_io = 0; float wr_ops = 0; float wr_ios = 0; float rd_ops = 0; float rd_ios = 0; struct timeval stop, start; ASSERT_TRUE(NULL != ark); loops = (uint32_t)(bytes / lchunk); db = (kv_t*)kv_db_create_fixed(LEN, klen, vlen); ASSERT_TRUE(db != NULL); printf("SYNC %dx%dx%d\n", klen, vlen, LEN); for (i=0; i<loops; i++) { /* write/load all key/value pairs from the db into the ark */ (void)ark_stats(ark, &ops, &io); gettimeofday(&start, NULL); fvt_kv_utils_load(ark, db, LEN); gettimeofday(&stop, NULL); wr_us += (stop.tv_sec*mil + stop.tv_usec) - (start.tv_sec*mil + start.tv_usec); (void)ark_stats(ark, &post_ops, &post_io); wr_ops += post_ops - ops; wr_ios += post_io - io; /* read/query all key/value pairs from the db */ (void)ark_stats(ark, &ops, &io); gettimeofday(&start, NULL); fvt_kv_utils_read(ark, db, vlen, LEN); gettimeofday(&stop, NULL); rd_us += (stop.tv_sec*mil + stop.tv_usec) - (start.tv_sec*mil + start.tv_usec); (void)ark_stats(ark, &post_ops, &post_io); rd_ops += post_ops - ops; rd_ios += post_io - io; /* delete all key/value pairs from the db */ fvt_kv_utils_del(ark, db, LEN); } wr_s = (float)((float)wr_us/(float)mil); rd_s = (float)((float)rd_us/(float)mil); wr_mb = (float)((double)(bytes+(uint64_t)(klen*LEN*loops)) / (double)mb64_1); printf(" writes: %d mb in %.1f secs at %.3f mbps, %.0f op/s, %.0f io/s\n", mb, wr_s, wr_mb/wr_s, wr_ops/wr_s, wr_ios/wr_s); printf(" reads: %d mb in %.1f secs at %.3f mbps, %.0f op/s, %.0f io/s\n", mb, rd_s, (float)mb/rd_s, rd_ops/rd_s, rd_ios/rd_s); kv_db_destroy(db, LEN); }
/** ******************************************************************************* * \brief ******************************************************************************/ void Sync_pth::run_multi_ctxt_wr(uint32_t num_ctxt, uint32_t num_pth, uint32_t npool, uint32_t vlen, uint32_t LEN, uint32_t secs) { uint32_t i = 0; uint32_t ctxt_i = 0; uint32_t pth_i = 0; uint32_t klen = 16; uint32_t tot_pth = num_ctxt * num_pth; set_get_args_t pth_args[tot_pth]; ARK *ark[num_ctxt]; kv_t *db[num_pth]; struct timeval stop, start; uint64_t ops = 0; uint64_t ios = 0; uint32_t t_ops = 0; uint32_t t_ios = 0; if (num_pth > MAX_PTH_PER_CONTEXT) { printf("cannot exceed %d pthreads for sync ops\n", MAX_PTH_PER_CONTEXT); return; } memset(pth_args, 0, sizeof(set_get_args_t) * tot_pth); /* alloc one set of db's, to be used for each context */ for (i=0; i<num_pth; i++) { db[i] = (kv_t*)kv_db_create_fixed(LEN, klen+i, vlen+i); } /* alloc one ark for each context */ for (ctxt_i=0; ctxt_i<num_ctxt; ctxt_i++) { ASSERT_EQ(0, ark_create_verbose(getenv("FVT_DEV"), &ark[ctxt_i], 1048576, 4096, 1048576, npool, 256, 8*1024, ARK_KV_VIRTUAL_LUN)); ASSERT_TRUE(NULL != ark[ctxt_i]); } /* start timer */ gettimeofday(&start, NULL); /* init each pth per context and run the pth */ ctxt_i = 0; i = 0; while (i < tot_pth) { pth_args[i].ark = ark[ctxt_i]; pth_args[i].db = db[pth_i]; pth_args[i].vlen = vlen+pth_i; pth_args[i].LEN = LEN; pth_args[i].secs = secs; run_write_loop(pth_args+i); ++pth_i; ++i; if ((i%num_pth) == 0) { /* reset for next context */ ++ctxt_i; pth_i = 0; } } printf("SYNC %dx%dx%d ctxt:%d pth:%d npool:%d ", klen, vlen, LEN, num_ctxt, num_pth, npool); fflush(stdout); for (i=0; i<tot_pth; i++) { wait(pth_args+i); } /* stop timer */ gettimeofday(&stop, NULL); secs = stop.tv_sec - start.tv_sec; t_ops = 0; t_ios = 0; for (i=0; i<num_ctxt; i++) { (void)ark_stats(ark[i], &ops, &ios); t_ops += (uint32_t)ops; t_ios += (uint32_t)ios; EXPECT_EQ(0, ark_delete(ark[i])); } for (i=0; i<num_pth; i++) { kv_db_destroy(db[i], LEN); } t_ops = t_ops / secs; t_ios = t_ios / secs; printf("op/s:%d io/s:%d secs:%d\n", t_ops, t_ios, secs); }
void kv_async_wait_jobs(void) { async_CB_t *pCB = NULL; uint32_t ctxt_running = 0; uint32_t i = 0; uint32_t e_secs = 0; uint64_t ops = 0; uint64_t ios = 0; uint32_t tops = 0; uint32_t tios = 0; printf("ASYNC: "); fflush(stdout); /* loop until all jobs are done or until time elapses */ do { ctxt_running = FALSE; /* loop through contexts(arks) and check if all jobs are done or * time has elapsed */ for (i=0; i<KV_ASYNC_CONTEXTS; i++) { /* check if all jobs are done */ for (pCB=pCTs[i].pCBs;pCB<pCTs[i].pCBs+KV_ASYNC_JOBS_PER_CTXT;pCB++) { if (pCB->flags & KV_ASYNC_RUNNING) { ctxt_running = TRUE; } } if (!ctxt_running) continue; /* check if time has elapsed */ if (time(0) - start < KV_ASYNC_SECS) continue; for (pCB=pCTs[i].pCBs;pCB<pCTs[i].pCBs+KV_ASYNC_JOBS_PER_CTXT;pCB++) { if (pCB->flags & KV_ASYNC_RUNNING && (!(pCB->flags & KV_ASYNC_SHUTDOWN)) ) { pCB->flags |= KV_ASYNC_SHUTDOWN; } } } } while (ctxt_running); stop = time(0); e_secs = stop - start; /* sum perf ops for all contexts/jobs and delete arks */ for (i=0; i<KV_ASYNC_CONTEXTS; i++) { (void)ark_stats(pCTs[i].ark, &ops, &ios); tops += (uint32_t)ops; tios += (uint32_t)ios; } tops = tops / e_secs; tios = tios / e_secs; printf("op/s:%d io/s:%d secs:%d\n", tops, tios, e_secs); /* sum perf ops for all contexts/jobs and delete arks */ for (i=0; i<KV_ASYNC_CONTEXTS; i++) { assert(0 == ark_delete(pCTs[i].ark)); } }