📄 pjsip-perf.c
字号:
/* Send one stateful request */static pj_status_t submit_job(void){ pjsip_tx_data *tdata; pj_status_t status; status = pjsip_endpt_create_request(app.sip_endpt, &app.client.method, &app.client.dst_uri, &app.local_uri, &app.client.dst_uri, &app.local_contact, NULL, -1, NULL, &tdata); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Error creating request", status); report_completion(701); return status; } status = pjsip_endpt_send_request(app.sip_endpt, tdata, -1, NULL, &tsx_completion_cb); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Error sending stateful request", status); //should have been reported by tsx_completion_cb(). //report_completion(701); //No longer necessary (r777) //pjsip_tx_data_dec_ref(tdata); } return status;}/* Client worker thread */static int client_thread(void *arg){ pj_time_val end_time, last_report, now; unsigned thread_index = (unsigned)(long)arg; unsigned cycle = 0, last_cycle = 0; pj_thread_sleep(100); pj_gettimeofday(&end_time); end_time.sec += app.client.timeout; pj_gettimeofday(&last_report); if (app.client.first_request.sec == 0) { pj_gettimeofday(&app.client.first_request); } /* Submit all jobs */ while (app.client.job_submitted < app.client.job_count && !app.thread_quit){ pj_time_val timeout = { 0, 1 }; unsigned i; int outstanding; pj_status_t status; /* Calculate current outstanding job */ outstanding = app.client.job_submitted - app.client.job_finished; /* Update stats on max outstanding jobs */ if (outstanding > (int)app.client.stat_max_window) app.client.stat_max_window = outstanding; /* Wait if there are more pending jobs than allowed in the * window. But spawn a new job anyway if no events are happening * after we wait for some time. */ for (i=0; outstanding > (int)app.client.job_window && i<1000; ++i) { pj_time_val wait = { 0, 500 }; unsigned count = 0; pjsip_endpt_handle_events2(app.sip_endpt, &wait, &count); outstanding = app.client.job_submitted - app.client.job_finished; if (count == 0) break; ++cycle; } /* Submit one job */ if (app.client.method.id == PJSIP_INVITE_METHOD) { status = make_call(&app.client.dst_uri); } else if (app.client.stateless) { status = submit_stateless_job(); } else { status = submit_job(); } ++app.client.job_submitted; ++cycle; /* Handle event */ pjsip_endpt_handle_events2(app.sip_endpt, &timeout, NULL); /* Check for time out, also print report */ if (cycle - last_cycle >= 500) { pj_gettimeofday(&now); if (PJ_TIME_VAL_GTE(now, end_time)) { break; } last_cycle = cycle; if (thread_index == 0 && now.sec-last_report.sec >= 2) { printf("\r%d jobs started, %d completed... ", app.client.job_submitted, app.client.job_finished); fflush(stdout); last_report = now; } } } if (app.client.requests_sent.sec == 0) { pj_gettimeofday(&app.client.requests_sent); } if (thread_index == 0) { printf("\r%d jobs started, %d completed%s\n", app.client.job_submitted, app.client.job_finished, (app.client.job_submitted!=app.client.job_finished ? ", waiting..." : ".") ); fflush(stdout); } /* Wait until all jobs completes, or timed out */ pj_gettimeofday(&now); while (PJ_TIME_VAL_LT(now, end_time) && app.client.job_finished < app.client.job_count && !app.thread_quit) { pj_time_val timeout = { 0, 1 }; unsigned i; for (i=0; i<1000; ++i) { unsigned count; count = 0; pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &count); if (count == 0) break; } pj_gettimeofday(&now); } /* Wait couple of seconds to let jobs completes (e.g. ACKs to be sent) */ pj_gettimeofday(&now); end_time = now; end_time.sec += 2; while (PJ_TIME_VAL_LT(now, end_time)) { pj_time_val timeout = { 0, 1 }; unsigned i; for (i=0; i<1000; ++i) { unsigned count; count = 0; pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &count); if (count == 0) break; } pj_gettimeofday(&now); } return 0;}static const char *good_number(char *buf, pj_int32_t val){ if (val < 1000) { pj_ansi_sprintf(buf, "%d", val); } else if (val < 1000000) { pj_ansi_sprintf(buf, "%d.%dK", val / 1000, (val % 1000) / 100); } else { pj_ansi_sprintf(buf, "%d.%02dM", val / 1000000, (val % 1000000) / 10000); } return buf;}static int server_thread(void *arg){ pj_time_val timeout = { 0, 1 }; unsigned thread_index = (unsigned)(long)arg; pj_time_val last_report, next_report; pj_gettimeofday(&last_report); next_report = last_report; next_report.sec++; while (!app.thread_quit) { pj_time_val now; unsigned i; for (i=0; i<100; ++i) { unsigned count = 0; pjsip_endpt_handle_events2(app.sip_endpt, &timeout, &count); if (count == 0) break; } if (thread_index == 0) { pj_gettimeofday(&now); if (PJ_TIME_VAL_GTE(now, next_report)) { pj_time_val tmp; unsigned msec; unsigned stateless, stateful, call; char str_stateless[32], str_stateful[32], str_call[32]; tmp = now; PJ_TIME_VAL_SUB(tmp, last_report); msec = PJ_TIME_VAL_MSEC(tmp); last_report = now; next_report = last_report; next_report.sec++; stateless = app.server.cur_state.stateless_cnt - app.server.prev_state.stateless_cnt; stateful = app.server.cur_state.stateful_cnt - app.server.prev_state.stateful_cnt; call = app.server.cur_state.call_cnt - app.server.prev_state.call_cnt; good_number(str_stateless, app.server.cur_state.stateless_cnt); good_number(str_stateful, app.server.cur_state.stateful_cnt); good_number(str_call, app.server.cur_state.call_cnt); printf("Total(rate): stateless:%s (%d/s), statefull:%s (%d/s), call:%s (%d/s) \r", str_stateless, stateless*1000/msec, str_stateful, stateful*1000/msec, str_call, call*1000/msec); fflush(stdout); app.server.prev_state = app.server.cur_state; } } } return 0;}static void write_report(const char *msg){ puts(msg);#if defined(PJ_WIN32) && PJ_WIN32!=0 OutputDebugString(msg); OutputDebugString("\n");#endif}int main(int argc, char *argv[]){ static char report[1024]; printf("PJSIP Performance Measurement Tool v%s\n" "(c)2006 pjsip.org\n\n", PJ_VERSION); if (create_app() != 0) return 1; if (init_options(argc, argv) != 0) return 1; if (init_sip() != 0) return 1; if (init_media() != 0) return 1; pj_log_set_level(app.log_level); if (app.log_level > 4) { pjsip_endpt_register_module(app.sip_endpt, &msg_logger); } /* Misc infos */ if (app.client.dst_uri.slen != 0) { if (app.client.method.id == PJSIP_INVITE_METHOD) { if (app.client.stateless) { PJ_LOG(3,(THIS_FILE, "Info: --stateless option makes no sense for INVITE," " ignored.")); } } } if (app.client.dst_uri.slen) { /* Client mode */ pj_status_t status; char test_type[64]; unsigned msec_req, msec_res; unsigned i; /* Get the job name */ if (app.client.method.id == PJSIP_INVITE_METHOD) { pj_ansi_strcpy(test_type, "INVITE calls"); } else if (app.client.stateless) { pj_ansi_sprintf(test_type, "stateless %.*s requests", (int)app.client.method.name.slen, app.client.method.name.ptr); } else { pj_ansi_sprintf(test_type, "stateful %.*s requests", (int)app.client.method.name.slen, app.client.method.name.ptr); } printf("Sending %d %s to '%.*s' with %d maximum outstanding jobs, please wait..\n", app.client.job_count, test_type, (int)app.client.dst_uri.slen, app.client.dst_uri.ptr, app.client.job_window); for (i=0; i<app.thread_count; ++i) { status = pj_thread_create(app.pool, NULL, &client_thread, (void*)(long)i, 0, 0, &app.thread[i]); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to create thread", status); return 1; } } for (i=0; i<app.thread_count; ++i) { pj_thread_join(app.thread[i]); app.thread[i] = NULL; } if (app.client.last_completion.sec) { pj_time_val duration; duration = app.client.last_completion; PJ_TIME_VAL_SUB(duration, app.client.first_request); msec_res = PJ_TIME_VAL_MSEC(duration); } else { msec_res = app.client.timeout * 1000; } if (msec_res == 0) msec_res = 1; if (app.client.requests_sent.sec) { pj_time_val duration; duration = app.client.requests_sent; PJ_TIME_VAL_SUB(duration, app.client.first_request); msec_req = PJ_TIME_VAL_MSEC(duration); } else { msec_req = app.client.timeout * 1000; } if (msec_req == 0) msec_req = 1; if (app.client.job_submitted < app.client.job_count) puts("\ntimed-out!\n"); else puts("\ndone.\n"); pj_ansi_snprintf( report, sizeof(report), "Total %d %s sent in %d ms at rate of %d/sec\n" "Total %d responses receieved in %d ms at rate of %d/sec:", app.client.job_submitted, test_type, msec_req, app.client.job_submitted * 1000 / msec_req, app.client.total_responses, msec_res, app.client.total_responses*1000/msec_res); write_report(report); /* Print detailed response code received */ pj_ansi_sprintf(report, "\nDetailed responses received:"); write_report(report); for (i=0; i<PJ_ARRAY_SIZE(app.client.response_codes); ++i) { const pj_str_t *reason; if (app.client.response_codes[i] == 0) continue; reason = pjsip_get_status_text(i); pj_ansi_snprintf( report, sizeof(report), " - %d responses: %7d (%.*s)", i, app.client.response_codes[i], (int)reason->slen, reason->ptr); write_report(report); } /* Total responses and rate */ pj_ansi_snprintf( report, sizeof(report), " ------\n" " TOTAL responses: %7d (rate=%d/sec)\n", app.client.total_responses, app.client.total_responses*1000/msec_res); write_report(report); pj_ansi_sprintf(report, "Maximum outstanding job: %d", app.client.stat_max_window); write_report(report); } else { /* Server mode */ char s[10]; pj_status_t status; unsigned i; puts("pjsip-perf started in server-mode"); printf("Receiving requests on the following URIs:\n" " sip:0@%.*s:%d%s for stateless handling\n" " sip:1@%.*s:%d%s for stateful handling\n" " sip:2@%.*s:%d%s for call handling\n", (int)app.local_addr.slen, app.local_addr.ptr, app.local_port, (app.use_tcp ? ";transport=tcp" : ""), (int)app.local_addr.slen, app.local_addr.ptr, app.local_port, (app.use_tcp ? ";transport=tcp" : ""), (int)app.local_addr.slen, app.local_addr.ptr, app.local_port, (app.use_tcp ? ";transport=tcp" : "")); printf("INVITE with non-matching user part will be handled call-statefully\n"); for (i=0; i<app.thread_count; ++i) { status = pj_thread_create(app.pool, NULL, &server_thread, (void*)(long)i, 0, 0, &app.thread[i]); if (status != PJ_SUCCESS) { app_perror(THIS_FILE, "Unable to create thread", status); return 1; } } puts("\nPress <ENTER> to quit\n"); fflush(stdout); fgets(s, sizeof(s), stdin); app.thread_quit = PJ_TRUE; for (i=0; i<app.thread_count; ++i) { pj_thread_join(app.thread[i]); app.thread[i] = NULL; } puts(""); } destroy_app(); return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -