Hi All, I was experimenting with the perf utils scripts and I noticed that the netdev-times.py was really slow. I modified the python script to run Python profiling and found that a lot of time was spent in the handle_skb_copy_datagram_iovec because there can be many many possible entries in rx_skb_list and the code did a linear search through the possible matches. Python dictionaries use hashing and could be much faster. I modified rx_skb_list to be a dictionary and the runtime for my example went from 5 minutes down to 11 seconds.
The attached patch shows the changes. I compared the output between the original perf script and the patched on; there were 8 lines that differed (as shown below), so there is still something not quite correct in the patch. The output should be identical. Comments and feedback would be appreciated on this patch. -Will [wcohen@santana profiling]$ diff -u /tmp/original /tmp/improved |more --- /tmp/original 2014-06-12 21:49:51.475501535 -0400 +++ /tmp/improved 2014-06-12 21:44:35.942703446 -0400 @@ -985,8 +985,6 @@ softirq_entry(+0.010msec) | |---netif_receive_skb(+0.021msec skb=ffff8803d7d79500 len=50) - | | - | skb_copy_datagram_iovec(+138.745msec 4574:gnome-shell) | |---netif_receive_skb(+0.044msec skb=ffff8803d7d79500 len=72) | | @@ -1011,8 +1009,6 @@ softirq_entry(+0.010msec) | |---netif_receive_skb(+0.021msec skb=ffff8803b0c25e00 len=50) - | | - | skb_copy_datagram_iovec(+37.385msec 6044:gnome-terminal-) | napi_poll_exit(+0.047msec em1) @@ -1676,8 +1672,6 @@ softirq_entry(+0.007msec) | |---netif_receive_skb(+0.017msec skb=ffff8803d704ff00 len=52) - | | - | skb_copy_datagram_iovec(+556.930msec 1301:Xorg) | napi_poll_exit(+0.067msec em1) @@ -2475,8 +2469,6 @@ |---netif_receive_skb(+0.026msec skb=ffff8803b104a800 len=52) | |---netif_receive_skb(+0.108msec skb=ffff8803b104a800 len=52) - | | - | skb_copy_datagram_iovec(+64.266msec 1301:Xorg) | napi_poll_exit(+0.125msec em1)
--- /usr/libexec/perf-core/scripts/python/netdev-times.py 2014-06-07 21:33:33.000000000 -0400 +++ /home/wcohen/libexec/perf-core/scripts/python/netdev-times.py 2014-06-13 09:46:03.809403435 -0400 @@ -23,7 +23,7 @@ net_rx_dic = {}; # key is cpu and value include time of NET_RX softirq-entry # and a list which stacks receive receive_hunk_list = []; # a list which include a sequence of receive events -rx_skb_list = []; # received packet list for matching +rx_skb_list = {}; # received packet list for matching # skb_copy_datagram_iovec buffer_budget = 65536; # the budget of rx_skb_list, tx_queue_list and @@ -387,9 +387,9 @@ 'event_t':time, 'skbaddr':skbaddr, 'len':skblen} event_list = net_rx_dic[cpu]['event_list'] event_list.append(rec_data) - rx_skb_list.insert(0, rec_data) - if len(rx_skb_list) > buffer_budget: - rx_skb_list.pop() + if len(rx_skb_list) < buffer_budget: + rx_skb_list[skbaddr] = rec_data + else: of_count_rx_skb_list += 1 def handle_net_dev_queue(event_info): @@ -435,13 +435,11 @@ tx_free_list.append(skb) del tx_xmit_list[i] return - for i in range(len(rx_skb_list)): - rec_data = rx_skb_list[i] - if rec_data['skbaddr'] == skbaddr: - rec_data.update({'handle':"kfree_skb", - 'comm':comm, 'pid':pid, 'comm_t':time}) - del rx_skb_list[i] - return + if skbaddr in rx_skb_list.keys(): + rx_skb_list[skbaddr].update({'handle':"kfree_skb", + 'comm':comm, 'pid':pid, 'comm_t':time}) + del rx_skb_list[skbaddr] + return def handle_consume_skb(event_info): (name, context, cpu, time, pid, comm, skbaddr) = event_info @@ -455,10 +453,8 @@ def handle_skb_copy_datagram_iovec(event_info): (name, context, cpu, time, pid, comm, skbaddr, skblen) = event_info - for i in range(len(rx_skb_list)): - rec_data = rx_skb_list[i] - if skbaddr == rec_data['skbaddr']: - rec_data.update({'handle':"skb_copy_datagram_iovec", - 'comm':comm, 'pid':pid, 'comm_t':time}) - del rx_skb_list[i] - return + if skbaddr in rx_skb_list.keys(): + rx_skb_list[skbaddr].update({'handle':"skb_copy_datagram_iovec", + 'comm':comm, 'pid':pid, 'comm_t':time}) + del rx_skb_list[skbaddr] + return