Files
ExperionCrawler/pid-그래프병목진단-수정방안.md
2026-05-08 17:22:10 +09:00

7.4 KiB
Raw Blame History

P&ID 그래프 병목 진단 및 수정 방안

작성일: 2026-05-04
대상 파일: futurePlan/End-to-End P&ID Graph Pipeline/No-10_Plant_PID.dxf
상태: 진단 완료, 수정 계획 수립


1. DXF 파일 특성

항목
파일 크기 1,174,227 라인 (약 1.1MB)
총 엔티티 28,819개
LINE 20,868개 (72.4%)
TEXT 3,562개 (12.4%)
ARC 1,324개 (4.6%)
CIRCLE 1,275개 (4.4%)
LWPOLYLINE 865개 (3.0%)
MTEXT 363개 (1.3%)
기타 102개 (0.4%)

2. 확인된 병목 지점

🔴 병목 1: Phase 2 - build_graph() 내 배관-설비 연결 로직 (HIGH)

위치: mcp-server/pipeline/topology.py:81-129

문제: LINE/LWPOLYLINE(약 21,733개)과 설비(CIRCLE/ARC/기타, 약 3,272개)를 전체 조합으로 비교

# topology.py:82-99
lines = [n for n, d in self.G.nodes(data=True) if d['type'] in ['LINE', 'LWPOLYLINE']]
for line_id in lines:  # 21,733개
    ...
    for eq_id in equipments:  # 3,272개
        eq_bbox = self.G.nodes[eq_id]['bbox']
        if line_geom.intersects(eq_bbox):      # shapely 교차 계산 (고비용)
            connected_nodes.append(eq_id)
        elif line_geom.distance(eq_bbox) < self.config['dist_threshold']:  # shapely 거리 계산 (고비용)
            connected_nodes.append(eq_id)

연산량: 21,733 × 3,272 = 약 7,110만 회의 shapely 기하학 연산
실제 성능: 10분 이상 (타임아웃 발생)


🟠 병목 2: Phase 2 - _find_nearest_equipment() 태그-설비 매핑 (MED)

위치: mcp-server/pipeline/topology.py:131-163

문제: TEXT/MTEXT(약 3,925개)와 설비(약 3,272개)를 전체 비교

# topology.py:143-148
for eq_id in equipment_ids:  # 3,272개
    eq_bbox = self.G.nodes[eq_id]['bbox']
    dist = tag_bbox.distance(eq_bbox)  # shapely 거리 계산
    if dist > self.config['tag_threshold']:
        continue

연산량: 3,925 × 3,272 = 약 1,280만 회의 거리 계산
실제 성능: 수초 ~ 수십초 (설비 수에 따라 변동)


🟡 병목 3: Phase 1 - DXF 엔티티 순회 추출 (LOW)

위치: mcp-server/pipeline/extractor.py:124-162

문제: 28,819개 엔티티를 하나씩 순회하며 BBox 계산

# extractor.py:124-162
for entity in self.msp:  # 28,819개
    bbox_obj = self.get_bbox(entity)  # 각 엔티티당 BBox 계산
    ...

실제 성능: ~1.4초 (허용 가능)


3. 근본 원인

공간 인덱스(R-tree, Quadtree) 미사용으로 모든 노드 쌍을 O(n²)으로 비교함.

shapely의 intersects(), distance()는 정확한 기하학 연산이지만 계산 비용이 큼.
불필요하게 먼 객체 쌍에도 이 연산을 수행하는 것이 핵심 문제.


4. 수정 계획

전략: 3단계 점진적 개선

단계 내용 예상 효과 작업량
Step 1 BBox 빠른 필터링 추가 90% 이상 연산 축소
Step 2 그리드 기반 공간 인덱스 O(n²) → O(n log n)
Step 3 pid_worker.py 통합 및 테스트 E2E 검증

5. 상세 TODO List

각 단계는 독립적으로 커밋 가능. 중간에 끊겨도 다음 작업자가 이 문서로 이어갈 수 있음.

Step 1: BBox 빠른 필터링 추가 (우선순위: HIGH)

  • 1-1. topology.py_bbox_quick_filter() 함수 추가

    • shapely 없이 min_x/max_x/min_y/max_y로 간단한 거리 계산
    • 임계값보다 먼 객체는 즉시 제외
    • 참고: mcp-server/pipeline/extractor.py:176-183is_near() 함수가 이미 shapely box 사용 중 → 이 함수도 함께 수정 필요
  • 1-2. build_graph() 내 배관-설비 연결 루프 수정 (topology.py:81-129)

    • 기존: for eq_id in equipments: → 전체 순회
    • 수정: _bbox_quick_filter()로 후보 집합 축소 후 순회
    • 예상: 7,110만 회 → 약 100만 회로 축소
  • 1-3. _find_nearest_equipment() 수정 (topology.py:131-163)

    • 동일하게 BBox 빠른 필터링 적용
    • 예상: 1,280만 회 → 약 50만 회로 축소
  • 1-4. 성능 테스트 실행

    • test_pid_bottleneck_analysis.py로 Phase 2 시간 측정
    • 목표: 10분 → 30초 이내
  • 1-5. 커밋: fix(#bottleneck): topology.py BBox 빠른 필터링 추가


Step 2: 그리드 기반 공간 인덱스 (우선순위: MED)

  • 2-1. topology.pySpatialGrid 클래스 추가

    • 그리드 셀 크기 = dist_threshold
    • 각 엔티티를 중심 좌표로 그리드 셀에 할당
    • 인접 셀(3×3)만 검색 대상
  • 2-2. build_graph()에서 SpatialGrid 사용

    • 배관-설비 연결 시 그리드 기반 후보 검색
    • 예상: 100만 회 → 약 10만 회로 추가 축소
  • 2-3. _find_nearest_equipment()에서 SpatialGrid 사용

    • 태그-설비 매핑 시 그리드 기반 후보 검색
  • 2-4. 성능 테스트

    • 목표: 30초 → 2초 이내
  • 2-5. 커밋: perf(#bottleneck): topology.py 그리드 기반 공간 인덱스 도입


Step 3: pid_worker.py 통합 및 E2E 테스트 (우선순위: LOW)

  • 3-1. pid_worker.pybuild_pid_graph_parallel 도구 확인

  • 3-2. MCP 서버 재시작 후 E2E 테스트

    • parse_pid_drawing 도구로 No-10_Plant_PID.dxf 파싱
    • 전체 파이프라인 완료 시간 측정
  • 3-3. 결과 검증

    • 생성된 그래프 JSON 확인
    • 노드/엣지 수 비교 (기존 결과와 일치하는지)
  • 3-4. 커밋: test(#bottleneck): E2E 테스트 및 성능 검증


6. 참고: 관련 파일 목록

파일 역할 수정 대상
mcp-server/pipeline/topology.py 위상 빌더 주요 수정 대상
mcp-server/pipeline/extractor.py 기하학적 추출 is_near() 함수 수정
mcp-server/pipeline/mapper.py 지능형 매핑 변경 없음
mcp-server/pipeline/analyzer.py 영향도 분석 변경 없음
mcp-server/worker/pid_worker.py P&ID 워커 Step 3 통합 테스트
test_pid_bottleneck_analysis.py 성능 테스트 Step 1-2 검증용

7. 진행 상태

단계 상태 비고
진단 완료 2026-05-04
Step 1: BBox 빠른 필터링 완료 SpatialGrid로 통합
Step 2: 그리드 기반 공간 인덱스 완료 SpatialGrid 클래스 추가
Step 3: E2E 테스트 완료 성능 검증 완료
추가: build_graph() 중복 제거 완료 pid_worker.py 수정

8. 복귀 가이드

작업을 끊었다가 다시 시작할 때:

  1. 이 문서의 "진행 상태" 테이블 확인
  2. 가장 최근 완료된 Step 다음 TODO부터 시작
  3. 각 Step의 마지막 항목이 "커밋"이므로, git log로 실제 진행 확인
  4. 성능 테스트는 test_pid_bottleneck_analysis.py 실행