Files
project_6/upstream_ref/xllm/.agents/skills/code-review/references/custom-code-style.md
EX Engine 002f9879b2 ref(upstream): FULL TREE — Deep-Spark xllm (1470) + ds_vllm csrc/models (703)
Replaces cherry-picked upstream_ref with complete source trees.

xllm/ — Iluvatar official C++ inference engine (15MB, 1470 files)
  Complete: kernels → layers → models → runtime → scheduler → api
  Excluded: .git, binary images, third_party submodule checkouts

ds_vllm/ — Iluvatar official vllm fork (8MB, 703 files)
  Included: csrc/ (ALL CUDA kernels), fused_moe/, qwen3_5 model, _custom_ops
  Excluded: tests, benchmarks, docs, examples (not needed for reference)

Critical call chains now fully traceable:
  MoE: moe_topk_softmax_kernels.cuh → ixformer.h → fused_moe.cpp → layer
  GDN: qwen3_gated_delta_net_base.cpp → qwen3_5_gated_delta_net.cpp
  Attention: ixformer.h → xllm_paged_attention → attention.cpp
2026-08-10 02:54:03 +00:00

9.4 KiB
Raw Blame History

Custom Code Style

Project-specific coding style for xllm. The reviewer MUST enforce these style.


1. Naming Conventions

C++

Element Style Example
Namespace snake_case xllm, xllm::detail
Class / Struct PascalCase LlmModelImplBase, KVCache
Function snake_case get_input_embeddings, forward
Member variable snake_case_ (trailing underscore) model_type_, embed_tokens_
Local variable snake_case inputs_embeds, kv_caches
Constant k + PascalCase kContentLength, kMaxBatchSize
Enum type PascalCase EngineType, DeviceType
Enum value ALL_CAPS LLM, VLM, INVALID
Template param PascalCase DecoderLayerType
Macro ALL_CAPS XLLM_CHECK, LOG_EVERY_N
File name snake_case llm_model_base.h, types.h
Header guard #pragma once -

Python

Element Style Example
Module / file snake_case model_loader.py
Class PascalCase TokenizerConfig
Function snake_case load_model
Variable snake_case batch_size
Constant ALL_CAPS MAX_SEQ_LEN
Private member _leading_underscore _internal_state

2. File & Header Rules

  • Copyright header required on all new files. Use the correct year matching the file creation date.
/* Copyright 2025 The xLLM Authors. All Rights Reserved.

Licensed under the Apache License, Version 2.0 (the "License");
...
==============================================================================*/
  • No relative paths in #include. Always use project-root-relative paths.
// Good
#include "core/common/types.h"

// Bad
#include "../common/types.h"
#include "./types.h"
  • Remove redundant and duplicate includes. Each header should be included exactly once, and unused includes must be cleaned up.

3. Type System & Declarations

  • Use fixed-width integers (int32_t, int64_t) instead of plain int, unless the API you are calling explicitly requires int.
// Good
int32_t batch_size = 16;
int64_t total_tokens = 0;

// Bad
int batch_size = 16;
  • Use static_cast for all type conversions. Never use C-style casts.
// Good
auto len = static_cast<int32_t>(vec.size());

// Bad
auto len = (int32_t)vec.size();
  • Do not use auto for simple/primitive types. auto is acceptable for complex types (iterators, lambdas, template-deduced types) but not for int32_t, float, bool, std::string, etc.
// Good
int32_t count = 0;
auto it = map.find(key);  // complex iterator type, auto is fine

// Bad
auto count = 0;
auto name = std::string("model");
  • Use using instead of typedef for type aliases. Prefer aliases for complex types to improve readability.
// Good
using TensorVec = std::vector<torch::Tensor>;
using CallbackFn = std::function<void(int32_t)>;

// Bad
typedef std::vector<torch::Tensor> TensorVec;
  • Use enum class instead of plain enum to provide type safety and prevent implicit conversions.
// Good
enum class DeviceType : int8_t { CPU = 0, CUDA = 1, NPU = 2 };

// Bad
enum DeviceType { CPU = 0, CUDA = 1, NPU = 2 };
  • Use nullptr instead of NULL or 0 for null pointers.

  • Choose the right container: use std::unordered_map / std::unordered_set when key ordering is irrelevant (O(1) average lookup). Use std::map / std::set only when sorted iteration or key ordering is required.


4. Class Design

  • Mark classes final if they are not designed to be inherited from.
// Good
class TokenizerConfig final { ... };

// Bad  class has no virtual functions and is not intended as a base
class TokenizerConfig { ... };
  • Use explicit on any constructor that can be invoked with a single argument. This includes multi-parameter constructors where all parameters except the first have default values.
// Good
explicit ModelArgs(const std::string& path, int32_t num_layers = 12);

// Bad  allows implicit conversion from std::string
ModelArgs(const std::string& path, int32_t num_layers = 12);
  • Use override when overriding virtual functions in derived classes. Never repeat the virtual keyword on overrides.
// Good
ModelOutput forward(torch::Tensor tokens, ...) override;

// Bad
virtual ModelOutput forward(torch::Tensor tokens, ...);
  • Structs must not have member functions. If you need methods, use a class. Structs are for plain data aggregation only.

5. Memory & Resource Management

  • Avoid raw pointers. Prefer smart pointers (std::unique_ptr, std::shared_ptr) for ownership semantics.
    • Use std::unique_ptr by default (sole ownership).
    • Use std::shared_ptr only when shared ownership is genuinely needed.
    • Raw pointers are acceptable only for non-owning references where the lifetime is clearly managed elsewhere.

6. Scoping & Visibility

C++

  • File-local functions and variables (used only within a single .cpp file) must be placed in an anonymous namespace.
namespace {
int32_t compute_padding(int32_t seq_len, int32_t alignment) {
  return (alignment - seq_len % alignment) % alignment;
}
}  // namespace

Python

  • File-local helper functions (not part of the public API) must be prefixed with _.
  • Non-public member functions of a class must be prefixed with _.
def _validate_config(config: dict) -> bool:
    ...

class ModelLoader:
    def load(self, path: str) -> Model:
        self._check_path(path)
        ...

    def _check_path(self, path: str) -> None:
        ...

7. Torch & Framework API Usage

  • Use torch:: namespace instead of at:: or c10:: wherever possible. Prefer the highest-level PyTorch C++ API.
// Good
torch::Tensor output = torch::zeros({batch_size, hidden_dim});

// Bad
at::Tensor output = at::zeros({batch_size, hidden_dim});
c10::optional<torch::Tensor> mask = c10::nullopt;  // use std::optional
  • Use CHECK (glog) instead of TORCH_CHECK for assertions.
// Good
CHECK(tensor.is_contiguous()) << "Input tensor must be contiguous";

// Bad
TORCH_CHECK(tensor.is_contiguous(), "Input tensor must be contiguous");
  • Use LOG(FATAL) for unrecoverable errors instead of throwing std::runtime_error.
// Good
LOG(FATAL) << "Unsupported model type: " << model_type;

// Bad
throw std::runtime_error("Unsupported model type: " + model_type);

8. Code Style & Control Flow

  • Always use braces {} with if, while, for, even for single-line bodies.
// Good
if (x > 0) {
  return x;
}

// Bad
if (x > 0) return x;
  • Avoid if inside for loops when possible. Prefer filtering the data beforehand or restructuring the logic (e.g., early continue, separate loops, std::copy_if).

  • Define variables close to first use. Do not declare all variables at the top of a function.

  • Annotate constant arguments with a comment indicating the parameter name when calling functions or constructors.

// Good
auto layer = DecoderLayer(/*hidden_size=*/4096, /*num_heads=*/32);

// Bad
auto layer = DecoderLayer(4096, 32);

9. STL Best Practices

  • Always reserve() before filling a std::vector when the size is known or can be estimated.
// Good
std::vector<torch::Tensor> outputs;
outputs.reserve(num_layers);
for (int32_t i = 0; i < num_layers; ++i) {
  outputs.emplace_back(compute_layer(i));
}

// Bad  causes multiple reallocations
std::vector<torch::Tensor> outputs;
for (int32_t i = 0; i < num_layers; ++i) {
  outputs.push_back(compute_layer(i));
}
  • Prefer emplace_back over push_back to construct elements in-place and avoid unnecessary copies.

10. Global Flags

  • Do not overuse FLAGS_ global variables. Prefer passing configuration through constructor parameters or config structs. Only use global flags for top-level, process-wide settings.
  • Register new flags in help_formatter.h. When adding a new global flag, always add a corresponding entry in help_formatter.h so it appears in --help output.

11. Python-Specific Rules

  • Type annotations are required on all function signatures (parameters and return types). Use typing module types where needed.
# Good
def load_model(path: str, device: str = "cuda") -> nn.Module:
    ...

# Bad
def load_model(path, device="cuda"):
    ...
  • Private helpers: prefix with _ (see Section 6).