-
Notifications
You must be signed in to change notification settings - Fork 394
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
Improve performance of exec-hash #3752
Improve performance of exec-hash #3752
Conversation
6dade93
to
c2ebbb2
Compare
c2ebbb2
to
3231fef
Compare
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.
Small things
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.
LGTM. It is missing some public methods documentation lines, but other than that (and minors from Alon) I think we're good to merge. Also, nice job in using SIMD optimized SHA package, it has multiple x86 flavors (SSE, ...) and arm as well (I wonder if it supports SVE extensions in arm, would make it super fast).
It demonstrate that the current algorithm of addBucketItem with multiple lock/unlock) is optimal compared to a single lock/unlock. goos: linux goarch: amd64 pkg: github.com/aquasecurity/tracee/pkg/bucketscache cpu: 12th Gen Intel(R) Core(TM) i7-12700H BenchmarkAddBucketItemCurrent-20 464 2586038 ns/op 2118 B/op 5 allocs/op BenchmarkAddBucketItemWithOneLock-20 122 9461730 ns/op 424 B/op 1 allocs/op
GetBucket was not thread safe since it was returning a reference to a bucket instead of its copy.
First call to getFileHash() for a given filename was returning an empty string. Context: aquasecurity#3745
Improve the computeFileHash function, by using minio/sha256-simd. Benchmarking indicates the current implementation is nearly three times faster than the old version (21,311 ns/op vs. 61,857 ns/op) while maintaining similar memory efficiency (33,040 B/op vs. 33,056 B/op) and the same number of memory allocations per operation (5 allocs/op). goos: linux goarch: amd64 pkg: github.com/aquasecurity/tracee/pkg/ebpf cpu: 12th Gen Intel(R) Core(TM) i7-12700H BenchmarkComputeFileHashOld-20 19257 61857 ns/op 33056 B/op 5 allocs/op BenchmarkComputeFileHashCurrent-20 56769 21311 ns/op 33040 B/op 5 allocs/op
The user can now choose between the following options: - none (default) - inode - dev-inode - digest-inode 'inode' option recalculates the file hash if the inode's creation time (ctime) differs, which can occur in different namespaces even for identical pathnames. 'dev-inode' option generally offers better performance compared to the pathname option, as it bypasses the need for recalculation by associating the creation time (ctime) with the device (dev) and inode pair. 'digest-inode' option is the most efficient, as it keys the hash to a pair consisting of the container image digest and inode. This approach, however, necessitates container enrichment. Code related to executable hashing was opportunistically refactored and moved to its own package. Co-authored-by: Geyslan Gregório <geyslan@gmail.com>
Previous implementation of sha256 hash computation used io.Copy. This method would allocate small buffers as needed when copying the file content into the hash digest. The result would be more allocations and more GC calls. Mitigate this by using one large buffer and clearing it per call. Benchmark results: goos: linux goarch: amd64 pkg: github.com/aquasecurity/tracee/pkg/exechash cpu: AMD EPYC 7571 BenchmarkComputeFileHashOld-8 18355 65371 ns/op 33056 B/op 5 allocs/op BenchmarkComputeFileHashCurrent-8 30561 41714 ns/op 272 B/op 4 allocs/op
3231fef
to
9b56ded
Compare
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.
I didn't do a full review, but left a couple of comments about the doc file
@@ -48,7 +48,10 @@ Other options: | |||
- **exec-env**: When tracing execve/execveat, show the environment variables that were used for execution. | |||
- **relative-time**: Use relative timestamp instead of wall timestamp for events. | |||
- **exec-hash**: When tracing some file related events, show the file hash (sha256). | |||
- Affected events: sched_process_exec, shared_object_loaded | |||
- Affected events: *sched_process_exec*, *shared_object_loaded* | |||
- **inode** option recalculates the file hash if the inode's creation time (ctime) differs, which can occur in different namespaces even for identical inode. This option is performant, but not recommended and should only be used if container enrichment can't be enabled for digest-inode, and if performance is preffered over correctness. |
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.
Ctime is inode change time, not creation time
- Affected events: sched_process_exec, shared_object_loaded | ||
- Affected events: *sched_process_exec*, *shared_object_loaded* | ||
- **inode** option recalculates the file hash if the inode's creation time (ctime) differs, which can occur in different namespaces even for identical inode. This option is performant, but not recommended and should only be used if container enrichment can't be enabled for digest-inode, and if performance is preffered over correctness. | ||
- **dev-inode** option generally offers better performance compared to the **inode** option, as it bypasses the need for recalculation by associating the creation time (ctime) with the device (dev) and inode pair. It's recommended if correctness is preffered over performance without container enrichment. |
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.
You say this option offers better performance, while on the end of this sentence it says that this option is more for correctness, and not performance. This is confusing
1. Explain what the PR does
c2ebbb2 feat(exechash): optimize hash by reusing buffer
9f9e5a4 feat(ebpf): expand exec-hash output option
eb17fc6 feat(ebpf): optimize computeFileHash
db51e0b fix(ebpf): fix getFileHash()
c469486 fix(bucketscache): GetBucket was not thread safe
041bcff chore(bucketscache): add benchmark
2. Explain how to test it
Added tests to confirm parity with previous hash functionality.
Can be manually tested by using:
tracee -o option:exec-hash={inode|dev-inode|digest-inode}
where you may choose which hash option you want, with varying degrees of accuracy and performance.
Close #3734
Close #3745