rtsp_tensorrt/docs/performance_tuning.md

10 KiB
Raw Permalink Blame History

性能调优指南

1. 系统优化

1.1 GPU设置

  • 设置CUDA计算能力
  • GPU功耗模式调整
  • 显存预分配策略

1.2 系统配置

  • CPU频率调节
  • 系统IO优化
  • 网络参数调整

2. Pipeline优化

2.1 多线程优化

  • 线程池配置
  • 任务调度策略
  • 线程亲和性设置

2.2 内存优化

  • 零拷贝传输
  • 内存池管理
  • 显存复用策略

2.3 批处理优化

  • 动态批大小
  • 批处理超时设置
  • 帧积累策略

2.4 输入输出映射优化

  • 映射关系管理
    • 使用哈希表实现 O(1) 查找
    • 缓存常用映射关系
    • 避免频繁修改映射
  • 并发访问优化
    • 读写锁分离
    • 细粒度锁定
    • 避免长时间持锁
  • 资源管理优化
    • 智能指针管理生命周期
    • 内存池复用
    • 延迟初始化策略

3. 推理优化

3.1 TensorRT优化

  • FP16/INT8量化
  • 动态Shape处理
  • Workspace大小设置

3.2 预处理优化

  • GPU预处理
  • 并行预处理
  • 数据预取

4. IO优化

4.1 输入优化

  • RTSP缓冲设置
  • 解码器选择
  • 帧采样策略

4.2 输出优化

  • 编码器参数
  • 推流缓冲
  • 写入策略

4.3 映射关系优化

  • 合理配置映射关系
    • 避免不必要的多重映射
    • 根据实际需求设置映射
    • 定期清理无效映射
  • 输出目标管理
    • 复用输出目标
    • 动态调整目标参数
    • 按需初始化资源
  • 性能监控
    • 监控映射状态
    • 跟踪资源使用
    • 分析性能瓶颈

5. 监控与调试

5.1 性能指标

  • GPU利用率
  • 内存使用
  • 处理延迟
  • 吞吐量统计

5.2 性能分析

  • NVPROF分析
  • 内存泄漏检测
  • 性能瓶颈定位

5.3 映射性能监控

  • 映射关系统计

    // 获取映射统计信息
    size_t total_sources = input_manager.getAllSourceNames().size();
    size_t total_targets = output_manager.getTargetCount();
    
    // 检查映射效率
    for (const auto& source : input_manager.getAllSourceNames()) {
        std::vector<std::string> targets;
        input_manager.getOutputTargets(source, targets);
        // 分析映射数量和资源使用
    }
    
  • 资源使用监控

    // 监控输出目标状态
    for (const auto& target : output_manager.getTargetNames()) {
        std::string error_msg;
        bool status = output_manager.getTargetStatus(target, error_msg);
        // 记录状态和错误信息
    }
    
  • 性能指标收集

    // 收集写入性能指标
    struct PerformanceMetrics {
        double avg_write_time;
        double max_write_time;
        size_t total_frames;
        size_t dropped_frames;
    };
    
    // 定期更新和分析性能指标
    void updateMetrics(const std::string& target, double write_time) {
        metrics[target].avg_write_time = 
            (metrics[target].avg_write_time * metrics[target].total_frames + write_time) /
            (metrics[target].total_frames + 1);
        metrics[target].max_write_time = std::max(metrics[target].max_write_time, write_time);
        metrics[target].total_frames++;
    }
    

6. 映射性能优化建议

6.1 配置优化

  1. 映射关系设计

    • 避免创建不必要的映射
    • 合理分组输出目标
    • 根据实际需求配置映射
  2. 缓冲区设置

    • 为不同类型的输出配置适当的缓冲区
    • 考虑输出目标的特性
    • 平衡内存使用和性能
  3. 参数调优

    • 根据输出目标类型设置合适的参数
    • 考虑网络条件和系统资源
    • 动态调整参数以适应变化

6.2 代码优化

  1. 映射查找优化

    // 使用哈希表存储映射关系
    std::unordered_map<std::string, std::vector<std::string>> source_target_map;
    
    // 缓存常用映射
    std::unordered_map<std::string, std::vector<std::string>> mapping_cache;
    
    // 快速查找实现
    bool getTargets(const std::string& source, std::vector<std::string>& targets) {
        auto it = mapping_cache.find(source);
        if (it != mapping_cache.end()) {
            targets = it->second;
            return true;
        }
    
        auto map_it = source_target_map.find(source);
        if (map_it != source_target_map.end()) {
            targets = map_it->second;
            mapping_cache[source] = targets;
            return true;
        }
        return false;
    }
    
  2. 并发访问优化

    // 使用读写锁
    mutable std::shared_mutex mapping_mutex;
    
    // 读取映射关系
    bool getTargets(const std::string& source, std::vector<std::string>& targets) const {
        std::shared_lock<std::shared_mutex> lock(mapping_mutex);
        auto it = source_target_map.find(source);
        if (it != source_target_map.end()) {
            targets = it->second;
            return true;
        }
        return false;
    }
    
    // 更新映射关系
    bool updateMapping(const std::string& source, const std::vector<std::string>& targets) {
        std::unique_lock<std::shared_mutex> lock(mapping_mutex);
        source_target_map[source] = targets;
        mapping_cache.erase(source);  // 清除缓存
        return true;
    }
    
  3. 资源管理优化

    // 使用智能指针管理资源
    class OutputTarget {
    public:
        using Ptr = std::shared_ptr<OutputTarget>;
        static Ptr create(const OutputTargetConfig& config) {
            return std::make_shared<OutputTarget>(config);
        }
    };
    
    // 资源池管理
    class ResourcePool {
    public:
        OutputTarget::Ptr acquireTarget(const std::string& name) {
            std::lock_guard<std::mutex> lock(pool_mutex);
            auto it = available_targets.find(name);
            if (it != available_targets.end()) {
                auto target = it->second;
                available_targets.erase(it);
                return target;
            }
            return nullptr;
        }
    
        void releaseTarget(const std::string& name, OutputTarget::Ptr target) {
            std::lock_guard<std::mutex> lock(pool_mutex);
            available_targets[name] = target;
        }
    
    private:
        std::mutex pool_mutex;
        std::unordered_map<std::string, OutputTarget::Ptr> available_targets;
    };
    

6.3 性能监控

  1. 映射效率监控

    struct MappingMetrics {
        size_t mapping_updates;
        size_t cache_hits;
        size_t cache_misses;
        double avg_lookup_time;
    };
    
    void updateMappingMetrics(const std::string& source, bool cache_hit, double lookup_time) {
        auto& metrics = mapping_metrics[source];
        metrics.mapping_updates++;
        cache_hit ? metrics.cache_hits++ : metrics.cache_misses++;
        metrics.avg_lookup_time = 
            (metrics.avg_lookup_time * (metrics.cache_hits + metrics.cache_misses - 1) + lookup_time) /
            (metrics.cache_hits + metrics.cache_misses);
    }
    
  2. 资源使用监控

    struct ResourceMetrics {
        size_t active_targets;
        size_t total_memory;
        size_t peak_memory;
        double avg_utilization;
    };
    
    void updateResourceMetrics(const std::string& target, size_t memory_usage) {
        auto& metrics = resource_metrics[target];
        metrics.total_memory = memory_usage;
        metrics.peak_memory = std::max(metrics.peak_memory, memory_usage);
        // 更新其他指标...
    }
    

6.4 常见问题解决

  1. 映射性能问题

    • 检查映射关系是否合理
    • 优化缓存策略
    • 调整锁粒度
  2. 资源使用问题

    • 监控内存使用
    • 及时释放资源
    • 优化资源池配置
  3. 并发访问问题

    • 使用适当的锁策略
    • 减少锁的持有时间
    • 考虑无锁实现

RTSP 流读取优化

延迟与流畅度平衡

RTSP 流的读取性能主要受以下参数影响:

  1. 缓冲区大小 (buffer_size)

    • 较大的缓冲区可以提供更流畅的播放体验,但会增加延迟
    • 较小的缓冲区可以降低延迟,但可能导致画面卡顿
    • 建议值:
      • 低延迟场景5-10
      • 一般场景30
      • 高流畅度场景50-100
  2. 帧率控制 (target_fps)

    • 限制帧率可以减少系统资源占用
    • 建议根据实际需求设置,通常不需要超过显示器刷新率
    • 常见设置:
      • 监控场景15-20 fps
      • 一般场景25-30 fps
      • 高帧率场景60 fps
  3. 超时设置 (frame_timeout_ms)

    • 较短的超时时间可以更快地检测到连接问题
    • 较长的超时时间可以容忍网络波动
    • 建议值:
      • 局域网1000-2000 ms
      • 互联网3000-5000 ms
  4. 重连策略

    • max_retry_countretry_interval_ms 的组合决定了重连行为
    • 建议值:
      • 稳定网络:重试 3 次,间隔 1000ms
      • 不稳定网络:重试 5-10 次,间隔 2000-3000ms

优化建议

  1. 网络优化

    • 使用有线网络而不是无线网络
    • 确保网络带宽充足
    • 考虑使用 QoS 策略优先处理 RTSP 流量
  2. 编码设置

    • 使用 MJPEG 编码可以降低延迟
    • H.264/H.265 编码可以节省带宽但会增加延迟
  3. 分辨率与帧率

    • 根据实际需求选择合适的分辨率和帧率
    • 不要盲目追求高分辨率和高帧率
  4. 内存管理

    • 避免频繁的帧拷贝
    • 考虑使用帧池来复用内存

性能监控

可以通过以下方式监控 RTSP 流的性能:

  1. 帧率监控

    float current_fps = reader.getCurrentFps();
    
  2. 连接状态监控

    bool is_connected = reader.isConnected();
    

常见问题解决

  1. 画面卡顿

    • 增加缓冲区大小
    • 检查网络带宽
    • 降低分辨率或帧率
  2. 延迟过高

    • 减小缓冲区大小
    • 使用 MJPEG 编码
    • 优化网络路径
  3. 频繁断连

    • 增加超时时间
    • 调整重连策略
    • 检查网络稳定性