Skip to content

Commit 7cee1b9

Browse files
geyslanrscampos
authored andcommitted
chore!: rollback proctree to simple LRU (#4299)
The expirable LRU cache is not intended to be used in the ProcessTree type since the TTL would impact its correctness on some scenarios. Despite TTL can be disabled by setting it to 0, it is not a good idea due to the potential performance impact of its implementation. See the comparison between the simple LRU and the expirable LRU below: | Benchmark | Exp LRU | Simple | % | | | TTL 0 | LRU | Impr. | | | (ns/op) | (ns/op) | * | |----------------------------------------|---------|---------|--------| | GetProcessByHash-Concurrency1 | 4.264 | 6.301 | -47.8% | | GetProcessByHash-Concurrency2 | 14.91 | 19.85 | -33.2% | | GetProcessByHash-Concurrency4 | 74.03 | 63.22 | 14.6% | | GetProcessByHash-Concurrency8 | 247.2 | 174.7 | 29.3% | | GetOrCreateProcessByHash-Concurrency1 | 37.02 | 8.370 | 77.4% | | GetOrCreateProcessByHash-Concurrency2 | 80.84 | 23.37 | 71.1% | | GetOrCreateProcessByHash-Concurrency4 | 181.6 | 75.67 | 58.4% | | GetOrCreateProcessByHash-Concurrency8 | 408.3 | 194.5 | 52.4% | | GetThreadByHash-Concurrency1 | 38.13 | 7.675 | 79.9% | | GetThreadByHash-Concurrency2 | 79.98 | 22.71 | 71.6% | | GetThreadByHash-Concurrency4 | 177.1 | 60.76 | 65.7% | | GetThreadByHash-Concurrency8 | 403.2 | 190.0 | 52.9% | | GetOrCreateThreadByHash-Concurrency1 | 38.16 | 7.996 | 79.0% | | GetOrCreateThreadByHash-Concurrency2 | 79.82 | 23.73 | 70.3% | | GetOrCreateThreadByHash-Concurrency4 | 177.1 | 67.13 | 62.1% | | GetOrCreateThreadByHash-Concurrency8 | 405.1 | 151.3 | 62.7% | Therefore, this commit reverts the ProcessTree to use the simple LRU cache until a better solution is designed. * Part of the performance improvement is also due to the removal of the outer lock done by 44e59d3. commit: 34be604 (main), cherry-pick
1 parent 8d6f034 commit 7cee1b9

File tree

7 files changed

+19
-79
lines changed

7 files changed

+19
-79
lines changed

docs/docs/install/config/index.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,6 @@ proctree:
1616
cache:
1717
process: 8192
1818
thread: 4096
19-
cache-ttl:
20-
process: 60
21-
thread: 60
2219

2320
capabilities:
2421
bypass: false

docs/docs/policies/usage/cli.md

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,9 +67,6 @@ proctree:
6767
cache:
6868
process: 8192
6969
thread: 8192
70-
cache-ttl:
71-
process: 120
72-
thread: 120
7370
# cri:
7471
# - runtime:
7572
# name: docker

examples/config/global_config.yaml

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,6 @@ proctree:
88
# cache:
99
# process: 8192
1010
# thread: 4096
11-
# cache-ttl:
12-
# process: 120
13-
# thread: 120
1411

1512
capabilities:
1613
bypass: false

pkg/cmd/cobra/config.go

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -173,21 +173,15 @@ func (c *RegoConfig) flags() []string {
173173
//
174174

175175
type ProcTreeConfig struct {
176-
Source string `mapstructure:"source"`
177-
Cache ProcTreeCacheConfig `mapstructure:"cache"`
178-
CacheTTL ProcTreeCacheTTLConfig `mapstructure:"cache-ttl"`
176+
Source string `mapstructure:"source"`
177+
Cache ProcTreeCacheConfig `mapstructure:"cache"`
179178
}
180179

181180
type ProcTreeCacheConfig struct {
182181
Process int `mapstructure:"process"`
183182
Thread int `mapstructure:"thread"`
184183
}
185184

186-
type ProcTreeCacheTTLConfig struct {
187-
Process int `mapstructure:"process"`
188-
Thread int `mapstructure:"thread"`
189-
}
190-
191185
func (c *ProcTreeConfig) flags() []string {
192186
flags := make([]string, 0)
193187

@@ -204,12 +198,6 @@ func (c *ProcTreeConfig) flags() []string {
204198
if c.Cache.Thread != 0 {
205199
flags = append(flags, fmt.Sprintf("thread-cache=%d", c.Cache.Thread))
206200
}
207-
if c.CacheTTL.Process != 0 {
208-
flags = append(flags, fmt.Sprintf("process-cache-ttl=%d", c.CacheTTL.Process))
209-
}
210-
if c.CacheTTL.Thread != 0 {
211-
flags = append(flags, fmt.Sprintf("thread-cache-ttl=%d", c.CacheTTL.Thread))
212-
}
213201

214202
return flags
215203
}

pkg/cmd/cobra/config_test.go

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -97,17 +97,12 @@ proctree:
9797
cache:
9898
process: 8192
9999
thread: 4096
100-
cache-ttl:
101-
process: 5
102-
thread: 10
103100
`,
104101
key: "proctree",
105102
expectedFlags: []string{
106103
"source=events",
107104
"process-cache=8192",
108105
"thread-cache=4096",
109-
"process-cache-ttl=5",
110-
"thread-cache-ttl=10",
111106
},
112107
},
113108
{
@@ -596,20 +591,6 @@ func TestProcTreeConfigFlags(t *testing.T) {
596591
"thread-cache=4096",
597592
},
598593
},
599-
{
600-
name: "process cache ttl set",
601-
config: ProcTreeConfig{
602-
Source: "",
603-
CacheTTL: ProcTreeCacheTTLConfig{
604-
Process: 5,
605-
Thread: 10,
606-
},
607-
},
608-
expected: []string{
609-
"process-cache-ttl=5",
610-
"thread-cache-ttl=10",
611-
},
612-
},
613594
{
614595
name: "all fields set",
615596
config: ProcTreeConfig{

pkg/cmd/flags/proctree.go

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import (
44
"fmt"
55
"strconv"
66
"strings"
7-
"time"
87

98
"github.com/aquasecurity/tracee/pkg/logger"
109
"github.com/aquasecurity/tracee/pkg/proctree"
@@ -21,8 +20,6 @@ Example:
2120
both | process tree is built from both events and signals.
2221
--proctree process-cache=8192 | will cache up to 8192 processes in the tree (LRU cache).
2322
--proctree thread-cache=4096 | will cache up to 4096 threads in the tree (LRU cache).
24-
--proctree process-cache-ttl=60 | will set the process cache element TTL to 60 seconds.
25-
--proctree thread-cache-ttl=60 | will set the thread cache element TTL to 60 seconds.
2623
--proctree disable-procfs-query | Will disable procfs queries during runtime
2724
2825
Use comma OR use the flag multiple times to choose multiple options:
@@ -38,8 +35,6 @@ func PrepareProcTree(cacheSlice []string) (proctree.ProcTreeConfig, error) {
3835
Source: proctree.SourceNone, // disabled by default
3936
ProcessCacheSize: proctree.DefaultProcessCacheSize,
4037
ThreadCacheSize: proctree.DefaultThreadCacheSize,
41-
ProcessCacheTTL: proctree.DefaultProcessCacheTTL,
42-
ThreadCacheTTL: proctree.DefaultThreadCacheTTL,
4338
ProcfsInitialization: true,
4439
ProcfsQuerying: true,
4540
}
@@ -98,24 +93,6 @@ func PrepareProcTree(cacheSlice []string) (proctree.ProcTreeConfig, error) {
9893
cacheSet = true
9994
continue
10095
}
101-
if strings.HasPrefix(value, "process-cache-ttl=") {
102-
num := strings.TrimPrefix(value, "process-cache-ttl=")
103-
ttl, err := strconv.Atoi(num)
104-
if err != nil {
105-
return config, err
106-
}
107-
config.ProcessCacheTTL = time.Duration(ttl) * time.Second
108-
continue
109-
}
110-
if strings.HasPrefix(value, "thread-cache-ttl=") {
111-
num := strings.TrimPrefix(value, "thread-cache-ttl=")
112-
ttl, err := strconv.Atoi(num)
113-
if err != nil {
114-
return config, err
115-
}
116-
config.ThreadCacheTTL = time.Duration(ttl) * time.Second
117-
continue
118-
}
11996
if strings.HasPrefix(value, "disable-procfs-query") {
12097
config.ProcfsQuerying = false
12198
continue

pkg/proctree/proctree.go

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@ import (
55
"sync"
66
"time"
77

8-
"github.com/hashicorp/golang-lru/v2/expirable"
8+
lru "github.com/hashicorp/golang-lru/v2"
99

10+
"github.com/aquasecurity/tracee/pkg/errfmt"
1011
"github.com/aquasecurity/tracee/pkg/logger"
1112
traceetime "github.com/aquasecurity/tracee/pkg/time"
1213
)
@@ -68,19 +69,17 @@ type ProcTreeConfig struct {
6869
Source SourceType
6970
ProcessCacheSize int
7071
ThreadCacheSize int
71-
ProcessCacheTTL time.Duration
72-
ThreadCacheTTL time.Duration
7372
ProcfsInitialization bool // Determine whether to scan procfs data for process tree initialization
7473
ProcfsQuerying bool // Determine whether to query procfs for missing information during runtime
7574
}
7675

7776
// ProcessTree is a tree of processes and threads.
7877
type ProcessTree struct {
79-
processes *expirable.LRU[uint32, *Process] // hash -> process
80-
threads *expirable.LRU[uint32, *Thread] // hash -> threads
81-
procfsChan chan int // channel of pids to read from procfs
82-
procfsOnce *sync.Once // busy loop debug message throttling
83-
ctx context.Context // context for the process tree
78+
processes *lru.Cache[uint32, *Process] // hash -> process
79+
threads *lru.Cache[uint32, *Thread] // hash -> threads
80+
procfsChan chan int // channel of pids to read from procfs
81+
procfsOnce *sync.Once // busy loop debug message throttling
82+
ctx context.Context // context for the process tree
8483
procfsQuery bool
8584
timeNormalizer traceetime.TimeNormalizer
8685
}
@@ -91,22 +90,26 @@ func NewProcessTree(ctx context.Context, config ProcTreeConfig, timeNormalizer t
9190
thrEvicted := 0
9291

9392
// Create caches for processes.
94-
processes := expirable.NewLRU[uint32, *Process](
93+
processes, err := lru.NewWithEvict[uint32, *Process](
9594
config.ProcessCacheSize,
96-
func(k uint32, v *Process) {
95+
func(uint32, *Process) {
9796
procEvited++
9897
},
99-
config.ProcessCacheTTL,
10098
)
99+
if err != nil {
100+
return nil, errfmt.WrapError(err)
101+
}
101102

102103
// Create caches for threads.
103-
threads := expirable.NewLRU[uint32, *Thread](
104+
threads, err := lru.NewWithEvict[uint32, *Thread](
104105
config.ThreadCacheSize,
105-
func(k uint32, v *Thread) {
106+
func(uint32, *Thread) {
106107
thrEvicted++
107108
},
108-
config.ThreadCacheTTL,
109109
)
110+
if err != nil {
111+
return nil, errfmt.WrapError(err)
112+
}
110113

111114
// Report cache stats if debug is enabled.
112115
go func() {

0 commit comments

Comments
 (0)