I totally see your point. I guess it’s not important to keep the OTHER counter, so I’ve removed it.
Using the new mutex-like semantics the code is much easier to understand. I’ve changed the names accordingly I’m sending a v6 Thanks for the review Daniele > On 6 Apr 2015, at 22:49, Ethan Jackson <et...@nicira.com> wrote: > > I don't really like the names of the two new functions, they're > verbose and don't convey much information (one or the other is fine, > both less so). I'm not sure what would be better, but off the top of > my head let me suggest something like: > > cycle_reset() > cycle_tally() > > Think about it, there's probably something better. > > My main problem with this patch is how fragile the counter calls seem. > After reading through it several times, I'm still not convinced that > it's correct, and I worry that as the code changes, it's going to get > pretty drastically wrong very quickly. I think conceptually these > things should be treated like mutex locks and unlocks. I.E. a call to > the diff() function should be in the same function as it's > corresponding cycles() function so it's clear what it corresponds too. > Couple of examples: > > The POLLING counter could be drastically simplified by simply > surrounding netdev_rxq_recv() with a diff and cycles call. > > Similarly PROCESSING could be simplified by surrounding dp_netdev_input(). > > I'm not sure how useful OTHER is, but if we need it, it could be > calculated as the total elapsed cycles minus POLLING and PROCESSING. > > I'm not sure those are necessarily the best way to proceed, but my > main point is that the code is confusing and likely fragile. I think > it could be improved. > > Ethan > > > On Wed, Apr 1, 2015 at 9:21 AM, Daniele Di Proietto > <diproiet...@vmware.com> wrote: >> The counters use x86 TSC if available (currently only with DPDK). They >> will be exposed by subsequents commits >> >> Signed-off-by: Daniele Di Proietto <diproiet...@vmware.com> >> --- >> lib/dpif-netdev.c | 70 >> ++++++++++++++++++++++++++++++++++++++++++++++++++++++- >> 1 file changed, 69 insertions(+), 1 deletion(-) >> >> diff --git a/lib/dpif-netdev.c b/lib/dpif-netdev.c >> index 8f267f6..c093d10 100644 >> --- a/lib/dpif-netdev.c >> +++ b/lib/dpif-netdev.c >> @@ -227,6 +227,13 @@ enum dp_stat_type { >> DP_N_STATS >> }; >> >> +enum pmd_cycles_counter_type { >> + PMD_CYCLES_POLLING, /* Cycles spent polling NICs. */ >> + PMD_CYCLES_PROCESSING, /* Cycles spent processing packets */ >> + PMD_CYCLES_OTHER, /* Cycles spent doing other tasks */ >> + PMD_N_CYCLES >> +}; >> + >> /* A port in a netdev-based datapath. */ >> struct dp_netdev_port { >> struct cmap_node node; /* Node in dp_netdev's 'ports'. */ >> @@ -342,6 +349,12 @@ struct dp_netdev_pmd_stats { >> ATOMIC(unsigned long long) n[DP_N_STATS]; >> }; >> >> +/* Contained by struct dp_netdev_pmd_thread's 'cycle' member. */ >> +struct dp_netdev_pmd_cycles { >> + /* Indexed by PMD_CYCLES_*. */ >> + ATOMIC(uint64_t) n[PMD_N_CYCLES]; >> +}; >> + >> /* PMD: Poll modes drivers. PMD accesses devices via polling to eliminate >> * the performance overhead of interrupt processing. Therefore netdev can >> * not implement rx-wait for these devices. dpif-netdev needs to poll >> @@ -384,6 +397,12 @@ struct dp_netdev_pmd_thread { >> /* Statistics. */ >> struct dp_netdev_pmd_stats stats; >> >> + /* Cycles counters */ >> + struct dp_netdev_pmd_cycles cycles; >> + >> + /* Used to count cicles. See 'pmd_cycles_counter_diff()' */ >> + uint64_t last_cycles; >> + >> struct latch exit_latch; /* For terminating the pmd thread. */ >> atomic_uint change_seq; /* For reloading pmd ports. */ >> pthread_t thread; >> @@ -393,6 +412,10 @@ struct dp_netdev_pmd_thread { >> int numa_id; /* numa node id of this pmd thread. */ >> }; >> >> +static inline uint64_t pmd_cycles_counter_diff(struct dp_netdev_pmd_thread >> *); >> +static inline void pmd_count_previous_cycles(struct dp_netdev_pmd_thread *, >> + enum pmd_cycles_counter_type); >> + >> #define PMD_INITIAL_SEQ 1 >> >> /* Interface to netdev-based datapath. */ >> @@ -2093,6 +2116,7 @@ dpif_netdev_execute(struct dpif *dpif, struct >> dpif_execute *execute) >> if (pmd->core_id == NON_PMD_CORE_ID) { >> ovs_mutex_lock(&dp->non_pmd_mutex); >> ovs_mutex_lock(&dp->port_mutex); >> + pmd_cycles_counter_diff(pmd); >> } >> >> pp = execute->packet; >> @@ -2102,6 +2126,7 @@ dpif_netdev_execute(struct dpif *dpif, struct >> dpif_execute *execute) >> dp_netdev_pmd_unref(pmd); >> ovs_mutex_unlock(&dp->port_mutex); >> ovs_mutex_unlock(&dp->non_pmd_mutex); >> + pmd_count_previous_cycles(pmd, PMD_CYCLES_PROCESSING); >> } >> >> return 0; >> @@ -2244,6 +2269,36 @@ dp_netdev_actions_free(struct dp_netdev_actions >> *actions) >> } >> >> >> +/* This function returns the length of the interval since the last call >> + * to the function itself (with the same 'pmd' argument) */ >> +static inline uint64_t >> +pmd_cycles_counter_diff(struct dp_netdev_pmd_thread *pmd) >> +{ >> + uint64_t old_cycles = pmd->last_cycles, >> +#ifdef DPDK_NETDEV >> + new_cycles = rte_get_tsc_cycles(); >> +#else >> + new_cycles = 0; >> +#endif >> + >> + pmd->last_cycles = new_cycles; >> + >> + return new_cycles - old_cycles; >> +} >> + >> +/* Updates the pmd cycles counter, considering the past cycles spent >> + * for the reason specified in 'type' */ >> +static inline void >> +pmd_count_previous_cycles(struct dp_netdev_pmd_thread *pmd, >> + enum pmd_cycles_counter_type type) >> +{ >> + uint64_t c; >> + >> + atomic_read_relaxed(&pmd->cycles.n[type], &c); >> + c += pmd_cycles_counter_diff(pmd); >> + atomic_store_relaxed(&pmd->cycles.n[type], c); >> +} >> + >> static void >> dp_netdev_process_rxq_port(struct dp_netdev_pmd_thread *pmd, >> struct dp_netdev_port *port, >> @@ -2256,6 +2311,8 @@ dp_netdev_process_rxq_port(struct dp_netdev_pmd_thread >> *pmd, >> if (!error) { >> int i; >> >> + pmd_count_previous_cycles(pmd, PMD_CYCLES_POLLING); >> + >> *recirc_depth_get() = 0; >> >> /* XXX: initialize md in netdev implementation. */ >> @@ -2263,6 +2320,7 @@ dp_netdev_process_rxq_port(struct dp_netdev_pmd_thread >> *pmd, >> packets[i]->md = PKT_METADATA_INITIALIZER(port->port_no); >> } >> dp_netdev_input(pmd, packets, cnt); >> + pmd_count_previous_cycles(pmd, PMD_CYCLES_PROCESSING); >> } else if (error != EAGAIN && error != EOPNOTSUPP) { >> static struct vlog_rate_limit rl = VLOG_RATE_LIMIT_INIT(1, 5); >> >> @@ -2282,6 +2340,7 @@ dpif_netdev_run(struct dpif *dpif) >> uint64_t new_tnl_seq; >> >> ovs_mutex_lock(&dp->non_pmd_mutex); >> + pmd_count_previous_cycles(non_pmd, PMD_CYCLES_OTHER); >> CMAP_FOR_EACH (port, node, &dp->ports) { >> if (!netdev_is_pmd(port->netdev)) { >> int i; >> @@ -2392,6 +2451,10 @@ pmd_thread_main(void *f_) >> /* Stores the pmd thread's 'pmd' to 'per_pmd_key'. */ >> ovsthread_setspecific(pmd->dp->per_pmd_key, pmd); >> pmd_thread_setaffinity_cpu(pmd->core_id); >> + >> + /* Initialize the cycles counter */ >> + pmd_cycles_counter_diff(pmd); >> + >> reload: >> emc_cache_init(&pmd->flow_cache); >> poll_cnt = pmd_load_queues(pmd, &poll_list, poll_cnt); >> @@ -2400,6 +2463,7 @@ reload: >> * reloading the updated configuration. */ >> dp_netdev_pmd_reload_done(pmd); >> >> + pmd_count_previous_cycles(pmd, PMD_CYCLES_OTHER); >> for (;;) { >> int i; >> >> @@ -2410,6 +2474,8 @@ reload: >> if (lc++ > 1024) { >> unsigned int seq; >> >> + pmd_count_previous_cycles(pmd, PMD_CYCLES_POLLING); >> + >> lc = 0; >> >> emc_cache_slow_sweep(&pmd->flow_cache); >> @@ -2420,6 +2486,7 @@ reload: >> port_seq = seq; >> break; >> } >> + >> } >> } >> >> @@ -2560,10 +2627,11 @@ dp_netdev_configure_pmd(struct dp_netdev_pmd_thread >> *pmd, struct dp_netdev *dp, >> ovs_mutex_init(&pmd->flow_mutex); >> dpcls_init(&pmd->cls); >> cmap_init(&pmd->flow_table); >> - /* init the 'flow_cache' since there is no >> + /* init the 'flow_cache' and cycles counter since there is no >> * actual thread created for NON_PMD_CORE_ID. */ >> if (core_id == NON_PMD_CORE_ID) { >> emc_cache_init(&pmd->flow_cache); >> + pmd_cycles_counter_diff(pmd); >> } >> cmap_insert(&dp->poll_threads, CONST_CAST(struct cmap_node *, >> &pmd->node), >> hash_int(core_id, 0)); >> -- >> 2.1.4 >> >> _______________________________________________ >> dev mailing list >> dev@openvswitch.org >> https://urldefense.proofpoint.com/v2/url?u=http-3A__openvswitch.org_mailman_listinfo_dev&d=AwIBaQ&c=Sqcl0Ez6M0X8aeM67LKIiDJAXVeAw-YihVMNtXt-uEs&r=SmB5nZacmXNq0gKCC1s_Cw5yUNjxgD4v5kJqZ2uWLlE&m=O2xV3f5YqpCBKEdlKnAo-_sNJe8evyjjTmi2S350aEI&s=EOHmUygNwnjosNJFaEvu1OHdALwwtjaL5rMeOiVVVzM&e= >> _______________________________________________ dev mailing list dev@openvswitch.org http://openvswitch.org/mailman/listinfo/dev