대용량 메시지 (Image, PointCloud2, LaserScan 등 - 수 MB 단위)
필수적 적용 대상: 2.76MB 이미지나 수십만 개 포인트의 라이다 데이터는 Deep Copy 발생 시 CPU 점유율이 급증하고, IPC 통신 버퍼 오버플로우로 프레임 드랍(4Hz 고꾸라짐 현상)이 발생합니다. UniquePtr + ConstSharedPtr 조합이 필수입니다.
소용량 메시지 (PoseStamped, Twist, Imu, Int32 등 - 수 B ~ 수 KB 단위)
기술적 적용 가능: geometry_msgs::msg::Twist 같은 제어 명령 데이터도 std::unique_ptr로 퍼블리시할 수 있습니다.
실질적 이점 미미: 몇 바이트 남짓한 데이터는 memcpy 복사 시간이 나노초(ns) 단위에 불과합니다. 따라서 굳이 포인터를 관리하는 오버헤드를 들이지 않고 기존 방
이미지를 발행할 때 (Publish)
// CvImage가 OpenCV Mat 데이터(`rect_img`)를 // ROS2 sensor_msgs::msg::Image 포맷으로 변환한 뒤 // 힙 메모리에 할당한 Raw 픽셀 데이터의 메모리 시작 주소.auto shared_msg = cv_bridge::CvImage(header, "bgr8", rect_img_).toImageMsg();// *shared_msg 역참조를 통해 기존 이미지 데이터를// 새로운 힙 메모리 공간에 100% 그대로 복사(Deep Copy)한 뒤,// 새롭게 생성된 메모리의 단독 시작 주소.auto unique_msg = std::make_unique<sensor_msgs::msg::Image>(*shared_msg);// unique_msg가 가진 메모리 주소의 독점 소유권을// ROS2 RMW(미들웨어) 통신 파이프라인으로 완전히 이전(Move).pub_rect_image_->publish(std::move(unique_msg));
실제 담기는 내용: 픽셀 데이터가 저장된 힙(Heap) 메모리의 시작 주소값(Pointer)과 데이터 길이, 해상도 등의 메타데이터 정보.
std::move()의 역할: 2.76MB 픽셀 데이터를 새로 복사하는 것이 아니라, “내가 가지고 있던 힙 메모리 주소의 독점 소유권을 ROS2 RMW(미들웨어)로 넘겨주겠다”는 소유권 이동 명령입니다.
이미지를 구독할 때 (Subscribe)
ConstSharedPtr / SharedPtr
1. ConstSharedPtr 동작 방식 (True Zero-Copy)
[퍼블리셔 (camera_driver)]
│ 1. std::make_unique<Image>() 생성 후 std::move()로 publish()
▼
[ROS2 IPC (통신 레이어)]
│ 2. "수신자가 ConstSharedPtr(읽기 전용)이네? 메모리 수정 안 하겠군!"
│ 3. 메모리 복사 없이 힙(Heap) 주소 그대로 전달
▼
[서브스크라이버 (FpsChecker)]
│ 4. 퍼블리셔가 만든 원본 메모리 주소(Pointer)를 그대로 수신
결과: 메모리 복사 횟수 0회.
2. SharedPtr 동작 방식 (Deep Copy 발생)
[퍼블리셔 (camera_driver)]
│ 1. std::make_unique<Image>() 생성 후 std::move()로 publish()
▼
[ROS2 IPC (통신 레이어)]
│ 2. "수신자가 SharedPtr(가변)을 요구하네? 원본 데이터를 수정할 수도 있겠어!"
│ 3. 2.76MB 메모리를 새롭게 할당(malloc)받아 원본 데이터를 100% 그대로 복사(memcpy)
▼
[서브스크라이버 (FpsChecker)]
│ 4. 새로 복사된 별도의 2.76MB 메모리 주소를 수신
결과: ROS2 통신 레이어 내부에서 1회 메모리 복사(Deep Copy) 발생.
std::move(unique_msg)와 ConstSharedPtr를 통한 Zero-Copy는 한 프로세스(Component Container) 내부의 메모리 주소를 공유할 때만 성립하는 C++ 소프트웨어적 최적화.