Uh oh!
There was an error while loading.Please reload this page.
- Notifications
You must be signed in to change notification settings - Fork144
Customizable Performance Report#166
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.
Already on GitHub?Sign in to your account
base:master
Are you sure you want to change the base?
Uh oh!
There was an error while loading.Please reload this page.
Conversation
Add 2 performance stats in libpcap to NFStreamer, and warp them in a newclass `PerformanceStats`
EvanLai88 commentedMar 9, 2023 • edited
Loading Uh oh!
There was an error while loading.Please reload this page.
edited
Uh oh!
There was an error while loading.Please reload this page.
Currently, my implementation stored each performance stat in a dictionary. Edit: just noticed that After a little bit of testing, if using a class instead of dictionary, it can be easier for people to implement custom stats (hint from class member vs dictionary key) with very little performance impact. btw, are there better names for class classclassPerf:def__init__(self,context)->None:self._received=context.Value("I",0)self._dropped=context.Value("I",0)self._dropped_if=context.Value("I",0)self._processed=context.Value("I",0)self._ignored=context.Value("I",0)@propertydefreceived(self):returnself._received.value@received.setterdefreceived(self,value):self._received.value=value@propertydefdropped(self):returnself._dropped.value@dropped.setterdefdropped(self,value):self._dropped.value=value@propertydefdropped_if(self):returnself._dropped_if.value@dropped_if.setterdefdropped_if(self,value):self._dropped_if.value=value@propertydefprocessed(self):returnself._processed.value@processed.setterdefprocessed(self,value):self._processed.value=value@propertydefignored(self):returnself._ignored.value@ignored.setterdefignored(self,value):self._ignored.value=valueclassPerformanceStats:def__init__(self,n_meters,context,is_linux,flows_count)->None:self.is_linux=is_linuxself.flows_count=flows_countself.perfs= [Perf(context)for_inrange(n_meters)]def__getitem__(self,idx)->Perf:returnself.perfs[idx] test codefromtimeimporttime_nsfrommultiprocessingimportget_contextfromnfstream.utilsimportRepeatedTimerclassPerf:def__init__(self,context)->None:self._received=context.Value("I",0)self._dropped=context.Value("I",0)self._dropped_if=context.Value("I",0)self._processed=context.Value("I",0)self._ignored=context.Value("I",0)@propertydefreceived(self):returnself._received.value@received.setterdefreceived(self,value):self._received.value=value@propertydefdropped(self):returnself._dropped.value@dropped.setterdefdropped(self,value):self._dropped.value=value@propertydefdropped_if(self):returnself._dropped_if.value@dropped_if.setterdefdropped_if(self,value):self._dropped_if.value=value@propertydefprocessed(self):returnself._processed.value@processed.setterdefprocessed(self,value):self._processed.value=value@propertydefignored(self):returnself._ignored.value@ignored.setterdefignored(self,value):self._ignored.value=valueclassPerformanceStatsWithClass:def__init__(self,n_meters,context,is_linux,flows_count)->None:self.is_linux=is_linuxself.flows_count=flows_countself.perfs= [Perf(context)for_inrange(n_meters)]def__getitem__(self,idx)->Perf:returnself.perfs[idx]classPerformanceStatsWithDict:def__init__(self,n_meters,context,is_linux,flows_count)->None:self.is_linux=is_linuxself.flows_count=flows_countself.performances= []for_inrange(n_meters):self.performances.append( {"received":context.Value("I",0),"dropped":context.Value("I",0),"dropped_if":context.Value("I",0),"processed":context.Value("I",0),"ignored":context.Value("I",0), } )def__getitem__(self,idx)->dict:returnself.performances[idx]defupdate_perf(perf:Perf|dict):ifisinstance(perf,dict):foriinrange(1_000_000):print(i,end="\r")perf["received"].value+=1perf["dropped"].value+=2perf["dropped_if"].value+=3perf["processed"].value+=4perf["ignored"].value+=5print(perf["received"].value,perf["dropped"].value,perf["dropped_if"].value,perf["processed"].value,perf["ignored"].value, )elifisinstance(perf,Perf):foriinrange(1_000_000):print(i,end="\r")perf.received+=1perf.dropped+=2perf.dropped_if+=3perf.processed+=4perf.ignored+=5print(perf.received,perf.dropped,perf.dropped_if,perf.processed,perf.ignored, )defwatch(perfs:list[Perf|dict]):ifisinstance(perfs[0],dict):forpinperfs:a=p["received"].valuea=p["dropped"].valuea=p["dropped_if"].valuea=p["processed"].valuea=p["ignored"].valueelifisinstance(perfs[0],Perf):forpinperfs:a=p.receiveda=p.droppeda=p.dropped_ifa=p.processeda=p.ignoreddeftime_func(func):defwapper(n_meters):start=time_ns()func(n_meters)print(f"{(time_ns()-start)/(10**9)} seconds")returnwapper@time_funcdeftest_class(n_meters):print("class")ctx=get_context()meters= []p=PerformanceStatsWithClass(n_meters,ctx,True,0)foriinrange(n_meters):meters.append(ctx.Process(target=update_perf,args=(p[i],)))rt=RepeatedTimer(0.001,watch,p)formeterinmeters:meter.start()foriinrange(n_meters):ifmeters[i].is_alive():meters[i].join()rt.stop()@time_funcdeftest_dict(n_meters):print("dict")ctx=get_context()meters= []p=PerformanceStatsWithDict(n_meters,ctx,True,0)foriinrange(n_meters):meters.append(ctx.Process(target=update_perf,args=(p[i],)))rt=RepeatedTimer(0.001,watch,p)formeterinmeters:meter.start()foriinrange(n_meters):ifmeters[i].is_alive():meters[i].join()rt.stop()if__name__=="__main__":test_class(4)test_dict(4) writing to context.Value 1,000,000 time while reading from it every 0.01 seconds class1000000 2000000 3000000 4000000 50000001000000 2000000 3000000 4000000 50000001000000 2000000 3000000 4000000 50000001000000 2000000 3000000 4000000 500000011.975047249 secondsdict1000000 2000000 3000000 4000000 50000001000000 2000000 3000000 4000000 50000001000000 2000000 3000000 4000000 50000001000000 2000000 3000000 4000000 500000011.891510533 seconds |
Customizable Performance Report
Description
received,dropped_by_interfacefromstruct nf_stattoNFStreamer's performance reportPerformanceStatsinutils.pyand makeupdate_performances()into its own method.Customize performance report by inheriting
PerformanceStatsand overrideupdate_performances()Related#147
Type of change
How Has This Been Tested?
Test Configuration:
Example code:
default log output:
{"flows_expired": 0,"packets_received": 0,"packets_processed": 0,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 0]}{"flows_expired": 0,"packets_received": 8,"packets_processed": 1,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 1]}{"flows_expired": 0,"packets_received": 14,"packets_processed": 10,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 10]}{"flows_expired": 0,"packets_received": 36,"packets_processed": 15,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 15]}{"flows_expired": 0,"packets_received": 69,"packets_processed": 43,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 43]}{"flows_expired": 0,"packets_received": 104,"packets_processed": 102,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 102]}{"flows_expired": 0,"packets_received": 109,"packets_processed": 108,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 108]}{"flows_expired": 0,"packets_received": 114,"packets_processed": 113,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 113]}{"flows_expired": 0,"packets_received": 116,"packets_processed": 115,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 115]}{"flows_expired": 0,"packets_received": 124,"packets_processed": 119,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 119]}{"flows_expired": 0,"packets_received": 132,"packets_processed": 129,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 129]}{"flows_expired": 0,"packets_received": 136,"packets_processed": 135,"packets_ignored": 0,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 135]}{"flows_expired": 0,"packets_received": 141,"packets_processed": 139,"packets_ignored": 1,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 139]}{"flows_expired": 0,"packets_received": 143,"packets_processed": 141,"packets_ignored": 1,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 141]}{"flows_expired": 0,"packets_received": 151,"packets_processed": 143,"packets_ignored": 1,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 143]}{"flows_expired": 0,"packets_received": 155,"packets_processed": 151,"packets_ignored": 1,"packets_dropped_filtered_by_kernel": 0,"packets_dropped_filtered_by_interface": 0,"meters_packets_processing_balance": [0, 151]}...custom log output:
Checklist: