Architecture
This document describes preheatโs internal architecture, including component design, data flow, and system interactions.
System Architecture Overview
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PREHEAT DAEMON โ
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ DAEMON โ โ CONFIG โ โ STATE โ โ LOGGING โ โ
โ โ CORE โ โ PARSER โ โ MANAGER โ โ SYSTEM โ โ
โ โ โ โ โ โ โ โ โ โ
โ โ Main loop โ โ INI parser โ โ Serialize โ โ File logger โ โ
โ โ Init/term โ โ Validation โ โ Persist โ โ Levels โ โ
โ โ Signals โ โ Defaults โ โ Load/save โ โ Rotation โ โ
โ โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ โโโโโโโโฌโโโโโโโ โ
โ โ โ โ โ โ
โ โโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโโ โ
โ โ SHARED DATA STRUCTURES โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ kp_state: Global state containing all application โ โ โ
โ โ โ data, Markov chains, and maps โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ MONITORING LAYER โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ โ โ โ โ โ
โ โ โ /proc reader โ โ Track app launches โ โ โ
โ โ โ Maps parser โ โ Update statistics โ โ โ
โ โ โ Process enum โ โ Manage exe entries โ โ โ
โ โ โโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ PROC SCANNER โ โ SPY MODULE โ โ โ
โ โ โ
โ โโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ PREDICTION LAYER โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ PROPHET MODULE โ โ โ
โ โ โ โ โ โ
โ โ โ Markov chain analysis โ โ โ
โ โ โ Correlation computation โ โ โ
โ โ โ Score calculation โ โ โ
โ โ โ Prediction generation โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโฌโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ READAHEAD LAYER โ โ
โ โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โ โ READAHEAD MODULE โ โ โ
โ โ โ โ โ โ
โ โ โ Memory budget calculation โ โ โ
โ โ โ File sorting (block/inode/path) โ โ โ
โ โ โ Parallel readahead workers โ โ โ
โ โ โ readahead(2) syscall wrapper โ โ โ
โ โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ โ
โผ โผ โผ
โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโโโโโโ
โ /proc โ โ Config โ โ State File โ
โ (read) โ โ File โ โ (read/write) โ
โโโโโโโโโโโ โโโโโโโโโโโ โโโโโโโโโโโโโโโโ
Core Components
Daemon Core (daemon/)
Files: main.c, daemon.c, signals.c
Responsibilities:
- Command-line argument parsing
- Daemonization (fork, setsid, chdir)
- Main event loop
- Signal handling (SIGHUP, SIGUSR1, SIGUSR2, SIGTERM)
- Graceful shutdown
Main Loop Pseudocode:
initialize()
load_config()
load_state()
while (running):
kp_spy_scan() # Monitor processes
kp_spy_update_model() # Update Markov chains
kp_prophet_predict() # Calculate predictions
kp_prophet_readahead() # Preload files
sleep(cycle_time)
save_state()
cleanup()
Configuration (config/)
Files: config.c, config.h, confkeys.h
Data Structure:
struct _kp_conf {
struct {
int cycle; // Scan interval
gboolean usecorrelation;
int minsize;
int memtotal, memfree, memcached;
} model;
struct {
gboolean doscan, dopredict;
int autosave;
char *mapprefix, *exeprefix;
int processes;
int sortstrategy;
} system;
struct {
gboolean enable_preheat_scoring;
double preheat_tool_boost;
} preheat;
};
State Management (state/)
Files: state.c, state.h
Whatโs Stored:
- Application registry (paths, sizes, launch counts)
- Memory maps for each application
- Markov chain nodes and transitions
- Bad executable list (failed opens)
Serialization Format:
[Header]
PREHEAT_STATE_V1
timestamp
[Executables]
exe_count
for each exe:
path, size, last_seen, launch_count
map_count
for each map:
path, offset, length
[Markov Chains]
markov_count
for each chain:
from_app, to_app, transition_count, probability
[Bad Exes]
bad_count
paths of unreadable executables
Monitoring Layer
Process Scanner (monitor/proc.c)
Function: kp_proc_scan()
Enumerates /proc to find running processes:
// Pseudocode
for each /proc/[pid]:
exe_path = readlink("/proc/[pid]/exe")
if exe_path matches exeprefix:
maps = parse("/proc/[pid]/maps")
for each map in maps:
if map.path matches mapprefix:
add_to_process_list(exe_path, map)
Maps File Format (/proc/[pid]/maps):
address perms offset dev inode pathname
7f1234560000-... r-xp 00000000 08:01 1234567 /usr/lib/libc.so
Spy Module (monitor/spy.c)
Functions: kp_spy_scan(), kp_spy_update_model()
Tracks application lifecycles:
- Detects new process launches
- Records application exits
- Updates Markov chain on transitions
Prediction Layer
Prophet Module (predict/prophet.c)
Functions: kp_prophet_predict(), kp_prophet_readahead()
Prediction Algorithm:
- Get running applications
- For each known application:
- Look up Markov transitions FROM running apps TO this app
- Calculate transition probability
- Apply correlation coefficient
- Compute final score
- Sort by score descending
- Return top N predictions
Score Calculation:
score = 0.0;
for each running_app:
p = markov_probability(running_app -> candidate_app)
if (usecorrelation):
p *= correlation(running_app, candidate_app)
score += p
// Normalize
score = log(score + EPSILON)
Markov Chain
Data Structure:
struct _kp_markov {
char *from_app; // Source application
GHashTable *transitions; // to_app -> count
int total_count; // Sum of all transitions
};
// Probability of transition A -> B
P(A->B) = count(A->B) / total_transitions_from(A)
Readahead Layer
Readahead Module (readahead/readahead.c)
Function: kp_readahead_file()
Process:
1. Check memory budget (meminfo)
2. Get predicted apps from prophet
3. Collect all files for predicted apps
4. Sort files by strategy (block/inode/path)
5. For each file:
fd = open(path, O_RDONLY)
readahead(fd, 0, file_size)
close(fd)
6. Track bytes preloaded
Sorting Implementation:
switch (sortstrategy):
case SORT_NONE:
// No sorting
case SORT_PATH:
qsort(files, by_path)
case SORT_INODE:
qsort(files, by_inode)
case SORT_BLOCK:
for each file:
block = get_block_number(fd)
qsort(files, by_block)
Getting Block Number (for HDD optimization):
// Uses FIBMAP ioctl
ioctl(fd, FIBMAP, &block_number)
Data Flow
Cycle Data Flow
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ONE CYCLE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Step 1: SCAN
/proc โโโโโโโโโโโโโโโโโโโโโโโโโโโโโ> Process List
read /proc/*/exe โ
read /proc/*/maps โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ Running Processes โ
โ + Their Maps โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
Step 2: LEARN โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ Compare with โ
โ Previous State โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
โญโโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโฎ
โ โ
New processes Exited processes
โ โ
โผ โผ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ Add to Markov โ โ Record exit โ
โ chain โ โ transition โ
โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ
โ โ
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ Updated State โ
โ (apps + Markov) โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
Step 3: PREDICT โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ Prophet: Score โ
โ all known apps โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ Ranked Prediction โ
โ List โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
Step 4: PRELOAD โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ Get files for โ
โ top predictions โ
โโโโโโโโโโโฌโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโ
โ readahead(2) โโโโโโโ> Disk Cache
โ each file โ
โโโโโโโโโโโโโโโโโโโโโ
File Structure
src/
โโโ daemon/
โ โโโ main.c # Entry point, argument parsing
โ โโโ daemon.c # Daemonization, main loop
โ โโโ signals.c # Signal handlers
โโโ config/
โ โโโ config.c # Configuration loading
โ โโโ config.h # Config structures
โ โโโ confkeys.h # Key name definitions
โโโ monitor/
โ โโโ proc.c # /proc filesystem scanner
โ โโโ proc.h
โ โโโ spy.c # Application tracker
โ โโโ spy.h
โโโ predict/
โ โโโ prophet.c # Prediction engine
โ โโโ prophet.h
โโโ readahead/
โ โโโ readahead.c # Preloading implementation
โ โโโ readahead.h
โโโ state/
โ โโโ state.c # State persistence
โ โโโ state.h
โโโ utils/
โโโ logging.c # Logging system
โโโ logging.h
External Dependencies
GLib
Preheat uses GLib for:
- Hash tables (
GHashTable) - Dynamic arrays (
GArray,GPtrArray) - String handling (
GString) - Main loop (optional)
- Memory management
System Interfaces
| Interface | Purpose |
|---|---|
/proc filesystem |
Process enumeration, maps |
readahead(2) |
Non-blocking file read |
ioctl(FIBMAP) |
Get file block numbers |
open/close |
File access |
signal(2) |
Signal handling |
fork/setsid |
Daemonization |
Memory Layout
Runtime Memory Usage
Daemon Process Memory
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Code Segment (~150 KB) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Heap: โ
โ โโโ Application entries (variable) โ
โ โโโ Markov chain nodes (variable) โ
โ โโโ Map entries (variable) โ
โ โโโ Working buffers (~100 KB) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Stack (~1 MB limit) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Typical total: 5-15 MB depending on tracked apps
Key Data Structures Size
| Structure | Approximate Size |
|---|---|
| Application entry | ~500 bytes + path strings |
| Map entry | ~200 bytes + path string |
| Markov node | ~100 bytes + transitions |
| Transition | ~20 bytes |
Thread Safety
Preheat is single-threaded with one exception:
- Main daemon: Single-threaded event loop
- Readahead workers: Forked processes (not threads)
This design:
- Avoids locking complexity
- Simplifies state management
- Forked workers have copy-on-write for read-only data
Error Handling
Error Recovery Strategy
| Error Type | Handling |
|---|---|
| Config parse error | Use defaults, log warning |
| State file missing | Start fresh, normal operation |
| State file corrupt | Discard, start fresh |
/proc read error |
Skip process, continue |
readahead fail |
Log, continue with next file |
| Out of memory | Reduce preload budget |
Defensive Coding
- All allocations checked for NULL
- File descriptors always closed (even on error paths)
- Signals handled with async-safe functions
- Graceful degradation over crashes
Navigation
| Previous | Up | Next |
|---|---|---|
| โ How It Works | Documentation Index | Configuration โ |