# memscope-rs API 使用指南

## 快速开始

memscope-rs 提供了简洁的 API 来追踪 Rust 应用程序的内存使用情况。

### 基本用法

```rust
use memscope_rs::{global_tracker, init_global_tracking, track};

// 初始化（可选，会在首次使用时自动初始化）
init_global_tracking().unwrap();

// 获取全局追踪器
let tracker = global_tracker().unwrap();

// 追踪变量
let data = vec![1, 2, 3, 4, 5];
track!(tracker, data);

let text = String::from("Hello, world!");
track!(tracker, text);

// 导出数据
tracker.export_json("output").unwrap();
tracker.export_html("output").unwrap();
```

## 核心 API

### 1. 初始化

```rust
use memscope_rs::init_global_tracking;

// 使用默认配置初始化
init_global_tracking().unwrap();

// 使用自定义配置初始化
use memscope_rs::GlobalTrackerConfig;
let config = GlobalTrackerConfig {
    tracker: memscope_rs::TrackerConfig {
        max_allocations: 1000000,
        enable_statistics: true,
    },
    ..Default::default()
};
init_global_tracking_with_config(config).unwrap();
```

### 2. 获取追踪器

```rust
use memscope_rs::global_tracker;

// 获取全局追踪器实例
let tracker = global_tracker().unwrap();
```

### 3. 追踪变量

#### 简单追踪

```rust
use memscope_rs::track;

// 使用 track! 宏自动追踪
let data = vec![1, 2, 3];
track!(tracker, data);

let text = String::from("Hello");
track!(tracker, text);
```

#### 带名称的追踪

```rust
use memscope_rs::track;

// 追踪时指定变量名和位置
let important_data = vec![1, 2, 3];
track!(tracker, important_data, "important_data", "my_file.rs", 42);
```

#### 直接追踪方法

```rust
// 使用 tracker.track() 方法
let data = vec![1, 2, 3];
tracker.track(&data);

// 使用 tracker.track_as() 方法指定名称
let data = vec![1, 2, 3];
tracker.track_as(&data, "my_data", "my_file.rs", 42);
```

### 4. 导出数据

#### 导出 JSON

```rust
// 导出所有 JSON 文件到指定目录
tracker.export_json("output")?;

// 这会生成以下文件：
// - memory_snapshots.json        - 内存快照数据
// - memory_passports.json        - 内存护照追踪
// - leak_detection.json          - 内存泄漏检测结果
// - unsafe_ffi_analysis.json    - 不安全/FFI 追踪数据
// - system_resources.json       - 系统资源监控
// - async_analysis.json         - 异步任务内存分析
```

#### 导出 HTML

```rust
// 导出 HTML 仪表板
tracker.export_html("output")?;

// 这会生成一个交互式的 HTML 仪表板文件
```

### 5. 获取统计信息

```rust
// 获取追踪统计信息
let stats = tracker.get_stats();

println!("总分配次数: {}", stats.total_allocations);
println!("活跃分配: {}", stats.active_allocations);
println!("峰值内存: {} bytes", stats.peak_memory_bytes);
println!("当前内存: {} bytes", stats.current_memory_bytes);
println!("内存护照数量: {}", stats.passport_count);
println!("活跃护照: {}", stats.active_passports);
println!("检测到的泄漏: {}", stats.leaks_detected);
println!("异步任务数量: {}", stats.async_task_count);
println!("活跃异步任务: {}", stats.active_async_tasks);
println!("运行时间: {:?}", stats.uptime);
```

## 高级用法

### 不安全代码追踪

```rust
use memscope_rs::global_tracker;

let tracker = global_tracker().unwrap();

// 追踪不安全分配
use std::alloc::{alloc, Layout};
unsafe {
    let layout = Layout::new::<[u32; 100]>();
    let ptr = alloc(layout);

    if !ptr.is_null() {
        // 创建内存护照（返回护照 ID）
        let passport_id = tracker
            .create_passport(ptr as usize, layout.size(), "unsafe_alloc".to_string())
            .expect("Failed to create passport");
        println!("Created passport: {}", passport_id);

        // 记录跨边界事件
        tracker.record_handover(ptr as usize, "ffi_context".to_string(), "malloc".to_string());

        // 使用内存...
        std::ptr::write_bytes(ptr as *mut u8, 0, layout.size());

        // 记录释放事件
        tracker.record_free(ptr as usize, "ffi_context".to_string(), "free".to_string());

        std::alloc::dealloc(ptr, layout);
    }
}
```

### 泄漏检测

```rust
use memscope_rs::global_tracker;

let tracker = global_tracker().unwrap();

// 执行泄漏检测（返回 LeakDetectionResult）
let leak_result = tracker.passport_tracker().detect_leaks_at_shutdown();

println!("检测到的泄漏数量: {}", leak_result.total_leaks);
println!("活跃护照数量: {}", leak_result.active_passports);
println!("总护照数量: {}", leak_result.total_passports);
```

### 访问内部追踪器

如果需要访问更底层的追踪功能：

```rust
use memscope_rs::global_tracker;

let tracker = global_tracker().unwrap();

// 访问基础追踪器
let base_tracker = tracker.tracker();
let report = base_tracker.analyze();

// 访问护照追踪器
let passport_tracker = tracker.passport_tracker();
let passport_stats = passport_tracker.get_stats();

// 访问异步追踪器
let async_tracker = tracker.async_tracker();
let async_stats = async_tracker.get_stats();
```

## 支持的类型

以下类型自动支持追踪：

- `Vec<T>`
- `String`
- `Box<T>`
- `Rc<T>`
- `Arc<T>`
- `HashMap<K, V>`
- `BTreeMap<K, V>`
- `VecDeque<T>`
- `RefCell<T>`
- `RwLock<T>`

## 完整示例

```rust
use memscope_rs::{global_tracker, init_global_tracking, track};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化
    init_global_tracking()?;

    // 获取追踪器
    let tracker = global_tracker()?;

    // 追踪各种类型
    let vec_data = vec![1, 2, 3, 4, 5];
    track!(tracker, vec_data);

    let string_data = String::from("Hello, memscope!");
    track!(tracker, string_data);

    let boxed_data = Box::new(42);
    track!(tracker, boxed_data);

    // 获取统计信息
    let stats = tracker.get_stats();
    println!("追踪统计: {:?}", stats);

    // 导出数据
    tracker.export_json("output")?;
    tracker.export_html("output")?;

    println!("数据已导出到 output/ 目录");

    Ok(())
}
```

## 注意事项

1. **线程安全**：全局追踪器是线程安全的，可以在多线程环境中使用
2. **性能影响**：追踪会带来一定的性能开销，建议仅在开发和调试时使用
3. **内存开销**：追踪本身会消耗内存，注意监控内存使用情况
4. **初始化**：虽然可以自动初始化，但建议在程序开始时显式调用 `init_global_tracking()`

## 故障排除

### 错误：AlreadyInitialized

如果你多次调用 `init_global_tracking()`，会收到 `AlreadyInitialized` 错误。这是正常的，因为全局追踪器只能初始化一次。

### 错误：NotInitialized

如果在未初始化的情况下调用 `global_tracker()`，会收到 `NotInitialized` 错误。确保在调用 `global_tracker()` 之前先调用 `init_global_tracking()`。

### 导出失败

确保目标目录存在且有写入权限。如果目录不存在，需要先创建：
```rust
use std::fs;
fs::create_dir_all("output")?;
```

## 更多示例

查看 `examples/` 目录获取更多使用示例：

- `basic_usage.rs` - 基本用法
- `global_tracker_showcase.rs` - 全局追踪器展示
- `complex_lifecycle_showcase.rs` - 复杂生命周期示例
- `complex_multithread_showcase.rs` - 多线程示例
- `comprehensive_async_showcase.rs` - 异步编程示例
- `unsafe_ffi_demo.rs` - 不安全代码和 FFI 示例
- `merkle_tree.rs` - Merkle 树实现示例

## 关系推断系统

memscope-rs 提供了强大的内存关系推断引擎，能够自动检测分配之间的语义关系。

### 支持的关系类型

| 关系类型 | 描述 | 检测方法 |
|----------|------|----------|
| **Owner** | A 拥有或指向 B | 指针扫描 - 在 A 的内存中找到指向 B 的指针 |
| **Slice** | A 是 B 的子视图 | 地址范围检测 - A 的指针在 B 的内部 |
| **Clone** | A 是 B 的克隆 | 内容相似度 + 时间窗口 + 调用栈匹配 |
| **Shared** | A 和 B 共享所有权 | Arc/Rc control block 模式识别 |

### 使用方法

```rust
use memscope_rs::analysis::relation_inference::{RelationGraphBuilder, Relation};

// 从活跃分配构建关系图
let graph = RelationGraphBuilder::build(&allocations, None);

// 查询关系
for edge in graph.edges() {
    println!("{:?}: {} -> {}", edge.relation, edge.from, edge.to);
}

// 检测循环引用
let cycles = graph.detect_cycles();
if !cycles.is_empty() {
    println!("检测到 {} 个循环引用", cycles.len());
}

// 获取所有节点
let nodes = graph.all_nodes();
```

### 准确率数据

基于真实测试数据的准确率：

```
=== Clone 检测准确率 ===
Precision: 100.00%
Recall: 100.00%
F1 Score: 100.00%

=== Owner 检测准确率 ===
✅ Box<Vec> 关系正确检测
✅ 独立 Vec 无误报

=== 性能数据 ===
1000 分配构建时间: ~230ms
```

### 配置选项

```rust
use memscope_rs::analysis::relation_inference::{GraphBuilderConfig, CloneConfig};

let config = GraphBuilderConfig {
    clone_config: CloneConfig {
        min_similarity: 0.8,              // 最小相似度阈值
        min_similarity_no_stack_hash: 0.95, // 无调用栈时的更严格阈值
        max_time_diff_ns: 10_000_000,     // 10ms 时间窗口
        max_clone_edges_per_node: 10,     // 每节点最大克隆边数
        ..Default::default()
    },
};

let graph = RelationGraphBuilder::build(&allocations, Some(config));
```

### 注意事项

1. **Owner 检测**：需要元数据在堆上（如 `Box<Vec>`），栈上的元数据无法被扫描
2. **Clone 检测**：依赖调用栈哈希，相同调用栈的分配会被分组比较
3. **Shared 检测**：依赖 Owner 关系，需要先检测 Owner 后再检测 Shared
4. **性能**：使用滑动时间窗口避免 O(n²) 复杂度

## 异步任务追踪

memscope-rs 提供了完整的异步任务内存追踪功能，可以追踪 tokio 任务的内存使用情况，并检测僵尸任务。

### 核心概念

| 概念 | 说明 |
|------|------|
| **Task ID** | 全局唯一任务 ID，永不回收，确保准确追踪 |
| **Tokio Task ID** | Tokio 运行时的任务 ID，可能被回收，仅作为 metadata |
| **Zombie Task** | 已启动但从未完成的任务，可能表示内存泄漏 |

### API 选择指南

```
┌─────────────────────────────────────────────────────────────────────┐
│                        何时使用哪个 API                               │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  场景 1: 在 async 代码中追踪                                         │
│  ─────────────────────────────────────                              │
│  ✅ 使用 track_in_tokio_task()                                       │
│     自动检测 tokio task ID，无需手动设置                              │
│                                                                     │
│  let (task_id, result) = tracker.track_in_tokio_task(               │
│      "my_task".to_string(),                                          │
│      async move {                                                    │
│          // 你的 async 代码                                          │
│      }                                                               │
│  ).await;                                                           │
│                                                                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  场景 2: 在同步代码中手动设置 task context                            │
│  ─────────────────────────────────────                              │
│  ✅ 使用 enter_task() 或 with_task()                                  │
│     手动设置 task ID，通常用于测试或特殊场景                           │
│                                                                     │
│  let task_id = 42u64;                                               │
│  let guard = AsyncTracker::enter_task(task_id);                       │
│  // 或                                                              │
│  AsyncTracker::with_task(task_id, || {                               │
│      // 同步代码                                                     │
│  });                                                                │
│                                                                     │
├─────────────────────────────────────────────────────────────────────┤
│                                                                     │
│  场景 3: 在 tokio 上下文中自动工作                                    │
│  ─────────────────────────────────────                              │
│  ✅ track_as() 在 tokio 上下文中自动获取 task ID                      │
│     但这需要用户在 async 入口处调用 enter_task() 设置 context          │
│                                                                     │
│  // 在 async handler 入口                                            │
│  let task_id = generate_unique_task_id();                            │
│  let _guard = AsyncTracker::enter_task(task_id);                     │
│                                                                     │
│  // 之后所有 track_as() 调用会自动关联到这个 task                      │
│  tracker.track_as(&data, "my_data", file, line);                    │
│                                                                     │
└─────────────────────────────────────────────────────────────────────┘
```

### 使用示例

#### 示例 1: track_in_tokio_task (推荐)

```rust
use memscope_rs::{global_tracker, init_global_tracking};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    init_global_tracking()?;
    let tracker = global_tracker()?;

    // 使用 track_in_tokio_task 自动追踪
    let (task_id, result) = tracker
        .async_tracker()
        .track_in_tokio_task("http_handler".to_string(), async {
            // 模拟处理请求
            let data = vec![1u8; 1024];
            tracker.track_as(&data, "request_data", file!(), line!());

            // 模拟一些延迟
            tokio::time::sleep(tokio::time::Duration::from_millis(100)).await;

            "response"
        })
        .await;

    println!("Task ID: {}, Result: {}", task_id, result);

    // 导出数据
    tracker.export_json("output")?;

    Ok(())
}
```

#### 示例 2: 手动设置 task context

```rust
use memscope_rs::{global_tracker, init_global_tracking, capture::backends::async_tracker::AsyncTracker};

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    init_global_tracking()?;
    let tracker = global_tracker()?;

    // 生成唯一 task ID
    let task_id = generate_unique_task_id();

    // 设置 task context
    let _guard = AsyncTracker::enter_task(task_id);

    // 在这个 task context 中，所有 track_as() 调用都会关联到这个 task
    let data = vec![1u8; 1024];
    tracker.track_as(&data, "my_data", file!(), line!());

    // 清理
    drop(_guard);

    Ok(())
}
```

#### 示例 3: 检测僵尸任务

```rust
use memscope_rs::{global_tracker, init_global_tracking};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    init_global_tracking()?;
    let tracker = global_tracker()?;

    // 启动一些任务...
    // ...

    // 在程序结束时检测僵尸任务
    let zombies = tracker.async_tracker().detect_zombie_tasks();

    if !zombies.is_empty() {
        println!("警告: 发现 {} 个僵尸任务!", zombies.len());
        for task_id in &zombies {
            println!("  - Task ID: {}", task_id);
        }
    }

    // 获取僵尸任务统计
    let (zombie_count, total_count) = tracker.async_tracker().zombie_task_stats();
    println!(
        "僵尸任务: {}/{} ({:.1}%)",
        zombie_count,
        total_count,
        if total_count > 0 {
            (zombie_count as f64 / total_count as f64) * 100.0
        } else {
            0.0
        }
    );

    Ok(())
}
```

### 数据流

```
track_in_tokio_task() 或 track_as()
            │
            ▼
AsyncTracker::get_current_task()
            │
            ▼
track_allocation_with_location()
            │
            ▼
┌───────────────────────────────────────┐
│         AsyncTracker 内部状态          │
│  - allocations HashMap                │
│  - profiles HashMap (TaskMemoryProfile)│
│  - stats                              │
└───────────────────────────────────────┘
            │
            ▼
export_all_json() → async_analysis.json
            │
            ▼
输出文件:
  - task_profiles: 每个任务的内存使用情况
  - summary: 统计摘要
```

### 任务 ID 设计说明

 Tokio 的 task ID 会在任务完成后被回收复用，这可能导致 ID 冲突。
 memscope-rs 使用双重 ID 系统解决这个问题：

```rust
struct TaskMemoryProfile {
    task_id: u64,        // 全局唯一，永不回收 (TASK_COUNTER)
    tokio_task_id: u64, // Tokio 运行时 ID，可能回收 (作为 metadata)
}
```

这样既保证了追踪的准确性（使用永不回收的 task_id），又保留了调试信息（tokio_task_id 可以关联到 tokio runtime）。

### 注意事项

1. **性能影响**：异步追踪会带来一定开销，建议仅在开发和调试时启用
2. **Task ID 唯一性**：使用 `generate_unique_task_id()` 生成的任务 ID 永不重复
3. **生命周期**：确保 `track_task_end()` 在任务完成时被调用，以正确计算任务持续时间
4. **僵尸任务**：未完成的任务会被标记为僵尸任务，可能表示资源泄漏

## 统一分析 API (v0.2.0 新增)

memscope-rs v0.2.0 引入了全新的统一分析 API，提供了一个简洁、高效的分析入口。

### 核心概念

| 概念 | 说明 |
|------|------|
| **Analyzer** | 统一分析入口，整合所有分析功能 |
| **MemoryView** | 统一读模型，复用 Snapshot 避免重复构建 |
| **Lazy Initialization** | 延迟初始化，按需加载分析模块 |

### 快速开始

```rust
use memscope_rs::{global_tracker, init_global_tracking, analyzer};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    // 初始化追踪器
    init_global_tracking()?;
    let tracker = global_tracker()?;

    // 追踪一些数据
    let data = vec![1, 2, 3, 4, 5];
    tracker.track(&data);

    // 创建统一分析器
    let mut az = analyzer(&tracker)?;

    // 运行完整分析
    let report = az.analyze();
    println!("{}", report.summary());

    // 或使用特定的分析功能
    let leaks = az.quick_leak_check();
    println!("泄漏数量: {}", leaks.leak_count);

    let cycles = az.quick_cycle_check();
    println!("循环引用数量: {}", cycles.cycle_count);

    let metrics = az.quick_metrics();
    println!("分配总数: {}", metrics.allocation_count);

    Ok(())
}
```

### 详细 API

#### 1. 创建 Analyzer

```rust
use memscope_rs::{global_tracker, init_global_tracking, analyzer};

init_global_tracking()?;
let tracker = global_tracker()?;

// 创建分析器（推荐方式）
let mut az = analyzer(&tracker)?;

// 或从 MemoryView 创建
use memscope_rs::view::MemoryView;
let view = MemoryView::from_tracker(tracker);
let mut az = memscope_rs::Analyzer::from_view(view);
```

#### 2. 图分析

```rust
// 获取图分析（延迟初始化）
let graph = az.graph();

// 检测循环引用
let cycles = graph.cycles();
println!("循环引用数量: {}", cycles.cycle_count);

// 获取所有权统计
let stats = graph.ownership_stats();
println!("对象总数: {}", stats.total_objects);
println!("总字节数: {}", stats.total_bytes);
println!("唯一类型数: {}", stats.unique_types);

// 获取关系统计
let relations = graph.relationship_stats();
println!("所有权边: {}", relations.ownership_edges);
println!("借用边: {}", relations.borrow_edges);
println!("克隆边: {}", relations.clone_edges);
```

#### 3. 检测分析

```rust
// 获取检测分析（延迟初始化）
let detect = az.detect();

// 泄漏检测
let leaks = detect.leaks();
println!("泄漏数量: {}", leaks.leak_count);
println!("泄漏字节数: {}", leaks.total_leaked_bytes);

// 使用后释放检测
let uaf = detect.uaf();
println!("UAF 数量: {}", uaf.uaf_count);

// 安全分析
let safety = detect.safety();
println!("安全问题数量: {}", safety.issue_count);

// 获取摘要
let summary = detect.summary();
println!("泄漏数量: {}", summary.leak_count);
println!("安全问题数量: {}", summary.safety_issues);
```

#### 4. 指标分析

```rust
// 获取指标分析（延迟初始化）
let metrics = az.metrics();

// 获取摘要
let summary = metrics.summary();
println!("分配总数: {}", summary.allocation_count);
println!("总字节数: {}", summary.total_bytes);
println!("峰值内存: {}", summary.peak_bytes);
println!("线程数: {}", summary.thread_count);

// 按大小排序
let top_allocations = metrics.top_by_size(10);
for alloc in top_allocations {
    println!("  {} bytes - {}", alloc.size, alloc.type_name.unwrap_or_else(|| "unknown".to_string()));
}

// 按类型统计
let by_type = metrics.by_type();
for (type_name, metric) in by_type {
    println!("  {} - {} 个分配, {} 字节", type_name, metric.count, metric.total_bytes);
}

// 按线程统计
let by_thread = metrics.by_thread();
for (thread_id, metric) in by_thread {
    println!("  线程 {} - {} 个分配, {} 字节", thread_id, metric.allocation_count, metric.total_bytes);
}

// 获取大小分布
let distribution = metrics.size_distribution();
println!("  最小: {} 字节", distribution.min);
println!("  最大: {} 字节", distribution.max);
println!("  平均: {} 字节", distribution.avg);
```

#### 5. 时间线分析

```rust
// 获取时间线分析（延迟初始化）
let timeline = az.timeline();

// 查询特定时间范围的事件
let events = timeline.query(start_time, end_time);
println!("时间范围内的分配数量: {}", events.len());

// 获取分配速率
let rate = timeline.allocation_rate(time_window_ns);
println!("分配速率: {} 分配/秒", rate.allocations_per_sec);
println!("字节速率: {} 字节/秒", rate.bytes_per_sec);
```

#### 6. 导出

```rust
// 获取导出引擎
let exporter = az.export();

// 导出为 JSON
exporter.json("output/memory_analysis.json")?;

// 导出为 HTML
exporter.html("output/dashboard.html")?;

// 生成 JSON 字符串
let json = exporter.to_json()?;
println!("{}", json);

// 生成 HTML 字符串
let html = exporter.to_html()?;
println!("{}", html);
```

### 架构优势

```mermaid
graph TB
    A[用户代码] --> B[analyzer 函数]
    B --> C[Analyzer 统一入口]
    C --> D[MemoryView 统一读模型]
    D --> E[EventStore 事件存储]
    
    C --> F[GraphAnalysis]
    C --> G[DetectionAnalysis]
    C --> H[MetricsAnalysis]
    C --> I[TimelineAnalysis]
    C --> J[ClassificationAnalysis]
    C --> K[SafetyAnalysis]
    
    C --> L[ExportEngine]
    L --> M[JSON/HTML 导出]
    
    style C fill:#4CAF50
    style D fill:#2196F3
    style E fill:#FF9800
```

### 设计原则

| 原则 | 说明 |
|------|------|
| **数据源唯一** | MemoryView 是唯一的数据源，避免重复构建 |
| **复用快照** | 复用 MemorySnapshot，提高效率 |
| **入口统一** | Analyzer 统一所有分析功能 |
| **职责分离** | 每个分析模块职责明确 |
| **延迟初始化** | 按需加载，减少不必要的计算 |
| **零破坏** | 完全兼容现有 API |

### 性能优化

1. **Lazy Initialization** - 分析模块只在首次访问时初始化
2. **Snapshot 复用** - MemoryView 复用 MemorySnapshot，避免重复构建 allocations
3. **高效过滤** - FilterBuilder 提供高效的过滤功能

### 使用建议

1. **推荐使用** `analyzer(&tracker)` 作为统一入口
2. **对于简单场景**，使用快速检查方法（`quick_leak_check`, `quick_cycle_check` 等）
3. **对于复杂场景**，使用完整分析（`az.analyze()`）
4. **对于特定需求**，使用特定的分析模块（`az.graph()`, `az.detect()` 等）

### 迁移指南

如果你使用的是旧版 API，可以轻松迁移到新的统一分析 API：

```rust
// 旧版 API
let tracker = global_tracker()?;
let stats = tracker.get_stats();
let leaks = tracker.passport_tracker().detect_leaks_at_shutdown();

// 新版 API
let mut az = analyzer(&tracker)?;
let stats = az.quick_metrics();
let leaks = az.quick_leak_check();
```

### 更多示例

查看 `examples/` 目录中的示例代码：

- `basic_usage.rs` - 基本用法
- `real_world_demo.rs` - 真实世界示例
- 展示如何使用新的 analyzer API