-
Notifications
You must be signed in to change notification settings - Fork 569
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
profile infrastructure #828
Merged
Merged
Changes from 15 commits
Commits
Show all changes
20 commits
Select commit
Hold shift + click to select a range
ed3bd4e
main: add timing ctx manager
williballenthin f982360
main: add coarse timing measurements
williballenthin 3d068fe
scripts: add utilities for collecting profile traces
williballenthin 86cab26
add perf counters in module capa.perf
williballenthin 6524449
main: perf: human format the numbers
williballenthin 3a12472
perf: render: show evaluate.feature counter
williballenthin 702d00d
gitignore
williballenthin 0629c58
common: move Result to capa.common from capa.engine
williballenthin 5770d0c
perf: add reset routine
williballenthin a35be4a
scripts: add py script for profiling time
williballenthin 70f0075
pep8
williballenthin b621205
mypy
williballenthin f598acb
scripts: remove old profiling scripts
williballenthin 26b7a0b
Merge branch 'master' into profiling
williballenthin 6c8d246
fix bad merge
williballenthin 334425a
changelog
williballenthin 6f6831f
perf: document that counters is unstable
williballenthin 2abebfb
main: remove perf messages
williballenthin 18c30e4
main: remove perf debug msgs
williballenthin 7a4aee5
profile-time: add doc
williballenthin File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
import collections | ||
from typing import Dict | ||
|
||
counters: Dict[str, int] = collections.Counter() | ||
|
||
|
||
def reset(): | ||
global counters | ||
counters = collections.Counter() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
import sys | ||
williballenthin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
import timeit | ||
import logging | ||
import argparse | ||
import subprocess | ||
|
||
import tqdm | ||
import tabulate | ||
|
||
import capa.main | ||
import capa.perf | ||
import capa.rules | ||
import capa.engine | ||
import capa.helpers | ||
import capa.features | ||
import capa.features.common | ||
import capa.features.freeze | ||
|
||
logger = logging.getLogger("capa.profile") | ||
|
||
|
||
def main(argv=None): | ||
if argv is None: | ||
argv = sys.argv[1:] | ||
|
||
label = subprocess.run( | ||
"git show --pretty=oneline --abbrev-commit | head -n 1", shell=True, capture_output=True, text=True | ||
).stdout.strip() | ||
is_dirty = ( | ||
subprocess.run( | ||
"git status | grep 'modified: ' | grep -v 'rules' | grep -v 'tests/data'", | ||
shell=True, | ||
capture_output=True, | ||
text=True, | ||
).stdout | ||
!= "" | ||
) | ||
|
||
if is_dirty: | ||
label += " (dirty)" | ||
|
||
parser = argparse.ArgumentParser(description="Profile capa performance") | ||
capa.main.install_common_args(parser, wanted={"format", "sample", "signatures", "rules"}) | ||
|
||
parser.add_argument("--number", type=int, default=3, help="batch size of profile collection") | ||
parser.add_argument("--repeat", type=int, default=30, help="batch count of profile collection") | ||
parser.add_argument("--label", type=str, default=label, help="description of the profile collection") | ||
|
||
args = parser.parse_args(args=argv) | ||
capa.main.handle_common_args(args) | ||
|
||
try: | ||
taste = capa.helpers.get_file_taste(args.sample) | ||
except IOError as e: | ||
logger.error("%s", str(e)) | ||
return -1 | ||
|
||
try: | ||
with capa.main.timing("load rules"): | ||
rules = capa.rules.RuleSet(capa.main.get_rules(args.rules, disable_progress=True)) | ||
except (IOError) as e: | ||
logger.error("%s", str(e)) | ||
return -1 | ||
|
||
try: | ||
sig_paths = capa.main.get_signatures(args.signatures) | ||
except (IOError) as e: | ||
logger.error("%s", str(e)) | ||
return -1 | ||
|
||
if (args.format == "freeze") or (args.format == "auto" and capa.features.freeze.is_freeze(taste)): | ||
with open(args.sample, "rb") as f: | ||
extractor = capa.features.freeze.load(f.read()) | ||
else: | ||
extractor = capa.main.get_extractor( | ||
args.sample, args.format, capa.main.BACKEND_VIV, sig_paths, should_save_workspace=False | ||
) | ||
|
||
with tqdm.tqdm(total=args.number * args.repeat) as pbar: | ||
|
||
def do_iteration(): | ||
capa.perf.reset() | ||
capa.main.find_capabilities(rules, extractor, disable_progress=True) | ||
pbar.update(1) | ||
|
||
samples = timeit.repeat(do_iteration, number=args.number, repeat=args.repeat) | ||
|
||
logger.debug("perf: find capabilities: min: %0.2fs" % (min(samples) / float(args.number))) | ||
logger.debug("perf: find capabilities: avg: %0.2fs" % (sum(samples) / float(args.repeat) / float(args.number))) | ||
logger.debug("perf: find capabilities: max: %0.2fs" % (max(samples) / float(args.number))) | ||
williballenthin marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
for (counter, count) in capa.perf.counters.most_common(): | ||
logger.debug("perf: counter: {:}: {:,}".format(counter, count)) | ||
|
||
print( | ||
tabulate.tabulate( | ||
[ | ||
( | ||
args.label, | ||
"{:,}".format(capa.perf.counters["evaluate.feature"]), | ||
"%0.2fs" % (sum(samples) / float(args.repeat) / float(args.number)), | ||
"%0.2fs" % (min(samples) / float(args.number)), | ||
"%0.2fs" % (max(samples) / float(args.number)), | ||
) | ||
], | ||
headers=["label", "count(evaluations)", "avg(time)", "min(time)", "max(time)"], | ||
tablefmt="github", | ||
) | ||
) | ||
|
||
return 0 | ||
|
||
|
||
if __name__ == "__main__": | ||
sys.exit(main()) |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this will have a marginal performance impact itself. we can potentially remove these once our performance work is complete.