Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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

Open
EvanLai88 wants to merge3 commits intonfstream:master
base:master
Choose a base branch
Loading
fromEvanLai88:performance-report

Conversation

@EvanLai88
Copy link

Customizable Performance Report

Description

  1. Addreceived,dropped_by_interface fromstruct nf_stat toNFStreamer's performance report
  2. Add a new classPerformanceStats inutils.py and makeupdate_performances() into its own method.

Customize performance report by inheritingPerformanceStats and overrideupdate_performances()

Related#147

Type of change

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

How Has This Been Tested?

Test Configuration:

  • OS version: Ubuntu 22.04.2 LTS
  • Python version: 3.11.0rc1
  • Hardware: Proxmox VE virtual machine on i3-8350k, 16GB ram.

Example code:

fromnfstreamimportNFStreamerfromnfstream.utilsimportPerformanceStatsclassCustomStats(PerformanceStats):defupdate_performances(self):received=0drops=0drops_if=0processed=0ignored=0formeterinself.performances:received+=meter["received"].valuedrops+=meter["dropped"].valuedrops_if+=meter["dropped_if"].valueignored+=meter["ignored"].valueprocessed+=meter["processed"].valueprint("received: {}, drop: {}, drop_if: {}, ignored: {}, processed: {}, debt: {}".format(received,drops,drops_if,ignored,processed,received- (drops+drops_if+ignored+processed),            )        )defmain():# streamer_default_logs = NFStreamer(#     source="ens18",#     idle_timeout=5,#     n_meters=2,#     performance_report=1,# )streamer_custom_logs=NFStreamer(source="ens18",idle_timeout=5,n_meters=2,performance_report=1,performance_stats=CustomStats,    )forflowinstreamer_custom_logs:passif__name__=="__main__":main()

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:

received: 0, drop: 0, drop_if: 0, ignored: 0, processed: 0, debt: 0received: 1, drop: 0, drop_if: 0, ignored: 0, processed: 1, debt: 0received: 5, drop: 0, drop_if: 0, ignored: 0, processed: 5, debt: 0received: 8, drop: 0, drop_if: 0, ignored: 0, processed: 7, debt: 1received: 14, drop: 0, drop_if: 0, ignored: 0, processed: 13, debt: 1received: 20, drop: 0, drop_if: 0, ignored: 0, processed: 19, debt: 1received: 22, drop: 0, drop_if: 0, ignored: 0, processed: 21, debt: 1received: 24, drop: 0, drop_if: 0, ignored: 0, processed: 23, debt: 1received: 26, drop: 0, drop_if: 0, ignored: 0, processed: 25, debt: 1received: 33, drop: 0, drop_if: 0, ignored: 0, processed: 31, debt: 2received: 38, drop: 0, drop_if: 0, ignored: 0, processed: 37, debt: 1...

Checklist:

  • My code follows the style guidelines of this project
  • I have performed a self-review of my own code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • Any dependent changes have been merged and published in downstream modules
  • I have checked my code and corrected any misspellings

@EvanLai88
Copy link
Author

EvanLai88 commentedMar 9, 2023
edited
Loading

Currently, my implementation stored each performance stat in a dictionary.

Edit: just noticed thatmeter_workflow() updates perf every second.

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 classPerformanceStats, and classPerf ?

class
classPerf: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 code
fromtimeimporttime_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

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

1 participant

@EvanLai88

[8]ページ先頭

©2009-2025 Movatter.jp