From c1081a3ab5dc7e5c83ad84dd0b5c795969745d7d Mon Sep 17 00:00:00 2001 From: Derrick Brashear Date: Sat, 21 Jul 2012 00:17:14 -0400 Subject: [PATCH] rxgen: per-opcode stats allow access to per-opcode stats Change-Id: I17639cf23acac23acfb9cb7dc07a7c5c81d4ff89 Reviewed-on: http://gerrit.openafs.org/7802 Tested-by: BuildBot Reviewed-by: Jacob Thebault-Spieker Reviewed-by: Derrick Brashear --- src/libafsrpc/afsrpc.def | 7 + src/rx/rx.c | 290 ++++++++++++++++++++++++++++++++------- src/rx/rx.h | 101 ++++++++++++++ src/rx/rx_prototypes.h | 5 + src/rxgen/rpc_parse.c | 66 ++++++++- src/rxgen/rpc_parse.h | 1 + 6 files changed, 416 insertions(+), 54 deletions(-) diff --git a/src/libafsrpc/afsrpc.def b/src/libafsrpc/afsrpc.def index 59ad355d8..3315184bf 100755 --- a/src/libafsrpc/afsrpc.def +++ b/src/libafsrpc/afsrpc.def @@ -331,6 +331,13 @@ EXPORTS rx_HostOf @337 rx_PortOf @338 + rx_ClearProcessRPCStats @339 + rx_ClearPeerRPCStats @340 + rx_CopyProcessRPCStats @341 + rx_CopyPeerRPCStats @342 + rx_ReleaseRPCStats @343 + RXAFS_OpCodeIndex @344 + ; for performance testing rx_TSFPQGlobSize @2001 DATA rx_TSFPQLocalMax @2002 DATA diff --git a/src/rx/rx.c b/src/rx/rx.c index 79956d49e..81dff7014 100644 --- a/src/rx/rx.c +++ b/src/rx/rx.c @@ -8040,9 +8040,34 @@ static int rxi_monitor_processStats = 0; static int rxi_monitor_peerStats = 0; + +void +rxi_ClearRPCOpStat(rx_function_entry_v1_p rpc_stat) +{ + rpc_stat->invocations = 0; + rpc_stat->bytes_sent = 0; + rpc_stat->bytes_rcvd = 0; + rpc_stat->queue_time_sum.sec = 0; + rpc_stat->queue_time_sum.usec = 0; + rpc_stat->queue_time_sum_sqr.sec = 0; + rpc_stat->queue_time_sum_sqr.usec = 0; + rpc_stat->queue_time_min.sec = 9999999; + rpc_stat->queue_time_min.usec = 9999999; + rpc_stat->queue_time_max.sec = 0; + rpc_stat->queue_time_max.usec = 0; + rpc_stat->execution_time_sum.sec = 0; + rpc_stat->execution_time_sum.usec = 0; + rpc_stat->execution_time_sum_sqr.sec = 0; + rpc_stat->execution_time_sum_sqr.usec = 0; + rpc_stat->execution_time_min.sec = 9999999; + rpc_stat->execution_time_min.usec = 9999999; + rpc_stat->execution_time_max.sec = 0; + rpc_stat->execution_time_max.usec = 0; +} + /*! * Given all of the information for a particular rpc - * call, create (if needed) and update the stat totals for the rpc. + * call, find or create (if requested) the stat structure for the rpc. * * @param stats * the queue of stats that will be updated with the new value @@ -8050,53 +8075,41 @@ static int rxi_monitor_peerStats = 0; * @param rxInterface * a unique number that identifies the rpc interface * - * @param currentFunc - * the index of the function being invoked - * * @param totalFunc - * the total number of functions in this interface - * - * @param queueTime - * the amount of time this function waited for a thread - * - * @param execTime - * the amount of time this function invocation took to execute - * - * @param bytesSent - * the number bytes sent by this invocation - * - * @param bytesRcvd - * the number bytes received by this invocation + * the total number of functions in this interface. this is only + * required if create is true * * @param isServer * if true, this invocation was made to a server * * @param remoteHost - * the ip address of the remote host + * the ip address of the remote host. this is only required if create + * and addToPeerList are true * * @param remotePort - * the port of the remote host + * the port of the remote host. this is only required if create + * and addToPeerList are true * * @param addToPeerList * if != 0, add newly created stat to the global peer list * * @param counter * if a new stats structure is allocated, the counter will - * be updated with the new number of allocated stat structures + * be updated with the new number of allocated stat structures. + * only required if create is true + * + * @param create + * if no stats structure exists, allocate one * */ -static int -rxi_AddRpcStat(struct rx_queue *stats, afs_uint32 rxInterface, - afs_uint32 currentFunc, afs_uint32 totalFunc, - struct clock *queueTime, struct clock *execTime, - afs_uint64 bytesSent, afs_uint64 bytesRcvd, int isServer, - afs_uint32 remoteHost, afs_uint32 remotePort, - int addToPeerList, unsigned int *counter) +static rx_interface_stat_p +rxi_FindRpcStat(struct rx_queue *stats, afs_uint32 rxInterface, + afs_uint32 totalFunc, int isServer, afs_uint32 remoteHost, + afs_uint32 remotePort, int addToPeerList, + unsigned int *counter, int create) { - int rc = 0; rx_interface_stat_p rpc_stat, nrpc_stat; - /* * See if there's already a structure for this interface */ @@ -8107,6 +8120,14 @@ rxi_AddRpcStat(struct rx_queue *stats, afs_uint32 rxInterface, break; } + /* if they didn't ask us to create, we're done */ + if (!create) + return rpc_stat; + + /* can't proceed without these */ + if (!totalFunc || !counter) + return NULL; + /* * Didn't find a match so allocate a new structure and add it to the * queue. @@ -8123,43 +8144,208 @@ rxi_AddRpcStat(struct rx_queue *stats, afs_uint32 rxInterface, totalFunc * sizeof(rx_function_entry_v1_t); rpc_stat = rxi_Alloc(space); - if (rpc_stat == NULL) { - rc = 1; - goto fail; - } + if (rpc_stat == NULL) + return NULL; + *counter += totalFunc; for (i = 0; i < totalFunc; i++) { + rxi_ClearRPCOpStat(&(rpc_stat->stats[i])); rpc_stat->stats[i].remote_peer = remoteHost; rpc_stat->stats[i].remote_port = remotePort; rpc_stat->stats[i].remote_is_server = isServer; rpc_stat->stats[i].interfaceId = rxInterface; rpc_stat->stats[i].func_total = totalFunc; rpc_stat->stats[i].func_index = i; - rpc_stat->stats[i].invocations = 0; - rpc_stat->stats[i].bytes_sent = 0; - rpc_stat->stats[i].bytes_rcvd = 0; - rpc_stat->stats[i].queue_time_sum.sec = 0; - rpc_stat->stats[i].queue_time_sum.usec = 0; - rpc_stat->stats[i].queue_time_sum_sqr.sec = 0; - rpc_stat->stats[i].queue_time_sum_sqr.usec = 0; - rpc_stat->stats[i].queue_time_min.sec = 9999999; - rpc_stat->stats[i].queue_time_min.usec = 9999999; - rpc_stat->stats[i].queue_time_max.sec = 0; - rpc_stat->stats[i].queue_time_max.usec = 0; - rpc_stat->stats[i].execution_time_sum.sec = 0; - rpc_stat->stats[i].execution_time_sum.usec = 0; - rpc_stat->stats[i].execution_time_sum_sqr.sec = 0; - rpc_stat->stats[i].execution_time_sum_sqr.usec = 0; - rpc_stat->stats[i].execution_time_min.sec = 9999999; - rpc_stat->stats[i].execution_time_min.usec = 9999999; - rpc_stat->stats[i].execution_time_max.sec = 0; - rpc_stat->stats[i].execution_time_max.usec = 0; } queue_Prepend(stats, rpc_stat); if (addToPeerList) { queue_Prepend(&peerStats, &rpc_stat->all_peers); } } + return rpc_stat; +} + +void +rx_ClearProcessRPCStats(afs_int32 rxInterface) +{ + rx_interface_stat_p rpc_stat; + int totalFunc, i; + + if (rxInterface == -1) + return; + + MUTEX_ENTER(&rx_rpc_stats); + rpc_stat = rxi_FindRpcStat(&processStats, rxInterface, 0, 0, + 0, 0, 0, 0, 0); + if (rpc_stat) { + totalFunc = rpc_stat->stats[0].func_total; + for (i = 0; i < totalFunc; i++) + rxi_ClearRPCOpStat(&(rpc_stat->stats[i])); + } + MUTEX_EXIT(&rx_rpc_stats); + return; +} + +void +rx_ClearPeerRPCStats(afs_int32 rxInterface, afs_uint32 peerHost, afs_uint16 peerPort) +{ + rx_interface_stat_p rpc_stat; + int totalFunc, i; + struct rx_peer * peer; + + if (rxInterface == -1) + return; + + peer = rxi_FindPeer(peerHost, peerPort, 0, 0); + if (!peer) + return; + + MUTEX_ENTER(&rx_rpc_stats); + rpc_stat = rxi_FindRpcStat(&peer->rpcStats, rxInterface, 0, 1, + 0, 0, 0, 0, 0); + if (rpc_stat) { + totalFunc = rpc_stat->stats[0].func_total; + for (i = 0; i < totalFunc; i++) + rxi_ClearRPCOpStat(&(rpc_stat->stats[i])); + } + MUTEX_EXIT(&rx_rpc_stats); + return; +} + +void * +rx_CopyProcessRPCStats(afs_uint64 op) +{ + rx_interface_stat_p rpc_stat; + rx_function_entry_v1_p rpcop_stat = + rxi_Alloc(sizeof(rx_function_entry_v1_t)); + int currentFunc = (op & MAX_AFS_UINT32); + afs_int32 rxInterface = (op >> 32); + + if (!rxi_monitor_processStats) + return NULL; + + if (rxInterface == -1) + return NULL; + + MUTEX_ENTER(&rx_rpc_stats); + rpc_stat = rxi_FindRpcStat(&processStats, rxInterface, 0, 0, + 0, 0, 0, 0, 0); + if (rpc_stat) + memcpy(rpcop_stat, &(rpc_stat->stats[currentFunc]), + sizeof(rx_function_entry_v1_t)); + MUTEX_EXIT(&rx_rpc_stats); + if (!rpc_stat) { + rxi_Free(rpcop_stat, sizeof(rx_function_entry_v1_t)); + return NULL; + } + return rpcop_stat; +} + +void * +rx_CopyPeerRPCStats(afs_uint64 op, afs_uint32 peerHost, afs_uint16 peerPort) +{ + rx_interface_stat_p rpc_stat; + rx_function_entry_v1_p rpcop_stat = + rxi_Alloc(sizeof(rx_function_entry_v1_t)); + int currentFunc = (op & MAX_AFS_UINT32); + afs_int32 rxInterface = (op >> 32); + struct rx_peer *peer; + + if (!rxi_monitor_peerStats) + return NULL; + + if (rxInterface == -1) + return NULL; + + peer = rxi_FindPeer(peerHost, peerPort, 0, 0); + if (!peer) + return NULL; + + MUTEX_ENTER(&rx_rpc_stats); + rpc_stat = rxi_FindRpcStat(&peer->rpcStats, rxInterface, 0, 1, + 0, 0, 0, 0, 0); + if (rpc_stat) + memcpy(rpcop_stat, &(rpc_stat->stats[currentFunc]), + sizeof(rx_function_entry_v1_t)); + MUTEX_EXIT(&rx_rpc_stats); + if (!rpc_stat) { + rxi_Free(rpcop_stat, sizeof(rx_function_entry_v1_t)); + return NULL; + } + return rpcop_stat; +} + +void +rx_ReleaseRPCStats(void *stats) +{ + if (stats) + rxi_Free(stats, sizeof(rx_function_entry_v1_t)); +} + +/*! + * Given all of the information for a particular rpc + * call, create (if needed) and update the stat totals for the rpc. + * + * @param stats + * the queue of stats that will be updated with the new value + * + * @param rxInterface + * a unique number that identifies the rpc interface + * + * @param currentFunc + * the index of the function being invoked + * + * @param totalFunc + * the total number of functions in this interface + * + * @param queueTime + * the amount of time this function waited for a thread + * + * @param execTime + * the amount of time this function invocation took to execute + * + * @param bytesSent + * the number bytes sent by this invocation + * + * @param bytesRcvd + * the number bytes received by this invocation + * + * @param isServer + * if true, this invocation was made to a server + * + * @param remoteHost + * the ip address of the remote host + * + * @param remotePort + * the port of the remote host + * + * @param addToPeerList + * if != 0, add newly created stat to the global peer list + * + * @param counter + * if a new stats structure is allocated, the counter will + * be updated with the new number of allocated stat structures + * + */ + +static int +rxi_AddRpcStat(struct rx_queue *stats, afs_uint32 rxInterface, + afs_uint32 currentFunc, afs_uint32 totalFunc, + struct clock *queueTime, struct clock *execTime, + afs_uint64 bytesSent, afs_uint64 bytesRcvd, int isServer, + afs_uint32 remoteHost, afs_uint32 remotePort, + int addToPeerList, unsigned int *counter) +{ + int rc = 0; + rx_interface_stat_p rpc_stat; + + rpc_stat = rxi_FindRpcStat(stats, rxInterface, totalFunc, isServer, + remoteHost, remotePort, addToPeerList, counter, + 1); + if (!rpc_stat) { + rc = -1; + goto fail; + } /* * Increment the stats for this function diff --git a/src/rx/rx.h b/src/rx/rx.h index 74deffcc3..599935a7c 100644 --- a/src/rx/rx.h +++ b/src/rx/rx.h @@ -890,4 +890,105 @@ extern int rx_DumpCalls(FILE *outputFile, char *cookie); #include "rx_prototypes.h" #endif +static_inline afs_uint32 +RPCOpStat_Peer(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return rpcop_stat->remote_peer; +} + +static_inline afs_uint32 +RPCOpStat_Port(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return rpcop_stat->remote_port; +} + +static_inline afs_uint32 +RPCOpStat_IsServer(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return rpcop_stat->remote_is_server; +} + +static_inline afs_uint32 +RPCOpStat_InterfaceId(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return rpcop_stat->interfaceId; +} + +static_inline afs_uint32 +RPCOpStat_NumFuncs(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return rpcop_stat->func_total; +} + +static_inline afs_uint32 +RPCOpStat_CurFunc(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return rpcop_stat->func_index; +} + +static_inline struct clock * +RPCOpStat_QTimeSum(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return &(rpcop_stat->queue_time_sum); +} + +static_inline struct clock * +RPCOpStat_QTimeSumSqr(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return &(rpcop_stat->queue_time_sum_sqr); +} + +static_inline struct clock * +RPCOpStat_QTimeSumMin(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return &(rpcop_stat->queue_time_min); +} + +static_inline struct clock * +RPCOpStat_QTimeSumMax(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return &(rpcop_stat->queue_time_max); +} + +static_inline struct clock * +RPCOpStat_ExecTimeSum(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return &(rpcop_stat->execution_time_sum); +} + +static_inline struct clock * +RPCOpStat_ExecTimeSumSqr(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return &(rpcop_stat->execution_time_sum_sqr); +} + +static_inline struct clock * +RPCOpStat_ExecTimeSumMin(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return &(rpcop_stat->execution_time_min); +} + +static_inline struct clock * +RPCOpStat_ExecTimeSumMax(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return &(rpcop_stat->execution_time_max); +} + +static_inline afs_uint64 +RPCOpStat_NumCalls(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return rpcop_stat->invocations; +} + +static_inline afs_uint64 +RPCOpStat_BytesSent(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return rpcop_stat->bytes_sent; +} + +static_inline afs_uint64 +RPCOpStat_BytesRcvd(void *blob) { + rx_function_entry_v1_p rpcop_stat = (rx_function_entry_v1_p)blob; + return rpcop_stat->bytes_rcvd; +} #endif /* !KDUMP_RX_LOCK */ diff --git a/src/rx/rx_prototypes.h b/src/rx/rx_prototypes.h index c42fdcb8d..e533cd1c3 100644 --- a/src/rx/rx_prototypes.h +++ b/src/rx/rx_prototypes.h @@ -167,6 +167,11 @@ extern void rx_clearProcessRPCStats(afs_uint32 clearFlag); extern void rx_clearPeerRPCStats(afs_uint32 clearFlag); extern void rx_SetRxStatUserOk(int (*proc) (struct rx_call * call)); extern int rx_RxStatUserOk(struct rx_call *call); +extern void rx_ClearProcessRPCStats(afs_int32 rxInterface); +extern void rx_ClearPeerRPCStats(afs_int32 rxInterface, afs_uint32 peerHost, afs_uint16 peerPort); +extern void *rx_CopyProcessRPCStats(afs_uint64 op); +extern void *rx_CopyPeerRPCStats(afs_uint64 op, afs_uint32 peerHost, afs_uint16 peerPort); +extern void rx_ReleaseRPCStats(void *stats); extern afs_int32 rx_SetSecurityConfiguration(struct rx_service *service, rx_securityConfigVariables type, void *value); diff --git a/src/rxgen/rpc_parse.c b/src/rxgen/rpc_parse.c index 3eff6a3c0..313205584 100644 --- a/src/rxgen/rpc_parse.c +++ b/src/rxgen/rpc_parse.c @@ -143,9 +143,12 @@ static void er_ProcDeclExterns_setup(void); static void er_ProcProcsArray_setup(void); static void er_ProcMainBody_setup(void); static void er_HeadofOldStyleProc_setup(void); +static void er_HeadofOldStyleProc_setup2(void); static void er_BodyofOldStyleProc_setup(void); +static void er_BodyofOldStyleProc_setup2(void); static void proc_er_case(definition * defp); static void er_TailofOldStyleProc_setup(void); +static void er_TailofOldStyleProc_setup2(void); @@ -842,6 +845,7 @@ check_proc(definition * defp, token * tokp, int noname) prefix, PackagePrefix[PackageIndex], defp->pc.proc_name); function_list_index++; + defp->statindex = no_of_stat_funcs; no_of_stat_funcs_header[PackageIndex]++; no_of_stat_funcs++; *Proc_listp = NULL; @@ -1972,6 +1976,9 @@ er_Proc_CodeGeneration(void) er_HeadofOldStyleProc_setup(); er_BodyofOldStyleProc_setup(); er_TailofOldStyleProc_setup(); + er_HeadofOldStyleProc_setup2(); + er_BodyofOldStyleProc_setup2(); + er_TailofOldStyleProc_setup2(); } else { er_ProcDeclExterns_setup(); er_ProcProcsArray_setup(); @@ -2056,6 +2063,13 @@ er_ProcMainBody_setup(void) PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]); f_print(fout, "\treturn opnames%d[op - %sLOWEST_OPCODE];\n}\n", PackageIndex, PackagePrefix[PackageIndex]); + f_print(fout, "struct %sstats *%sOpCodeStats(int op)\n{\n", + PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]); + f_print(fout, "\tif (op < %sLOWEST_OPCODE || op > %sHIGHEST_OPCODE)\n\t\treturn NULL;\n", + PackagePrefix[PackageIndex], PackagePrefix[PackageIndex]); + f_print(fout, "\treturn NULL;/*%d %s*/\n}\n", + PackageIndex, PackagePrefix[PackageIndex]); + return; } f_print(fout, "int %s%sExecuteRequest(struct rx_call *z_call)\n", @@ -2075,6 +2089,14 @@ er_ProcMainBody_setup(void) f_print(fout, "\treturn hton_syserr_conv(z_result);\n}\n"); } +static void +er_HeadofOldStyleProc_setup2(void) +{ + if ( cflag ) { + f_print(fout, "int %sOpCodeIndex(int op)\n{\n", (combinepackages ? MasterPrefix : PackagePrefix[PackageIndex])); + f_print(fout, "\tswitch (op) {\n"); + } +} static void er_HeadofOldStyleProc_setup(void) @@ -2144,6 +2166,44 @@ proc_er_case(definition * defp) f_print(fout, "\t\t\tbreak;\n"); } +static void +proc_op_case(definition * defp) +{ + f_print(fout, "\t\tcase %d:", defp->pc.proc_opcodenum); + f_print(fout, "\treturn %d;\n", + defp->statindex); +} + +static void +er_BodyofOldStyleProc_setup2(void) +{ + list *listp; + + if (!cflag) + return; + if (combinepackages) { + int temp = PackageIndex; + for (PackageIndex = 0; PackageIndex <= temp; PackageIndex++) { + for (listp = proc_defined[PackageIndex]; listp != NULL; + listp = listp->next) + proc_op_case((definition *) listp->val); + } + PackageIndex = temp; + } else { + for (listp = proc_defined[PackageIndex]; listp != NULL; + listp = listp->next) + proc_op_case((definition *) listp->val); + } +} + +static void +er_TailofOldStyleProc_setup2(void) +{ + if ( cflag ) { + f_print(fout, "\t\tdefault:\n"); + f_print(fout, "\t\t\treturn -1;\n\t}\n}\n"); + } +} static void er_TailofOldStyleProc_setup(void) @@ -2169,9 +2229,11 @@ h_ProcMainBody_setup(void) static void h_HeadofOldStyleProc_setup(void) { + char *pprefix = (combinepackages ? MasterPrefix : + PackagePrefix[PackageIndex]); + f_print(fout,"\nstruct %sstats{\n\tint statsver;\n};", pprefix); f_print(fout,"\nextern int %s%sExecuteRequest(struct rx_call *);\n", - prefix, - (combinepackages ? MasterPrefix : PackagePrefix[PackageIndex])); + prefix, pprefix); f_print(fout,"\nextern int %sOpCodeIndex(int op);\n", PackagePrefix[PackageIndex]); } diff --git a/src/rxgen/rpc_parse.h b/src/rxgen/rpc_parse.h index 7adb6f2d6..e003ef404 100644 --- a/src/rxgen/rpc_parse.h +++ b/src/rxgen/rpc_parse.h @@ -225,5 +225,6 @@ struct definition { } def; procedure_def pc; int can_fail; + int statindex; }; typedef struct definition definition; -- 2.39.5