연구한 이야기

    CMake 와 static library에서의 종속성 관리

    target이 static library인 CMake를 서브프로젝트로 포함시키는 구성에서의 종속성 관리. 회사에서 개발하는 게임은, 엔진을 자체 수정하며 작업하기에, 다양한 내부 라이브러리를 링크해서 사용한다. 지금껏 iOS 환경에서는 XCode를 직접 수정해가며 종속성을 관리하고 프로젝트들을 링킹했는데, 이번에 서브 프로젝트들을 CMake로 관리하려고 했다. 각 서브프로젝트의 CMakeLists.txt별로 존재하는 다양한 라이브러리 파일들..(ffmpeg라던지 zlib라던지 ssl이라던지..) 이들을 메인 프로젝트가 알 수 있게 해야 했다. 하지만, static library가 target 인 CMake를 XCodeProj로 만들 때, 종속성 정보를 메인 프로젝트로 전달해 줄 방법이 없었다. 그래서 방..

    서버 스트레스테스트 시 일정 주기로 멈춰요!

    RUST만든 웹서버를, jmeter를 통해 stress test를 진행하였다. 만든 서버는 config 파일을 watch 하고 읽어서, 웹으로 들어온 요청에 json으로 적절히 응답해주는 간단한 서버이다. 그런데..! 스트레스 테스트 시 몇십 초 이후, (약 7000+개의 connection이 이뤄진 다음), connection 이 아무리 시간이 지나도 이루어지지 않는다. 그런데, 또 몇십 초 지나면, 일부 connection은 수립되기는 한다. 이 현상이 반복되고 있었다... 여러 문제를 체크해 보았다. 로컬에서 테스트도 해보고, cpu부하나 대역폭도 체크해 보았다. 처음에는 무지하게도 `TIME_WAIT` 을 의심했는데, TIME_WAIT을 없애기 위해 연결 종료시에 linger를 이용해 RST를 보..

    docker exec format error

    RUST로 (잘 만든) 서버를 도커로 패키징하여 aws ec2 t4g nano 인스턴스에 올렸다! exec format error exec failed, exec format error 라는 명령어와 함께 실행이 안된다. 해결 X86_64 환경에서 개발한 이미지는, 기본적으로 AMD 아키텍처에서 동작한다. ARM CPU 환경을 지원하기 위해서는 해당 아키텍처에서 개발해야 한다. 혹은, docker buildx 등을 사용해서 멀티아키텍처 개발을 한다. 클라우드 빌드를 통해 각 아키텍처마다 build를 할 수도 있겠다.

    동기화객체 성능테스트

    동기화객체 성능테스트

    동기화객체 성능테스트 멀티스레드와 동기화 객체 멀티스레드 프로그래밍은 하나의 기능을 여러 스레드가 동일하게 실행하는 호모지니어스 방식과, 업무를 다르게 각자의 스레드로 분배하는 헤테로지니어스 방식으로 구분됩니다. 예를 들어, 게임 서버에서 길찾기 기능을 하나의 스레드로 분리하고, 네트워크 IO를 하나의 스레드로 분리한다면, 이는 헤테로지니어스 방식의 멀티스레드 설계입니다. 하지만, IOCP의 워커 스레드와 마찬가지로 하나의 동일한 로직을 수행하는 스레드가 여럿 있다면, 이는 호모지니어스 방식의 멀티스레드입니다. 이러한 멀티스레드 프로그래밍에서는 주의해야 할 점들이 생깁니다. 동기화 문제입니다. 가장 단순한 연산인 증감 연산마저도 CPU atomic하지 않기에, 수행 도중 context switching이..

    IOCP 서버 코어 개발하기

    IOCP 서버 코어 개발하기

    IOCP 서버 코어 개발 IOCP 기반 서버 코어 개발하기 이 문서는 IOCP를 기반으로 한 서버 라이브러리 개발 과정을 담았습니다. IO Completion Port IO Completion Port란, Windows OS에서 입출력 완료 통지를 알려주는 방식을 의미합니다. 흔히 소켓 모델의 하나로서 이야기되고는 하지만, 엄밀히 말하면 이는 그저 Overlapped IO에서 입출력 결과를 통지하는 하나의 방법론일 뿐입니다. 소켓 통신 또한 네트워크를 통한 IO이기에, 이에 대한 입출력 완료 통지를 IOCP를 통해 받도록 할 수 있습니다. Overlapped IO와 비동기 Overlapped IO란, IO가 Overlapped (중첩) 된다는 뜻으로서, 하나의 스레드가 한번에 하나의 IO만을 처리하는 것..

    패킷 직렬화버퍼

    패킷 직렬화버퍼

    패킷 직렬화와 마샬링 네트워크간 통신이 이루어지기 위해서는, 레이어 7계층에서부터 보낼 데이터를 아래 층으로 요청하여 결국 1계층의 비트 스트림으로 변환되고, 이후 수신 때에도 비트 스트림으로부터 레이어 7계층의 의미있는 데이터로 해석해내는 과정이 필요합니다. 이러한 일련의 과정에서 ‘데이터를 바이트 스트림으로 변환하는 과정’을 ‘직렬화’라고 하며, 이를 포함하여 데이터의 메모리 구조를 저장이나 전송을 위해 적당한 자료형태로 변형하는 과정을 ‘마샬링’이라고 부르고 있습니다. 바이트 오더 바이트 오더, 바이트 순서는 OS가 내부적으로 데이터를 표현하는 방식을 의미하기에, 현재는 CPU 아키텍처에 따라 두 종류의 바이트 오더가 존재합니다. Little Endian이라고 불리는 방식은 데이터가 바이트 단위로 ..

    메모리풀과 프리리스트

    메모리풀과 프리리스트

    개요 메모리풀은 미리 메모리를 준비시키고 이를 재사용하게 함으로서 생성과 반환에 소모되는 시간을 없애는 기술입니다. 가상메모리 시스템에서도 4KB단위로 페이징하는 것이 메모리풀의 성격을 가지고 있다고 볼 수도 있겠습니다. 다양한 버킷 크기를 지원하는 메모리풀의 구현은 안전 장치가 더해질수록 기본 힙 관리자와 성능차이가 줄어들 것이므로, 이 프로젝트에서는 고정 크기의 객체 (오브젝트)에 대한 메모리풀을 도입하는 것으로 하겠습니다. 메모리풀과 프리리스트 메모리풀 메모리풀은 처음 초기화 시 지정된만큼 충분한 메모리 공간을 할당받아 관리를 시작합니다. 이 경우, 준비된 메모리를 할당받아 사용하고 반환하는 것은 성능 향상이 되지만, 만일 메모리풀이 부족할 경우 resize를 할 지, 이 오버헤드가 감당 가능한지 ..

    TCP와 링버퍼

    TCP와 링버퍼

    TCP와 L7 버퍼링 TCP와 UDP를 비교하였을 때, 개발 측면에서의 가장 큰 차이점은 UDP는 데이터그램 방식으로서 송신한 메시지가 정확한 크기로 상대방에게 전달되지만, TCP는 데이터 간 경계가 없이 스트림 방식으로 송수신된다는 점입니다. 이러한 특징으로 인하여 7계층에서 4계층 TCP 버퍼로부터 데이터를 읽어올 때, 메시지의 완전한 형태의 패킷으로 받아지지 않는 경우를 대비하기 위해 7계층에도 수신 버퍼가 필요합니다. 7계층에서 수신된 모든 네트워크 데이터를 버퍼링하고, 해당 데이터가 충분히 쌓이게 되어 읽을 수 있는 상태가 된다면 그 때 메시지를 읽어내어 버퍼에서 빼내는 방식을 사용해야 합니다. L7 버퍼의 필요성 수신 링버퍼는 TCP의 특성상 데이터의 경계가 없이 스트림으로 오는 수신 데이터를..