From 0844424ad1921bace8eab224aa3ed7cfdd5c5aa4 Mon Sep 17 00:00:00 2001 From: discountchubbs Date: Sun, 7 Dec 2025 11:47:14 -0800 Subject: [PATCH 1/7] update --- sunnypilot/common/README.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sunnypilot/common/README.md b/sunnypilot/common/README.md index 9068a75ea6..447155a4ba 100644 --- a/sunnypilot/common/README.md +++ b/sunnypilot/common/README.md @@ -36,8 +36,7 @@ While `ParamWatcher` offers superior performance for UI rendering, it presents s * **Event Latency**: In high-load scenarios, `inotify` events may experience slight delays or coalescing compared to direct reads. However, for user interface applications, this latency (<10ms) is imperceptible. * **Complexity**: The solution requires managing a singleton background thread and OS-specific event loops, increasing code complexity compared to the synchronous `Params::get` function. -## 5. Implementation Analysis: `param_watcher.py` - +## Implementation Analysis The `ParamWatcher` class provides a cross-platform solution for monitoring file system changes, specifically targeting the parameter files used in Openpilot. The implementation leverages the `ctypes` library to interface directly with operating system kernels, bypassing higher-level abstractions for maximum performance. ### Linux Implementation (`_run_linux`) @@ -69,7 +68,6 @@ The use of `ctypes` (Python Software Foundation, n.d.) is a strategic choice. It With 232 defined parameters in `param_keys.h`, the maximum static RAM footprint of `ParamWatcher` is estimated to be **less than 250 KB**. Even if every single parameter were cached simultaneously, this static usage is negligible. Crucially, this stable footprint is likely more probable to maintain no trend of memory increase, whenc compared to the standard `Params::get` approach, which generates **megabytes** of short-lived "garbage" allocations per second, forcing the Python Garbage Collector to pause execution repeatedly. ## Architectural Integration: The Process-Local Singleton Pattern - To ensure resource efficiency within openpilot's multi-process architecture (e.g., `ui`, `controlsd`, `modeld`), `ParamWatcher` implements the Singleton design pattern (Gamma et al., 1994) using the Python `__new__` allocator. ### Process Isolation and Concurrency @@ -89,7 +87,6 @@ Runtime analysis demonstrates that multiple instantiation attempts result in a s Replacing polling mechanisms with event-driven caching shifts the computational load from kernel space (syscalls) to user space (RAM). This transition eliminates I/O overhead and UI stutters caused by garbage collection, resulting in a more responsive user experience. ## References - Apple Inc. (n.d.-a). *File System Events*. Retrieved from https://developer.apple.com/documentation/coreservices/file_system_events Apple Inc. (n.d.-b). *CFRunLoop*. Retrieved from https://developer.apple.com/documentation/corefoundation/cfrunloop-rhk From 6b4118ab27d598ad3a5dc9dd0cf4a695562f33a5 Mon Sep 17 00:00:00 2001 From: discountchubbs Date: Sun, 7 Dec 2025 11:55:27 -0800 Subject: [PATCH 2/7] dates --- sunnypilot/common/README.md | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/sunnypilot/common/README.md b/sunnypilot/common/README.md index 447155a4ba..03286569cb 100644 --- a/sunnypilot/common/README.md +++ b/sunnypilot/common/README.md @@ -6,8 +6,8 @@ The standard `Params::get()` method executes a full file I/O lifecycle—opening ### System Overhead Analysis * **System Call Overhead**: Every read operation requires context switches into kernel mode. The `Params::get` function calls `util::read_file` (sunnypilot, 2024), which subsequently invokes `std::ifstream` (sunnypilot, 2024). - * *Impact*: Frequent context switching degrades performance (Linux man-pages, n.d.-a; Linux man-pages, n.d.-b). -* **C++ Stream Overhead**: The use of `std::ifstream` introduces additional overhead for maintaining stream state and buffering compared to raw file descriptors (cppreference.com, n.d.-a; Codezup, n.d.). +* **Impact**: Frequent context switching degrades performance (Linux man-pages, 2025 -a; Linux man-pages, 2025 -b). +* **C++ Stream Overhead**: The use of `std::ifstream` introduces additional overhead for maintaining stream state and buffering compared to raw file descriptors (cppreference.com, n.d.-a; Codezup, 2025). * **Memory Churn**: The instantiation of `std::string result(size, '\0');` forces heap allocation and deallocation during every call (sunnypilot, 2024). This stresses the memory allocator and can lead to fragmentation (cppreference.com, n.d.). ## The `ParamWatcher` Optimization @@ -40,7 +40,7 @@ While `ParamWatcher` offers superior performance for UI rendering, it presents s The `ParamWatcher` class provides a cross-platform solution for monitoring file system changes, specifically targeting the parameter files used in Openpilot. The implementation leverages the `ctypes` library to interface directly with operating system kernels, bypassing higher-level abstractions for maximum performance. ### Linux Implementation (`_run_linux`) -The Linux implementation interacts directly with the kernel's `inotify` subsystem (Linux man-pages, n.d.-c). +The Linux implementation interacts directly with the kernel's `inotify` subsystem (Linux man-pages, 2025 -c). * **Library Loading**: `libc = ctypes.CDLL('libc.so.6')` loads the standard C library to access system calls. * **Initialization**: `inotify_init()` is called to create a new inotify instance, returning a file descriptor. @@ -62,10 +62,10 @@ The macOS implementation uses the `FSEvents` API from the `CoreServices` framewo * **Handling**: Inside the callback, the code iterates through the changed paths provided by the OS. It extracts the filename and calls `_trigger_callbacks` to invalidate the cache for that specific parameter. ### Python `ctypes` Integration -The use of `ctypes` (Python Software Foundation, n.d.) is a strategic choice. It allows the Python interpreter to load shared libraries (`libc.so.6` on Linux, `CoreServices` on macOS) and call C functions directly. This approach avoids the overhead of spawning subprocesses or compiling external C extensions, keeping the codebase pure Python while achieving C-level system integration. +The use of `ctypes` (Python Software Foundation, 2025) is a strategic choice. It allows the Python interpreter to load shared libraries (`libc.so.6` on Linux, `CoreServices` on macOS) and call C functions directly. This approach avoids the overhead of spawning subprocesses or compiling external C extensions, keeping the codebase pure Python while achieving C-level system integration. ### Memory Impact Analysis - With 232 defined parameters in `param_keys.h`, the maximum static RAM footprint of `ParamWatcher` is estimated to be **less than 250 KB**. Even if every single parameter were cached simultaneously, this static usage is negligible. Crucially, this stable footprint is likely more probable to maintain no trend of memory increase, whenc compared to the standard `Params::get` approach, which generates **megabytes** of short-lived "garbage" allocations per second, forcing the Python Garbage Collector to pause execution repeatedly. + With 232 defined parameters in `param_keys.h`, the maximum static RAM footprint of `ParamWatcher` is estimated to be **less than 250 KB**. Even if every single parameter were cached simultaneously, this static usage is negligible. Importantly, this stable footprint is likely more probable to maintain no trend of memory increase, whenc compared to the standard `Params::get` approach, which generates **megabytes** of short-lived "garbage" allocations per second, forcing the Python Garbage Collector to pause execution repeatedly. ## Architectural Integration: The Process-Local Singleton Pattern To ensure resource efficiency within openpilot's multi-process architecture (e.g., `ui`, `controlsd`, `modeld`), `ParamWatcher` implements the Singleton design pattern (Gamma et al., 1994) using the Python `__new__` allocator. @@ -89,21 +89,21 @@ Replacing polling mechanisms with event-driven caching shifts the computational ## References Apple Inc. (n.d.-a). *File System Events*. Retrieved from https://developer.apple.com/documentation/coreservices/file_system_events -Apple Inc. (n.d.-b). *CFRunLoop*. Retrieved from https://developer.apple.com/documentation/corefoundation/cfrunloop-rhk +Apple Inc. (n.d.-b). *CFRunLoop*. Retrieved from https://developer.apple.com/documentation/corefoundation/cfrunloop -Codezup. (n.d.). *Efficient File I/O in C++*. Retrieved from https://codezup.com/efficient-file-io-cpp-best-practices/ +Codezup. (2025). *Efficient File I/O in C++*. Retrieved from https://codezup.com/efficient-file-io-cpp-best-practices/ cppreference.com. (n.d.-a). *std::basic_ifstream*. Retrieved from https://en.cppreference.com/w/cpp/io/basic_ifstream cppreference.com. (n.d.-b). *std::basic_string*. Retrieved from https://en.cppreference.com/w/cpp/string/basic_string/basic_string -Linux man-pages. (n.d.-a). *open(2)*. Retrieved from https://man7.org/linux/man-pages/man2/open.2.html +Linux man-pages. (2025 -a). *open(2)*. Retrieved from https://man7.org/linux/man-pages/man2/open.2.html -Linux man-pages. (n.d.-b). *read(2)*. Retrieved from https://man7.org/linux/man-pages/man2/read.2.html +Linux man-pages. (2025-b). *read(2)*. Retrieved from https://man7.org/linux/man-pages/man2/read.2.html -Linux man-pages. (n.d.-c). *inotify(7)*. Retrieved from https://man7.org/linux/man-pages/man7/inotify.7.html +Linux man-pages. (2025 -c). *inotify(7)*. Retrieved from https://man7.org/linux/man-pages/man7/inotify.7.html -Python Software Foundation. (n.d.). *ctypes — A foreign function library for Python*. Retrieved from https://docs.python.org/3/library/ctypes.html +Python Software Foundation. (2025). *ctypes — A foreign function library for Python*. Retrieved from https://docs.python.org/3/library/ctypes.html Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). *Design Patterns: Elements of Reusable Object-Oriented Software*. Addison-Wesley. From 7ba21f9f1b926ae5844d1b6a42f4ae868d1c1ee0 Mon Sep 17 00:00:00 2001 From: discountchubbs Date: Sun, 7 Dec 2025 11:57:27 -0800 Subject: [PATCH 3/7] 2025 --- sunnypilot/common/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sunnypilot/common/README.md b/sunnypilot/common/README.md index 03286569cb..64103994bb 100644 --- a/sunnypilot/common/README.md +++ b/sunnypilot/common/README.md @@ -5,10 +5,10 @@ The standard `Params::get()` method executes a full file I/O lifecycle—opening, allocating, reading, and closing—for every function call. This approach results in significant CPU overhead and memory churn due to the frequency of these operations in the user interface loop. ### System Overhead Analysis -* **System Call Overhead**: Every read operation requires context switches into kernel mode. The `Params::get` function calls `util::read_file` (sunnypilot, 2024), which subsequently invokes `std::ifstream` (sunnypilot, 2024). +* **System Call Overhead**: Every read operation requires context switches into kernel mode. The `Params::get` function calls `util::read_file` (sunnypilot, 2025), which subsequently invokes `std::ifstream` (sunnypilot, 2025). * **Impact**: Frequent context switching degrades performance (Linux man-pages, 2025 -a; Linux man-pages, 2025 -b). * **C++ Stream Overhead**: The use of `std::ifstream` introduces additional overhead for maintaining stream state and buffering compared to raw file descriptors (cppreference.com, n.d.-a; Codezup, 2025). -* **Memory Churn**: The instantiation of `std::string result(size, '\0');` forces heap allocation and deallocation during every call (sunnypilot, 2024). This stresses the memory allocator and can lead to fragmentation (cppreference.com, n.d.). +* **Memory Churn**: The instantiation of `std::string result(size, '\0');` forces heap allocation and deallocation during every call (sunnypilot, 2025). This stresses the memory allocator and can lead to fragmentation (cppreference.com, n.d.). ## The `ParamWatcher` Optimization The `ParamWatcher` implementation utilizes OS-level file system events, such as `inotify` on Linux or `FSEvents` on macOS, to maintain a Random Access Memory (RAM) cache. This architecture eliminates the need for continuous polling. From 79971b9eb2bb9a7a33bebd4e4e062e7e8b10180b Mon Sep 17 00:00:00 2001 From: discountchubbs Date: Sun, 7 Dec 2025 12:11:49 -0800 Subject: [PATCH 4/7] move limitations to end --- sunnypilot/common/README.md | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sunnypilot/common/README.md b/sunnypilot/common/README.md index 64103994bb..a94b93c420 100644 --- a/sunnypilot/common/README.md +++ b/sunnypilot/common/README.md @@ -14,7 +14,6 @@ The standard `Params::get()` method executes a full file I/O lifecycle—opening The `ParamWatcher` implementation utilizes OS-level file system events, such as `inotify` on Linux or `FSEvents` on macOS, to maintain a Random Access Memory (RAM) cache. This architecture eliminates the need for continuous polling. ### Performance Comparison - | Feature | Standard `Params::get` | Optimized `ParamWatcher` | | :--- | :--- | :--- | | **Workflow** | `open` → `malloc` → `read` → `close` | `dict.get()` (RAM lookup) | @@ -29,13 +28,6 @@ Standard C++ modules like `std::ifstream` are optimized for **throughput**—rea * **The Memory Trap**: The `std::string` class allocates memory on the heap. Repeated allocation creates short-lived objects, which in C++ fragments memory. In Python (which wraps this), it triggers the Garbage Collector, pausing the UI. * **The Query Mismatch**: `Params::get` queries the current value every frame, whereas `ParamWatcher` waits for a notification of change, serving cached values in the interim. -## Limitations and Trade-offs -While `ParamWatcher` offers superior performance for UI rendering, it presents specific trade-offs: - -* **Static RAM Usage**: `ParamWatcher` maintains a persistent dictionary cache of all accessed parameters (~50KB), whereas `Params::get` uses zero static RAM but incurs high dynamic memory access. -* **Event Latency**: In high-load scenarios, `inotify` events may experience slight delays or coalescing compared to direct reads. However, for user interface applications, this latency (<10ms) is imperceptible. -* **Complexity**: The solution requires managing a singleton background thread and OS-specific event loops, increasing code complexity compared to the synchronous `Params::get` function. - ## Implementation Analysis The `ParamWatcher` class provides a cross-platform solution for monitoring file system changes, specifically targeting the parameter files used in Openpilot. The implementation leverages the `ctypes` library to interface directly with operating system kernels, bypassing higher-level abstractions for maximum performance. @@ -83,6 +75,13 @@ Runtime analysis demonstrates that multiple instantiation attempts result in a s * **Result**: Both instances report the exact same memory address (`4814358960`) and share the same background thread ID (`6114635776`). * **Impact**: The system incurs the overhead of the watcher thread (measured at < 0.1% CPU idle usage) only once per active process, regardless of import frequency. The average CPU usage across one minute was 0.002%. +## Limitations and Trade-offs +While `ParamWatcher` offers superior performance for UI rendering, it presents specific trade-offs: + +* **Static RAM Usage**: `ParamWatcher` maintains a persistent dictionary cache of all accessed parameters (~50KB), whereas `Params::get` uses zero static RAM but incurs high dynamic memory access. +* **Event Latency**: In high-load scenarios, `inotify` events may experience slight delays or coalescing compared to direct reads. However, for user interface applications, this latency (<10ms) is imperceptible. +* **Complexity**: The solution (the process singleton approach) requires managing a background thread and OS-specific event loops, increasing code complexity compared to the synchronous `Params::get` function. + ## Conclusion Replacing polling mechanisms with event-driven caching shifts the computational load from kernel space (syscalls) to user space (RAM). This transition eliminates I/O overhead and UI stutters caused by garbage collection, resulting in a more responsive user experience. From 48a880229875cf7cb730cc4676e91dab9242d9ee Mon Sep 17 00:00:00 2001 From: discountchubbs Date: Sun, 7 Dec 2025 12:12:43 -0800 Subject: [PATCH 5/7] cp analysis needs high level --- sunnypilot/common/README.md | 1 - 1 file changed, 1 deletion(-) diff --git a/sunnypilot/common/README.md b/sunnypilot/common/README.md index a94b93c420..b7b97461f9 100644 --- a/sunnypilot/common/README.md +++ b/sunnypilot/common/README.md @@ -1,4 +1,3 @@ - # Comparative Analysis of Parameter Access Methods: `Params::get` vs. `ParamWatcher` ## Inefficiencies in Standard Parameter Access From d0ec46dc5decfe05bf5a3252c7164fbfb80a898e Mon Sep 17 00:00:00 2001 From: discountchubbs Date: Sun, 7 Dec 2025 12:14:54 -0800 Subject: [PATCH 6/7] cp --- sunnypilot/common/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sunnypilot/common/README.md b/sunnypilot/common/README.md index b7b97461f9..926a2c38db 100644 --- a/sunnypilot/common/README.md +++ b/sunnypilot/common/README.md @@ -9,7 +9,7 @@ The standard `Params::get()` method executes a full file I/O lifecycle—opening * **C++ Stream Overhead**: The use of `std::ifstream` introduces additional overhead for maintaining stream state and buffering compared to raw file descriptors (cppreference.com, n.d.-a; Codezup, 2025). * **Memory Churn**: The instantiation of `std::string result(size, '\0');` forces heap allocation and deallocation during every call (sunnypilot, 2025). This stresses the memory allocator and can lead to fragmentation (cppreference.com, n.d.). -## The `ParamWatcher` Optimization +## The ParamWatcher Optimization The `ParamWatcher` implementation utilizes OS-level file system events, such as `inotify` on Linux or `FSEvents` on macOS, to maintain a Random Access Memory (RAM) cache. This architecture eliminates the need for continuous polling. ### Performance Comparison @@ -52,7 +52,7 @@ The macOS implementation uses the `FSEvents` API from the `CoreServices` framewo * **Execution**: `CFRunLoopRun()` starts the event loop. This passes control to the OS, which wakes the thread only when necessary. * **Handling**: Inside the callback, the code iterates through the changed paths provided by the OS. It extracts the filename and calls `_trigger_callbacks` to invalidate the cache for that specific parameter. -### Python `ctypes` Integration +### Python ctypes Integration The use of `ctypes` (Python Software Foundation, 2025) is a strategic choice. It allows the Python interpreter to load shared libraries (`libc.so.6` on Linux, `CoreServices` on macOS) and call C functions directly. This approach avoids the overhead of spawning subprocesses or compiling external C extensions, keeping the codebase pure Python while achieving C-level system integration. ### Memory Impact Analysis From 42e08515e6e772598850fd20e4a640a3d051041d Mon Sep 17 00:00:00 2001 From: discountchubbs Date: Sun, 7 Dec 2025 12:22:15 -0800 Subject: [PATCH 7/7] make the link go to LxCx --- sunnypilot/common/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sunnypilot/common/README.md b/sunnypilot/common/README.md index 926a2c38db..b33e39cd81 100644 --- a/sunnypilot/common/README.md +++ b/sunnypilot/common/README.md @@ -105,6 +105,6 @@ Python Software Foundation. (2025). *ctypes — A foreign function library for P Gamma, E., Helm, R., Johnson, R., & Vlissides, J. (1994). *Design Patterns: Elements of Reusable Object-Oriented Software*. Addison-Wesley. -sunnypilot. (2025). *common/params.cc* [Source code]. GitHub. https://github.com/sunnypilot/sunnypilot/blob/master/common/params.cc +sunnypilot. (2025). *common/params.cc* [Source code]. GitHub. https://github.com/sunnypilot/sunnypilot/blob/master/common/params.cc#L180C1-L206C2 -sunnypilot. (2025). *common/util.cc* [Source code]. GitHub. https://github.com/sunnypilot/sunnypilot/blob/master/common/util.cc +sunnypilot. (2025). *common/util.cc* [Source code]. GitHub. https://github.com/sunnypilot/sunnypilot/blob/master/common/util.cc#L79C1-L117C2