1293.71 Tick 실행 시간의 측정과 모니터링
1. Tick 실행 시간 측정의 필요성
Tick 실행 시간은 행동 트리의 단일 Tick이 시작부터 완료까지 소요하는 시간이다. 이 시간이 Tick 주기를 초과하면 Tick 오버런(overrun)이 발생하여 시스템 응답성이 저하된다. Tick 실행 시간의 측정과 모니터링은 행동 트리의 실시간 성능을 보장하고, 성능 병목을 식별하기 위한 기본적 진단 도구이다(Faconti, 2022).
2. Tick 실행 시간의 구성 요소
단일 Tick의 실행 시간은 방문되는 모든 노드의 실행 시간의 합으로 구성된다.
T_{tick} = \sum_{i \in \text{visited}} T_{node_i}
각 노드의 실행 시간은 노드 유형에 따라 달라진다.
| 노드 유형 | 통상 실행 시간 | 구성 |
|---|---|---|
| ConditionNode | 나노초~마이크로초 | 블랙보드 읽기 + 조건 평가 |
| SyncActionNode | 마이크로초~밀리초 | 경량 계산 수행 |
| StatefulActionNode (onRunning) | 마이크로초 | 상태 확인 |
| 제어 노드 | 나노초 | 자식 관리 로직 |
3. 기본 측정 방법
3.1 std::chrono를 이용한 측정
void tickLoop() {
rclcpp::Rate rate(10); // 10 Hz
while (rclcpp::ok()) {
executor_.spin_some();
auto start = std::chrono::steady_clock::now();
tree_.tickOnce();
auto end = std::chrono::steady_clock::now();
auto duration = std::chrono::duration_cast<
std::chrono::microseconds>(end - start);
RCLCPP_DEBUG(node_->get_logger(),
"Tick execution time: %ld us", duration.count());
rate.sleep();
}
}
std::chrono::steady_clock은 단조 증가하는 시계로, 시스템 시간 조정에 영향받지 않으므로 실행 시간 측정에 적합하다.
3.2 통계적 측정
단일 Tick의 실행 시간은 노드 방문 경로에 따라 변동하므로, 통계적 측정이 필요하다.
class TickMonitor {
public:
void recordTick(std::chrono::microseconds duration) {
tick_count_++;
total_time_ += duration;
if (duration > max_time_) max_time_ = duration;
if (duration < min_time_) min_time_ = duration;
// 이동 평균
avg_time_ = total_time_ / tick_count_;
// 오버런 검출
if (duration > tick_budget_) {
overrun_count_++;
}
}
void report() const {
RCLCPP_INFO(logger_,
"Tick stats: avg=%ld us, min=%ld us, max=%ld us, overruns=%d/%d",
avg_time_.count(), min_time_.count(), max_time_.count(),
overrun_count_, tick_count_);
}
private:
int tick_count_{0};
int overrun_count_{0};
std::chrono::microseconds total_time_{0};
std::chrono::microseconds max_time_{0};
std::chrono::microseconds min_time_{std::chrono::microseconds::max()};
std::chrono::microseconds avg_time_{0};
std::chrono::microseconds tick_budget_;
};
4. 노드별 실행 시간 프로파일링
Tick 전체 시간뿐 아니라, 개별 노드의 실행 시간을 측정하여 성능 병목을 식별할 수 있다. BehaviorTree.CPP v4의 로깅 인터페이스를 활용한다.
// BehaviorTree.CPP의 TreeObserver를 이용한 노드별 측정
class TickProfiler : public BT::TreeObserver {
public:
void onNodeStart(const BT::TreeNode& node) override {
start_times_[node.UID()] = std::chrono::steady_clock::now();
}
void onNodeCompleted(const BT::TreeNode& node,
BT::NodeStatus status) override {
auto end = std::chrono::steady_clock::now();
auto start = start_times_[node.UID()];
auto duration = std::chrono::duration_cast<
std::chrono::microseconds>(end - start);
node_times_[node.name()].push_back(duration);
}
void reportTopNodes(int n) const {
// 평균 실행 시간 기준 상위 N개 노드 보고
}
private:
std::unordered_map<uint16_t,
std::chrono::steady_clock::time_point> start_times_;
std::unordered_map<std::string,
std::vector<std::chrono::microseconds>> node_times_;
};
5. ROS2 진단 시스템과의 통합
Tick 실행 시간을 ROS2의 진단(diagnostics) 시스템에 발행하여, 런타임 모니터링을 수행할 수 있다.
class TickDiagnostics {
public:
void update(std::chrono::microseconds tick_time) {
diagnostic_msgs::msg::DiagnosticStatus status;
status.name = "BehaviorTree/TickTiming";
if (tick_time > tick_budget_) {
status.level = diagnostic_msgs::msg::DiagnosticStatus::WARN;
status.message = "Tick overrun detected";
} else {
status.level = diagnostic_msgs::msg::DiagnosticStatus::OK;
status.message = "Tick timing normal";
}
diagnostic_msgs::msg::KeyValue kv;
kv.key = "tick_time_us";
kv.value = std::to_string(tick_time.count());
status.values.push_back(kv);
diagnostics_pub_->publish(status);
}
};
6. 실행 시간 분포 분석
Tick 실행 시간의 분포를 분석하면 시스템의 시간적 특성을 파악할 수 있다.
\text{jitter} = T_{tick}^{max} - T_{tick}^{min}
\text{utilization} = \frac{T_{tick}^{avg}}{T_{tick\_period}} \times 100\%
활용률(utilization)이 50%를 초과하면 Tick 오버런의 위험이 증가하므로, 노드 최적화나 Tick 주기 조정을 고려해야 한다.
7. 히스토그램 기반 모니터링
Tick 실행 시간의 히스토그램을 구성하면 분포의 꼬리(tail) 특성을 파악할 수 있다. 꼬리가 긴 분포는 간헐적 오버런의 가능성을 나타낸다.
실행 시간 분포 예시:
0-1ms: ████████████████████ 85%
1-2ms: ████ 10%
2-5ms: █ 3%
5-10ms: ▌ 1.5%
>10ms: ▏ 0.5% ← 간헐적 오버런
99 백분위수(p99)가 Tick 예산 이내인지 확인하는 것이 실시간 시스템에서의 핵심적 기준이다.
참고 문헌
- Colledanchise, M., & Ogren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
- Faconti, D. (2022). BehaviorTree.CPP documentation and API reference. https://www.behaviortree.dev/