Skip to content

Commit 921300c

Browse files
committed
issue: 4480494 Add dev tooling and docs
Introduce comprehensive development tooling infrastructure to standardize and streamline development workflows across the libxlio codebase. Cursor Rules for Development Workflows: - commit-msg: Generate well-formatted commit messages - performance-issue: Investigate performance bottlenecks - solve-bug: Structured bug resolution workflow - test-plan: Comprehensive test plan generation - review-commit: Code review guidelines for commits - review-pr: Pull request review standards - research-functionality: Code exploration and documentation Project-Specific Guidelines: - coding.mdc: C++ standards for performance-critical code (naming conventions, pointer usage, cache alignment) - testing.mdc: Google Test patterns and fork-based testing (ti_N/tu_N naming, LD_PRELOAD requirements) Greptile Integration: - greptile.json: AI-powered code review automation (custom rules for core/tests/config, performance checks) These rules leverage MCP tools (Redmine, Confluence, GitHub) for context-aware assistance and integrate with existing project documentation (coding-style.md, style.conf). Benefits: - Standardized commit messages and documentation - Automated code quality checks via Greptile - Structured workflows for common development tasks - Better onboarding for new contributors - Context-aware AI assistance through Cursor rules Signed-off-by: Tomer Cabouly <[email protected]>
1 parent 8eeccc7 commit 921300c

File tree

10 files changed

+3797
-0
lines changed

10 files changed

+3797
-0
lines changed

.cursor/rules/coding.mdc

Lines changed: 315 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,315 @@
1+
---
2+
globs: **/*.c,**/*.cpp,**/*.h,**/*.cc
3+
alwaysApply: false
4+
---
5+
# C++ Programming Guidelines for libxlio
6+
7+
This guide is tailored for libxlio, a performance-critical networking library.
8+
9+
## Basic Principles
10+
11+
- Use English for all code and documentation.
12+
- Create necessary types and classes.
13+
- Use Doxygen style comments to document public classes and methods.
14+
- Follow the one-definition rule (ODR).
15+
- Prioritize performance without sacrificing code clarity.
16+
17+
## Nomenclature
18+
19+
- Use PascalCase for classes and structures.
20+
- Use snake_case for variables, functions, and methods.
21+
- Use ALL_CAPS for constants and macros.
22+
- Use snake_case for file and directory names.
23+
- Use UPPERCASE for environment variables.
24+
- Private/protected data members must use `m_` prefix (e.g., `m_count`, `m_buffer`).
25+
- Static data members must use `s_` prefix (e.g., `s_instance`).
26+
- Global variables must use `g_` prefix (e.g., `g_tcp_seg_pool`).
27+
- Avoid magic numbers and define constants.
28+
- Start each function with a verb.
29+
- Use verbs for boolean variables. Example: is_valid, has_error, can_delete, etc.
30+
- Precede getters with the word `get` (e.g., `get_count()`).
31+
- Precede setters with the word `set` (e.g., `set_count()`).
32+
- Use complete words instead of abbreviations and ensure correct spelling.
33+
- Except for standard abbreviations like api, url, etc.
34+
- Except for well-known abbreviations:
35+
- i, j, k for loops
36+
- err for errors
37+
- ctx for contexts
38+
- req, res for request/response parameters
39+
40+
## Auto Keyword
41+
42+
Use of `auto` should be carefully considered in performance-critical code:
43+
44+
- **Encouraged**: For iterator declarations and inside templates where it simplifies code.
45+
```cpp
46+
for (auto &elem : container) { }
47+
```
48+
- **Allowed**: When the initializer is a class name and it doesn't complicate readability.
49+
```cpp
50+
auto obj = MyClass();
51+
```
52+
- **Discouraged**: In other situations to avoid:
53+
- Hiding the type of variables, complicating code understanding.
54+
- Obscuring integer promotion and bit operations.
55+
- Hiding whether assignment uses copy or reference semantics.
56+
- Making performance implications unclear.
57+
- **Rationale**: Performance-critical code requires visibility into types for proper optimization and understanding of memory operations.
58+
59+
## Formatting
60+
61+
Follow the clang-format style defined in contrib/jenkins_tests/style.conf:
62+
63+
- Use 4 spaces for indentation (no tabs except in Makefiles).
64+
- Maximum line length: 100 characters.
65+
- Outermost namespace blocks should not be indented.
66+
- Case labels align with their switch statement (not indented).
67+
- Function definitions: place opening brace on its own line.
68+
```cpp
69+
int function()
70+
{
71+
// function body
72+
}
73+
```
74+
- Other braces (classes, loops, conditionals): opening brace on same line, closing brace on its own line.
75+
```cpp
76+
class MyClass {
77+
// class body
78+
};
79+
80+
if (condition) {
81+
// code
82+
}
83+
```
84+
- Always use braces for control statements, even for single-line bodies.
85+
- No blank spaces at the end of a line.
86+
87+
## Pointers and References
88+
89+
- Place `*` and `&` by the variable name, not the type.
90+
```cpp
91+
// Right:
92+
int *ptr;
93+
bool foo(char *str, std::vector<int> &result);
94+
95+
// Wrong:
96+
int* ptr;
97+
bool foo(char* str, std::vector<int>& result);
98+
```
99+
- Use raw pointers for performance-critical paths where necessary.
100+
- Smart pointers (std::unique_ptr, std::shared_ptr) are acceptable for higher-level resource management.
101+
- Custom memory pools and allocators are preferred for frequently allocated objects.
102+
103+
## Functions
104+
105+
- Write focused functions with a single purpose and clear intent.
106+
- Keep functions readable and maintainable (avoid arbitrary instruction limits; focus on clarity).
107+
- Name functions with a verb and something else.
108+
- If it returns a boolean, use is_x or has_x, can_x, etc.
109+
- If it doesn't return anything (void), use execute_x or save_x, update_x, etc.
110+
- Avoid nesting blocks by:
111+
- Early checks and returns.
112+
- Extraction to utility functions.
113+
- Use standard library algorithms (std::for_each, std::transform, std::find, etc.) to avoid function nesting.
114+
- Reduce function parameters using structs or classes:
115+
- Use an object to pass multiple parameters.
116+
- Use an object to return multiple results.
117+
- Declare necessary types for input arguments and output.
118+
- Use a single level of abstraction.
119+
120+
## Data
121+
122+
- Don't abuse primitive types and encapsulate data in composite types.
123+
- Avoid data validations in functions and use classes with internal validation.
124+
- Prefer immutability for data.
125+
- Use const for data that doesn't change.
126+
- Use constexpr for compile-time constants.
127+
128+
## Classes
129+
130+
- Follow SOLID principles.
131+
- Prefer composition over inheritance.
132+
- Declare interfaces as abstract classes or concepts.
133+
- Write small classes with a single purpose.
134+
- Less than 200 instructions.
135+
- Less than 10 public methods.
136+
- Less than 10 properties.
137+
- Use the Rule of Five (or Rule of Zero) for resource management.
138+
- Make member variables private and provide getters/setters where necessary.
139+
- Use const-correctness for member functions.
140+
141+
## Class Layout
142+
143+
Field layout is critical for performance optimization in libxlio:
144+
145+
- Group all fields together (either at top or bottom of class definition).
146+
- Group all methods together, separately from fields.
147+
- Do NOT mix methods and fields in the class definition.
148+
- **Rationale**: Field layout matters for padding and cache miss optimizations. Mixing fields and methods complicates visual perception and estimation of the resulting ABI.
149+
150+
**Right:**
151+
```cpp
152+
class Foo {
153+
public:
154+
Foo();
155+
void method1();
156+
157+
protected:
158+
void method2();
159+
160+
private:
161+
void method3();
162+
163+
public:
164+
int m_field1;
165+
166+
protected:
167+
int m_field2;
168+
169+
private:
170+
int m_field3;
171+
};
172+
```
173+
174+
**Also acceptable (no repeated visibility):**
175+
```cpp
176+
class Bar {
177+
public:
178+
Bar();
179+
void method1();
180+
181+
private:
182+
void method2();
183+
184+
int m_field1;
185+
int m_field2;
186+
};
187+
```
188+
189+
## Exceptions
190+
191+
libxlio has a configurable exception handling mechanism. Follow these guidelines:
192+
193+
- Use exceptions sparingly in performance-critical code paths.
194+
- Prefer error codes for expected error conditions in hot paths.
195+
- Use exceptions for truly exceptional situations during initialization/setup.
196+
- Use custom exception classes (`xlio_exception`) when exceptions are needed.
197+
- If you catch an exception, it should be to:
198+
- Fix an expected problem.
199+
- Add context with additional information.
200+
- Otherwise, use a global handler.
201+
- **Rationale**: Exception handling overhead is inappropriate for data path operations in a performance-critical library.
202+
203+
## Memory Management
204+
205+
Memory management in libxlio prioritizes performance:
206+
207+
- Use custom memory pools and allocators for performance-critical allocations.
208+
- Raw pointers are acceptable and often preferred in hot paths.
209+
- Smart pointers (std::unique_ptr, std::shared_ptr) for non-performance-critical resource management.
210+
- Use RAII (Resource Acquisition Is Initialization) principles where they don't impact performance.
211+
- Avoid memory leaks by proper resource management.
212+
- Consider cache alignment and padding when designing data structures.
213+
- Use `xlio_allocator` and related custom allocators for frequently allocated objects.
214+
- Prefer stack allocation over heap allocation when possible.
215+
216+
## Performance-Critical Programming
217+
218+
libxlio is a performance-critical library. Apply these optimizations when appropriate:
219+
220+
- Use inline functions for hot paths where beneficial.
221+
- Consider cache line alignment (typically 64 bytes) for frequently accessed structures.
222+
- Use `likely`/`unlikely` compiler hints for branch prediction in hot paths.
223+
- Minimize allocations in the data path; prefer object pools and pre-allocation.
224+
- Prefer stack allocation over heap allocation when object lifetime allows.
225+
- Use `const` and `constexpr` aggressively to enable compiler optimizations.
226+
- Be mindful of false sharing in multi-threaded code.
227+
- Profile before optimizing; measure the impact of changes.
228+
- Document performance-critical sections and the reasoning behind optimizations.
229+
230+
## Include Order
231+
232+
Organize includes to minimize dependencies and reduce compile time:
233+
234+
1. `config.h` (if applicable)
235+
2. Related header (for .cpp files, include the corresponding .h)
236+
3. C system headers (e.g., `<sys/types.h>`, `<unistd.h>`)
237+
4. C++ standard library headers (e.g., `<string>`, `<vector>`)
238+
5. Other libraries' headers (e.g., `<json-c/json.h>`)
239+
6. Your project's headers (e.g., `"core/util/utils.h"`)
240+
241+
**Example:**
242+
```cpp
243+
#include "config.h"
244+
245+
#include "foo/server/fooserver.h"
246+
247+
#include <sys/types.h>
248+
#include <unistd.h>
249+
250+
#include <string>
251+
#include <vector>
252+
253+
#include "base/basictypes.h"
254+
#include "foo/server/bar.h"
255+
```
256+
257+
- Keep dependencies minimal to reduce compile time.
258+
- Use forward declarations when possible to avoid unnecessary includes.
259+
260+
## Comments
261+
262+
- Use Doxygen style comments to document public classes, methods, and APIs.
263+
```cpp
264+
/**
265+
* @brief Brief description of the function
266+
* @param arg1 Description of first parameter
267+
* @return Description of return value
268+
*/
269+
int my_function(int arg1);
270+
```
271+
- Use C++ style (`//`) for single-line comments.
272+
- Use C style (`/* */`) for multi-line comments with proper alignment:
273+
```cpp
274+
/* The preferred comment style for multi-line comments
275+
* looks like this.
276+
*/
277+
```
278+
- Comments should explain **WHAT** your code does and **WHY**, not **HOW**.
279+
- Write comments as English prose with proper capitalization and punctuation.
280+
- Comments are important for readability and maintainability in complex, performance-critical code.
281+
282+
## Testing
283+
284+
- Follow the Arrange-Act-Assert convention for tests.
285+
- Name test variables clearly.
286+
- Write unit tests for each public function.
287+
- Follow the Given-When-Then convention.
288+
- All features or bug fixes **must be tested** by unit tests.
289+
290+
## Project Structure
291+
292+
- Use modular architecture.
293+
- Organize code into logical directories.
294+
- Use automake and autotools.
295+
- Separate interface (.h) from implementation (.cpp).
296+
- Use namespaces to organize code logically.
297+
298+
## Standard Library
299+
300+
- Use the C++ Standard Library when it doesn't compromise performance.
301+
- Use std::vector, std::map, std::unordered_map, etc. for collections (except in hot paths).
302+
- Use std::chrono for time-related operations.
303+
- Consider custom implementations for performance-critical data structures.
304+
305+
## Concurrency
306+
307+
libxlio is a multi-threaded library. Thread safety is critical:
308+
309+
- Use std::thread, std::mutex, std::lock_guard for thread safety.
310+
- Use std::atomic for atomic operations.
311+
- Avoid data races by proper synchronization.
312+
- Use thread-safe data structures when necessary.
313+
- Be mindful of lock contention in hot paths.
314+
- Consider lock-free algorithms for performance-critical sections.
315+
- Document thread-safety guarantees for all public APIs.

0 commit comments

Comments
 (0)