개념
"빠르다" 는 판정이 아니다
웹 서비스 성능은 분포 로 판정한다 — p95 가 기준 안에 있으면 통과다. 느린 요청 1%가 있어도 서비스는 성립한다.
경질 실시간(hard real-time) 시스템은 다르다. 한 번이라도 마감을 넘기면 실패 다. 에어백 전개 판단이 100번 중 99번 제때 되는 것은 통과가 아니다. 그래서 판정 기준이 최악의 경우 로 바뀐다.
이 차이가 QA 의 작업을 바꾼다.
| 분포 기준(웹) | 최악 기준(실시간) | |
|---|---|---|
| 측정 목표 | 백분위와 꼬리 | 최악값의 상한 |
| 통과 조건 | p95·p99 기준 이내 | 모든 경우에 마감 이내 |
| 측정만으로 | 충분하다 | 충분하지 않다 |
| 필요한 것 | 부하와 시간 | 측정 + 분석 |
"측정만으로 충분하지 않다" 가 이 레슨의 출발점 이다.
측정한 최대값은 WCET 가 아니다
최악 실행 시간(WCET, Worst-Case Execution Time) 은 어떤 입력·어떤 상태에서도 그 이상 걸리지 않는 값 이다. 그런데 측정으로 얻는 것은 "내가 시험한 경우들의 최대" 다. 둘은 다르다.
실제 WCET (알 수 없음)
↓
|-----------------●---------|
↑ ↑
측정한 최대값 분석이 주는 상한
(과소 추정 위험) (안전하지만 비관적)측정이 WCET 에 닿지 못하는 이유는 넷이다.
1) 최악 경로를 안 밟았다. 가장 오래 걸리는 분기 조합이 실행되지 않았다. 분기가 많으면 경로 수가 폭발하고, 그 중 최악이 어느 것인지 모른다.
2) 캐시가 따뜻했다. 반복 실행하면 명령·데이터가 캐시에 남아 빨라진다. 실제 최악은 캐시가 비어 있는 상태 다.
3) 간섭이 없었다. 다른 태스크·인터럽트·DMA·메모리 경쟁이 실행 시간을 늘린다. 단독 측정은 그 영향을 담지 못한다.
4) 입력 데이터가 짧았다. 반복 횟수가 입력에 비례하는 코드에서, 시험 데이터가 최악 크기가 아니었다.
그래서 측정값에 여유를 곱해 WCET 로 쓰는 관행 이 널리 있지만, 그 여유의 근거가 없으면 숫자가 아니라 희망이다. 안전이 걸린 프로젝트에서는 분석과 측정을 함께 쓰고, 어느 방법으로 얻었는지를 증거에 적는다.
분석 방법의 종류와 도구, 그리고 규격이 요구하는 수준은 해당 규격과 도구 문서에서 확인한다(원문 확인). 정적 분석은 코드와 하드웨어 모델에서 상한을 유도하고, 측정 기반·혼합 방식은 실행 기록을 결합한다 — 각 방식의 전제와 한계가 다르다.
실행 시간과 응답 시간은 다르다
여기서 가장 많이 혼동된다.
실행 시간(execution time) — 그 태스크가 CPU 를 쓰는 시간 의 합. 방해받지 않고 혼자 돌 때 걸리는 시간.
응답 시간(response time) — 태스크가 깨어난 순간부터 끝날 때까지 의 시간. 그 사이에 높은 우선순위 태스크에 선점당해 기다린 시간이 포함된다.
마감을 지키는지 판정하는 것은 응답 시간 이다. 실행 시간이 2 ms 여도, 더 높은 우선순위 태스크들에 밀려 20 ms 뒤에 끝나면 마감 10 ms 를 넘긴다.
[태스크 C(저우선순위) 의 응답 시간]
깨어남 ●
|--A실행--| |--B실행--| |--C실행--|
|<------------ 응답 시간 ------------>|
↑ C의 실행 시간은 이것뿐실행 시간만 재고 "마감 안에 끝난다" 고 보고하는 것 이 이 영역의 전형적 오류다.
응답 시간 분석 — 무엇을 더하는가
고정 우선순위 선점 스케줄링에서 널리 쓰이는 응답 시간 분석(RTA) 의 식은 이런 모양이다. 공개 교재에서 널리 인용되는 형태다.
R_i = C_i + B_i + Σ ⌈ R_i / T_j ⌉ · C_j (j = i 보다 우선순위가 높은 태스크들)
C_i : 태스크 i 의 실행 시간 (WCET)
B_i : 블로킹 — 낮은 우선순위 태스크가 공유 자원을 잡고 있어 기다리는 시간
T_j : 높은 우선순위 태스크 j 의 주기
⌈ ⌉ : 올림식 자체보다 구조가 중요하다. 응답 시간은 세 덩어리의 합이다.
- 내 실행 시간(
C_i) — 내가 CPU 를 쓰는 시간 - 블로킹(
B_i) — 낮은 우선순위 때문에 기다리는 시간(아래에서 다룬다) - 간섭(합) — 높은 우선순위 태스크들이 내 응답 구간 안에 몇 번 깨어나 얼마나 쓰는가
세 번째 항의 ⌈R_i / T_j⌉ 가 뜻하는 것은 "내가 기다리는 동안 j 가 몇 번
깨어나는가" 다. 내 응답 시간이 길어지면 그 횟수가 늘고, 그러면 응답 시간이
또 길어진다. 그래서 식을 반복 대입해 수렴시켜 푼다. 수렴하지 않고 마감을
넘어가면 일정 불가(스케줄 불가) 다.
이 식에서 QA 가 읽어야 할 실무적 함의는 셋이다.
C_i가 작아도 간섭이 크면 마감을 넘긴다. 최적화로 내 코드를 빠르게 해도 해결되지 않는 경우가 있다- 높은 우선순위 태스크의 주기를 줄이면(더 자주 깨우면) 낮은 우선순위의 응답 시간이 늘어난다. 한 태스크의 설정 변경이 다른 태스크를 깨뜨린다
- 블로킹은 우선순위와 무관하게 끼어든다. 가장 높은 우선순위 태스크도 블로킹을 겪는다
식의 정확한 형태, 적용 조건(주기·마감·독립성 가정), 그리고 확장(지터·산발 태스크·다중 코어) 은 실시간 시스템 교재와 해당 규격에서 확인한다(원문 확인). 전제가 깨지면 식이 성립하지 않는다 — 특히 다중 코어는 전혀 다른 분석이 필요하다.
CPU 사용률만으로 판정할 수 없다
"CPU 사용률 70% 니까 여유 있다" 는 흔한 보고이고, 실시간 판정으로는 쓸 수 없다.
고정 우선순위에서 주기가 짧은 태스크에 높은 우선순위를 주는 방식(주기 단조)
의 사용률 상한 으로 널리 인용되는 값이 있다 — 태스크 수 n 에 대해
n(2^(1/n) − 1) 이고, n 이 커지면 ln 2 ≈ 0.69 에 수렴한다.
이 상한의 정확한 적용 조건(마감이 주기와 같다, 태스크가 독립적이다 등) 은
교재 원문에서 확인한다(원문 확인).
여기서 읽을 것은 숫자가 아니라 두 가지다.
- 100% 가 기준이 아니다. 사용률이 69% 를 넘으면 상한만으로는 보장할 수 없다
- 상한은 충분 조건일 뿐이다. 상한을 넘어도 실제로는 스케줄 가능할 수 있고, 그것을 판정하려면 응답 시간 분석 이 필요하다
그래서 보고 문장이 달라진다. "CPU 사용률 70%" 가 아니라 "응답 시간 분석 결과 모든 태스크가 마감 대비 N% 여유를 갖는다" 가 판정이다.
우선순위 역전과 블로킹
B_i 항이 생기는 이유다. 구조는 이렇다.
낮은 우선순위 L 이 공유 자원(뮤텍스) 을 잡는다
↓
높은 우선순위 H 가 깨어나 같은 자원을 요구한다 → H 가 기다린다 (여기까지는 정상)
↓
중간 우선순위 M 이 깨어나 L 을 선점한다
↓
L 이 못 돌아 자원을 놓지 못하고, H 는 M 때문에 계속 기다린다 ← 우선순위 역전H 가 M 에게 밀리는 것 이 역전이고, M 이 길게 돌면 H 의 지연이 한없이 늘어날 수 있다. 이것이 실시간 시스템의 고전적 사고 원인이다.
대응 수단으로 우선순위 상속(자원을 잡은 태스크의 우선순위를 요구자 수준으로 올린다) 과 우선순위 상한 계열의 프로토콜이 쓰인다. 공개 교재는 상한 계열에서 한 태스크가 낮은 우선순위에 의해 한 번만 블로킹된다는 성질을 설명한다. 각 프로토콜의 정확한 정의·성질·사용 중인 RTOS 의 지원 범위와 설정 방법은 교재와 RTOS 공식 문서에서 확인한다(원문 확인).
QA 가 확인할 질문은 네 개다.
- 공유 자원 목록이 있는가. 어느 자원을 어느 태스크들이 공유하는지
- 보호 수단이 무엇인가. 뮤텍스인가 인터럽트 금지인가, 프로토콜 설정이 켜져 있는가
- 임계 구간이 얼마나 긴가. 블로킹 시간의 상한이 여기서 나온다
- 임계 구간 안에서 블로킹되는 호출을 하지 않는가. 자원을 잡은 채 대기하면 블로킹 시간이 폭발한다
네 번째가 코드 검토에서 잡아야 하는 항목 이다. 임계 구간 안의 로그 출력, 메모리 할당, 다른 뮤텍스 획득, 긴 반복이 전형적 문제다.
QA 가 분석 결과를 검증하는 방법
분석은 대개 설계·플랫폼 담당이 수행한다. QA 의 자리는 분석의 전제가 실제와 맞는지 확인하는 것 이다. 분석이 틀리는 것은 식이 틀려서가 아니라 입력이 틀려서 다.
| 분석의 전제 | QA 가 확인할 방법 |
|---|---|
| 태스크 목록과 우선순위 | 실제 설정(RTOS 구성·코드) 과 대조 |
| 주기와 마감 | 실제 깨어나는 주기를 관측으로 확인 |
실행 시간(C_i) | 최악 경로를 만든 조건에서 측정, 분석값과 비교 |
블로킹(B_i) | 공유 자원 목록과 임계 구간 길이 확인 |
| 인터럽트 부하 | 분석에 들어갔는가, 실제 발생률과 맞는가 |
| 독립성 가정 | 태스크 간 대기·동기화가 실제로 없는가 |
다섯 번째가 자주 빠진다. 인터럽트는 모든 태스크보다 우선하므로, 인터럽트 부하가 분석에 들어가지 않으면 전부 과소 추정된다. 특히 통신 폭주 시 인터럽트 발생률 이 평시와 다르다 — 레슨 3 의 CAN 부하, 레슨 2 의 직렬 통신에서 이 조건을 만들 수 있다.
여섯 번째도 중요하다. 분석식의 전제는 태스크가 독립적이라는 것이다. 태스크 A 가 B 의 완료를 기다리는 구조가 들어가 있으면 식이 성립하지 않는다. 설계 문서에 없는 대기가 코드에 있는 경우가 실제로 있다.
시험으로 만드는 최악 조건
분석값을 검증하려면 최악에 가까운 조건을 의도적으로 만든다. 축은 다섯이다.
- 최악 경로 — 가장 긴 분기 조합으로 가는 입력. 레슨 8 의 호스트 단위 시험에서 어느 입력이 어느 경로로 가는지 파악해 두면 여기서 쓰인다
- 캐시 불리 — 반복 실행으로 따뜻해진 캐시를 쓰지 않도록, 사이에 다른 작업을 끼우거나 첫 실행을 측정한다
- 동시 부하 — 모든 태스크가 함께 도는 상태, 그리고 여러 태스크의 주기가 동시에 겹치는 순간(임계 순간) 을 만든다
- 인터럽트 폭주 — 통신·센서 인터럽트를 최대 발생률로. 레슨 3·레슨 6 의 수단을 쓴다
- 최대 입력 — 반복 횟수가 입력에 비례하는 코드에 최대 크기 데이터를 넣는다
세 번째가 가장 중요하고 가장 잘 빠진다. 모든 태스크의 주기가 같은 순간에 겹치면 간섭이 최대가 된다. 그런 순간은 드물게 발생하므로 일반 시험에서는 만나지 못하고, 운영 몇 달 뒤에 간헐적 마감 초과로 나타난다. 의도적으로 겹치게 만드는 시작 조건을 설계한다.
측정 방법과 그 영향
측정 자체가 대상을 바꾼다는 문제는 모듈 63 레슨 4 에서 다뤘다. 실시간 측정에서 구체적으로 나타나는 모양이다.
| 방법 | 오버헤드 | 정확도 |
|---|---|---|
| 소프트웨어 타이머로 자기 측정 | 측정 코드가 결과에 포함 | 오버헤드만큼 과대 |
| 출력 핀 토글 + 계측기 | 매우 작음 | 높음(레슨 4) |
| 추적 포트·하드웨어 추적 | 작음 | 높음, 장비 필요 |
| RTOS 의 통계 기능 | 중간 | 설정에 따라 다름, 평균 중심일 수 있다 |
RTOS 통계 기능을 쓸 때 주의 — 제공하는 값이 평균인지 최대인지, 측정 주기가 어떻게 되는지 확인한다. 평균값을 최악값으로 읽으면 분석이 전부 틀어진다. 기능의 정확한 의미와 설정은 RTOS 공식 문서에서 확인한다(원문 확인).
그리고 계측된 빌드와 배포 빌드가 다르다 는 문제가 여기도 있다. 타이밍을 재려고 넣은 코드가 타이밍을 바꾼다. 레슨 8 의 두 빌드 비교, 모듈 63 레슨 4 의 계측 영향 처리를 그대로 적용한다.
여유를 숫자로 말한다
이 영역의 최종 산출물은 여유(margin) 표 다. 태스크별로 이렇게 적는다.
| 태스크 | 마감 | 분석 응답 시간 | 측정 최대 | 여유 | 근거 |
|---|---|---|---|---|---|
| 제어 주기 | (요구) | (분석) | (측정) | (계산) | 분석 방법·측정 조건 |
여유 요구 수준은 상상해 넣지 않는다. 몇 %를 여유로 요구할지는 요구사항과 규격이 정한다(원문 확인). QA 의 일은 그 자리에 숫자가 필요하다는 것을 지적하고 누가 정할지 묻는 것 이다 — 모듈 31 레슨 3, 모듈 40 레슨 7 과 같은 원칙.
그리고 한계에 붙은 값을 통과로 보지 않는다. 여유가 거의 없는 태스크는 다음 변경에서 바로 넘어간다. 여유 표에 "다음 변경에서 위험한 태스크" 열을 두면 설계 논의에 바로 쓰인다.
실무에서 왜 필요한가
실시간 시스템에서 가장 찾기 어려운 결함이 간헐적 마감 초과 다. 재현되지 않고, 로그에는 "가끔 반응이 늦다" 만 남는다. 원인은 거의 항상 이 레슨의 범위에 있다 — 최악 경로를 밟은 경우, 주기가 겹친 순간, 인터럽트 폭주, 우선순위 역전.
그리고 이 결함은 기능 시험으로 잡히지 않는다. 기능은 정상이고 시간만 늦다. 그래서 분석의 전제를 확인하고 최악 조건을 의도적으로 만드는 작업 이 없으면 운영에서 처음 만난다.
QA 가 기여하는 가장 큰 지점은 분석의 전제 확인 이다. 분석은 플랫폼 담당이 하지만, 그 입력(태스크 목록·주기·우선순위·인터럽트 부하·공유 자원) 이 실제와 맞는지는 아무도 보지 않는 경우가 많다. 코드와 설정을 대조해 어긋난 곳을 찾아내는 것은 전형적인 QA 작업이고, 한 건만 찾아도 분석 전체가 다시 돌아간다.
두 번째 기여는 용어를 바로잡는 것 이다. "실행 시간" 과 "응답 시간" 을 섞어 쓰는 회의, "CPU 사용률 70%" 를 여유의 근거로 쓰는 보고는 흔하다. 구분을 아는 사람 한 명이 있으면 판정의 품질이 달라진다.