blob: f8d6706287f5bf42a8bf38d12b8cffabe8ce9cf7 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
# DTail Channel-less Read/Output Path (formerly "Turbo Boost")
## Overview
This document describes DTail's channel-less read/output path. It was originally
introduced as an opt-out "turbo boost" optimization, but it is now the single,
default processing path for all read/output operations. It improves performance
by using channel-less processing and optimized I/O. The on/off toggles described
in early revisions of this document (`DTAIL_TURBOBOOST_DISABLE`,
`DTAIL_CHANNELLESS_GREP`, `DTAIL_OPTIMIZED_READER`) have been removed; the
channel-less path is now unconditional.
## Problem Statement
The original dgrep implementation used multiple channels in a pipeline:
- `rawLines chan *bytes.Buffer` (buffer: 100) - Raw lines read from file
- `lines chan *line.Line` (buffer: 100) - Filtered lines to send to client
This created several performance issues:
1. Fixed channel buffer sizes causing blocking under high throughput
2. Context switching overhead between goroutines
3. Channel synchronization overhead
4. Memory allocations for channel operations
## Solution
The channel-less implementation replaces the channel pipeline with direct function calls using a `LineProcessor` interface.
### Key Components
1. **LineProcessor Interface** (`internal/io/line/processor.go`)
- Defines methods for processing lines without channels
- `ProcessLine()` - Handle a single line
- `Flush()` - Ensure buffered data is written
- `Close()` - Clean up resources
2. **GrepLineProcessor** (`internal/server/handlers/lineprocessor.go`)
- Implements LineProcessor for grep operations
- Writes directly to the network connection
- Uses internal buffering for efficiency (64KB buffer)
- Thread-safe with mutex protection
3. **Modified File Reading** (`internal/io/fs/readfile_processor.go`)
- `StartWithProcessor()` - Channel-less file reading
- Direct callbacks instead of channel sends
- Inline regex filtering without goroutines
4. **Optimized File Reading** (`internal/io/fs/readfile_processor_optimized.go`)
- Uses buffered line reading instead of byte-by-byte
- Custom scanner with 256KB buffer
- Efficient handling of long lines
- Special optimization for tail mode
### Feature Flags (historical — removed)
Early revisions gated this work behind opt-in environment variables
(`DTAIL_CHANNELLESS_GREP`, `DTAIL_OPTIMIZED_READER`). These no longer exist: the
channel-less, optimized read path is always on and cannot be toggled.
### Benefits
1. **Reduced Latency**: No channel queuing delays
2. **Lower Memory Usage**: No channel buffers
3. **Better CPU Efficiency**: Fewer context switches
4. **Simpler Code Flow**: Direct processing without goroutine coordination
5. **Predictable Performance**: No channel blocking
### Compatibility
- The original channel-based implementation has since been removed; the
channel-less path is the only one.
- Same command-line interface
- Protocol compatibility maintained
- All integration tests pass
### Performance Testing
Use the provided script to compare performance:
```bash
./test_channelless_performance.sh
```
This will test:
1. Original channel-based implementation
2. Channel-less implementation
3. Optimized channel-less implementation
### Usage
The channel-less path is always active; no environment variables are needed:
```bash
# Run dgrep normally — the channel-less, optimized path is used automatically
dgrep -regex "pattern" file.log
```
### Future Improvements
1. Extend channel-less approach to other commands (dcat, dtail)
2. Add configurable buffer sizes
3. Implement zero-copy optimizations
4. Add performance metrics collection
5. Consider using io_uring on Linux for async I/O
## Summary
The channel-less path is always on — there is no enable/disable switch. The
former `DTAIL_TURBOBOOST_DISABLE` environment variable and the
`Server.TurboBoostDisable` config field have been removed;
`DTAIL_TURBOBOOST_DISABLE` is now inert and an old config still carrying a
`TurboBoostDisable` key is silently ignored.
The path provides:
- Channel-less processing for grep and cat operations
- Optimized buffered I/O reader (256KB buffer)
- Buffer pooling to reduce memory allocations
|