LOGIN • JOININ

extreme PERFORMANCE

Performance.png


1... 강력한 성능

CGCII는 Windows의 Overlapped I/O와 IOCP에 최적화되어 구현되었습니다.
Overlapped I/O의 비동기 전송 효율과 IOCP의 효율적 프로세스 사용 능력을 최대한 활용해 고효율을 내도록 각종 알고리즘과 처리 방법을 사용했습니다.

강력한 네트워크 I/O 처리 성능 
 서버의 네트워크 처리 능력을 나타내는 가장 중요한 지표 중에 하나가 송수신 성능일 것입니다.
즉 초당 얼마의 송신 요청(Send Request)를 소화해 낼수 있으며 혹은 얼마의 메시지를 수신할 수 있느냐를 의미하는 것입니다.
 동작방식이 달라 단순히 비교하기 힘들겠지만 가장 간단한 크기의 메시지 를 송수신한다했을 때.
일반적인 리눅스 기반 APACH류의 웹서버가 초당 1~2만 메시지 정도를 처리할 수 있는 하드웨라면
송수신 최적화 처리가 없는 C++로 제작된 엔진의 경우 30~50만 메시지의 처리는 가능하며 
CGCII엔진의 경우 최대 5,000만~8,000만 정도의 메시지의 성능을 발휘할 수 있습니다.

강력한 동시 접속 유지 능력 

일반적으로 리눅스 APACH 웹서버의 경우 서버당 256접속 수준입니다.
많은 접속 처리가 가능한 node.js나 Nginx 등의 경우 많은 접속을 받을 수 있지만 단일 쓰레드에서 동작하므로 성능의 한계가 있습니다. 
 CGCII서버는 다중쓰레드와 비동기식 접속처리로 버의 용량이 허용하는 한 소켓의 수의 제한없이 접속을 받아 들일 수 있습니다.
송수신버퍼의 크기를 최소로 설정하게 되면 600MByte정도의 용량으로 6만 접속 정도를 수용할 수 있습니다.

강력한 접속 처리 능력 
서버의 경우 최대 접속수뿐만 아니라 초당 처리할 수 있는 접속 처리 수 역시 중요합니다.
CGCII는 접속과 접속 종료 역시 비동기 I/O를 사용하며 다중  쓰레드로 접속 해제된 소켓의 재활용이나 객체 풀 등을 활용함으로써 고성능의 접속처리 능력을 발휘합니다.
초당 수천건 이상의 접속 시도와 종료처리도 원할히 수행할 정도로 우수한 성능을 제공합니다.

고성능 메시지 직렬화
서버의 역할 중 네트워크 I/O 처리와 더불어 수신된 메시지의 값을 읽어내고 전송할 메시지를 작성하는 성능 역시 매우 중요합니다.
CGCII에서는 CGD::buffer과 CGPool을  사용한  CCGBuffer를 통해 제공합니다.
CGD::buffer는 다른 어떠한 메시지 직렬화 방법보다 간단하고 성능이 우수하며 다른 직렬화 라이브러리와도 같이 사용될 수 있습니다.

고성능 DB 쿼리
서버의 처리 능력에 있어 가장 큰 병목이 DB에 대한 쿼리 처리입니다. CGCII에서는 고성능 DB쿼리 처리를 위해 DB 세션 풀을 구성하고 고성능의 동기식 혹은 비동기식의 쿼리를 수행해 줍니다.



2... 효율적인 객체 관리 시스템, 풀 시스템 그리고 가비지 콜렉션

다중쓰레드에 최적화된 고성능 메모리 풀 
네트워크 I/O는 그 처리 과정에서 많은 메모리 버퍼의 할당과 해제 수반하기 때문에 메모리의 동적 할당이 성능에 미치는 영향은 지대합니다.
단순히  Google의 'tcmalloc'나 facebook의 'jemalloc' 과 같은  메모리 풀로 바꾸었을 뿐인데 성능이 20~30%가 향상되었다는 예들은 소개되고 있을 정도로 서버에서 풀이 성능에 미치는 영향은 큽니다.
CGCII는 
메모리 블럭 단위로 할당과 해제를 해 효율을 높인 풀인 'CGPool'을 제공합니다.
다중쓰레드에 최적화되어 있으며 필요에 따라 다양하게 튜닝이 가능합니다.
또 내부적으로 다양한 통계를 바탕으로 효율적인 가비지처리와 풀 관리를 수행하도록 처리되어 있다.
(CGCII Performance 문서 ‘CGCII Pool System’참조)

PoolSystem.png



풀의 핵심 객체 풀
범용적인 힙 시스템은 단순한 메모리 풀일 뿐이지만 CGPool은 객체 풀도 제공해 준다는 것이 가장 강력한 점 중에 하나입니다. 
일반적으로 메모리 풀보다는 객체의 재사용을 하는 객체풀로 인한 성능향상이 더욱 극적입니다.
객체 풀은 메모리 할당뿐 아니라  객체의 초기화와 소멸 처리에 드는 비용까지 획기적으로 줄여 주기 때문입니다.
CGPool의 객체풀은 템플릿 메타 프로그래밍으로 구현해 사용 역시 매우 간단합니다.



3... 효율적인 쓰레드 관리

다중 코어에 최적화된 분산 처리 체계
요즈음 프로세스 들은 코어 수를 늘려 성능을 높이는 것이 일반화되었습니다. 
CGCII는 필요할 경우 다양한 형태의 쓰레드 구조를 손쉽게 구현할 수 있도록 해줍니다. 
특히 단일 로드 밸런서 구조가 다중 코어 환경에서 최적으로 동작할 수 있도록 해주며 
비동기 처리와 스케쥴드 실행도 함께 제공해줍니다.  (CGCII Executing System 문서 참조)

Executor3.png


락-프리(Lock Free)
 다중 쓰레드의 처리에서 동기화 처리를 위한 락(Lock)은 필수불가결하지만 데드락과 같은 문제를 발생시키기도 하고 성능에 있어서도 악영향을 미칩니다.   더군다나 코어수가 많아지면 그 영향은 더욱 커지게 됩니다.
CGCII는 락으로 인한 성능 저하를 최소화하기 위해 락-프리를 광범위하게 사용합니다.
락-프리 스택과 큐뿐만 아니라 각종 I/O처리 등  기존에 락을 써야만 했던 처리의 대부분을 원자적(Atomic)함수를 사용해 락-프리로 구현했습니다.



4... 로직 최적화
성능의 최적화에 있어 단편적인 함수를 특별한 함수로 대체하거나 풀의 사용과 같은 것들도 중요하지만 근본적으로는 부하를 많이 발생시킬 수 있는 알고리즘이나 로직을 최소화하는 것이 가장 중요할 것입니다.

반복문의 최소화 (구조적 최적화)
서버의 내부처리에 있어 for문 혹은 while문 등의 반복문은 많은 그 대상의 수에 반비례해 성능을 하락시킵니다. 즉 처리해야할 접속자수가 많아지거나 부하가 몰리게 되면 될수록 반복문은 성능을 극적으로 떨어뜨릴 수 있습니다. 더군다나 락처리를 동반하는 경우라면 더더욱 성능을 떨어뜨립니다. 그래서 최대한 접속자수 혹은 처리량 수 비례로 증가하는 곳의 반복문은 어떤 방법을 사용해서라도 삽입,삭제,검색을  O(1) 로 구현하도록 노력 했습니다.

배열형 데이터 처리 (하드웨어 최적화)
 일반적으로 연결 리스트(Linked list) , 트리(Tree), 해쉬(Hashing)와 같은 비선형 메모리 억세스를 해야만 하는 경우 하드웨어 캐쉬의 효율을 극도로 떨어뜨려 선형적 메모리 억세스를 수행하는 배열에 비해 수십배 많게는 수백배의 처리 시간이 걸리는 경우가 많습니다.
이러한 문제는 접속 수나 처리량이 많은 서버의 경우 상당히 많은 부하를 가중시킵니다.
따라서 빈번한 순회(Iteration)가 필요한 경우 최대한 배열형 구조를 채택함하고  다중 레벨  포인터와 같은 것은 최대한 배제하도록 설계해 대규모 데이터 처리의 효율성을 극대화 시켰습니다.

하드웨어 캐쉬 효율 극대화 (하드웨어 최적화)
최근 하드웨어에는 프로그래밍 로직만큼이나 하드웨어적인 캐쉬의 효율은 성능에 있어 매우 중요한 부분을 차지합니다.
따라서 CGCII는 캐쉬의 적중률을 높도록 메모리의 사용을 최적화했습니다.
예를 들어 배열 데이터를 임시로 처리하기 위해 vector<T>와 같은 객체를 만들 경우 vector<T>는 동적할당을 통해 배열을 할당받습니다. 이렇게 되면 이중 포인터를 억세스 하는 것이므로 캐쉬이 적중률이 떨어집니다. 따라서 vector<T>가 아닌 지역변수형 vector로 직접 제작한 CGD::array<T>를 사용함으로써 캐쉬의 적중률을 최적화하도록 하였습니다.

템플릿 메타 프로그래밍을 통한 최적화 (프로그래밍 언어적 최적화)
 템플릿 메타 프로그래밍의 대규모 사용으로 기존에는 실시간 처리되어야 했던 많은 것들이 컴파일 타임에 처리되거나 내부적으로 자동적으로 효율적인 알고리즘을 선택하도록 구현되어 있습니다.
예를 들어 상수 문자열을 처리할 경우 실시간으로 문자열 길이 확인을 자동적으로 컴파일 단계처리로 옮겨줍니다.
또 데이터를 복사할 때 trivial 데이터일 경우 컴파일러에서 판단해 자동적으로 memcpy()함수를 사용하도록 해줍니다.



5... 효율적인  네트워크 I/O

비동기식 소켓 I/O (Asynchronouse Socket I/O)
CGCII가 강력한 I/O 성능을 낼 수 있는 가장 핵심은 바로 윈도우즈의 중첩된 I/O (Overlapped I/O) 기능 때문입니다. 
또 CGCII는 중첩된 I/O에 최적화되어 있습니다.
비동기식 I/O의 경우 메모리 버퍼 중첩사용이나 복사의 최소화 등으로  대규모 송수신에는 뛰어난 효율을 나타내지만 작은 데이터를 빈번하게 전송할 경우 오히려 효율이 떨어질 수도 있습니다. 
하지만 중첩된 I/O에 최적화된 알고리즘과 처리를 통해 단점들은 최소화하고 장점을 극대화할 수 있도록 구현되어 있어 어떤 상황에서도 최적화된 송수신 처리를 수행하도록 해줍니다.

비복사 송수신 시스템 (Zero Copy Transfer)
서버의 경우 수신 받은 데이터를 여러 곳에 재전송하는 경우가 많습니다. 
채팅만 해도 한 피어에서 수신 받은 데이터를 다른 여러 피어로 재전송해야 합니다. 즉 1:N전송을 수행한다는 것입니다.
이런 1:N 전송은 채팅뿐만 아니라 서버의 특성상 매우 빈번하게 사용됩니다.
CGCII는 수신한 데이터를 여러 피어로의 전송할 때 모두 참조 계수로 동작해 내부적인 복사가 전혀 일어나지 않는 무복사 송수신이 가능하도록 구현되어 있습니다.

모음 송신 처리 (Gathering Send)
서버에 부하가 많이 걸리게 되면 데이터를 매번 전송하는 것이 아니라 큐잉처리를 했다 한꺼번에 전송하도록 해 서버의 부하가 몰렸을 때 유발되는 부하를 최소화하도록 해줍니다. 
이 역시 윈도우즈의 중첩된 I/O 기능을 활용함으로써 극대화된 성능의 구현이 가능했습니다.


효율적인 송수신 알고리즘과 버퍼 체제
CGCII에서는 다양한 상황에 최적화된 송수신 알고리즘과 버퍼체계를 제공합니다.

- 채팅서버의 경우 1:N 전송이 많고 소켓당 데이터의 송수신량은 많지 않습니다.
- 모바일 게임서버나 메신저의 경우 많은 접속자 수를 처리하지만 데이터의 송수신량은 매우 적습니다. 
- MMOG 서버의 경우 대규모 접속과  고성능 1:N 전송을 요구하며 높은 송수신 빈도를 가지며 렉에 민감합니다.
- 다운로드 서버의 경우 수신은 거의 없으며 대규모 데이터의 전송 능력이 필요합니다.
- 서버 간의 접속은 일반적으로 하나 혹은 적은 수의 접속으로 대규모 데이터를 송수신을 하게 됩니다.
- 로그 서버의 경우 대규모 데이터의 빠른 수신처리가 요구됩니다.

이런 다양한 상황에 대응하여 소켓 별로 적절한 소켓 I/O 알고리즘과 각종 튜닝을 할 수 있도록 구현되어 있습니다.
대규모 접속을 유지해야 하지만 송수신 량이 적을 경우 소켓당 사용 메모리를 최소화하도록 튜닝 할 수 있으며 
대규모 송수신이 필요한 경우 소켓당 메모리를 많이 사용하더라도 최고의 전송효율을 보이도록 할수도 있습니다.
또 단일 접속으로 대규모의 송수신이 필요할 경우 하나의 소켓 처리를 여러 쓰레드에 분산처리 해 효율을 높일 수도 있습니다.

최적화된 소켓 파라메터 튜닝
서버 네트워크 I/O의 경우 매우 다양한 형태 송수신 에 대응해 알고리즘 뿐만 아니라 각 상황에 맞는 각 소켓의 설정 파라메터 값 역시 튜닝할 수 있도록 해줍니다.
이를 통해 서버의 성능과 효율 그리고 궁극적으로는 안정성을 향상시킬수 있습니다.

부하 적응형 송수신
서버에 과부하가 몰리거나 순간적인 렉이 발생하면 그로 인해 처리되어야 할 내용이 제때 처리되지 못하고 누적되게 되면 또다른 처리나 더 많은 처리를 유발시켜 성능을 기하급수적으로 떨어뜨리는 구조를 가진 경우가 많습니다. 
CGCII에서는 네트워크 I/O의 처리가 누적될 경우 반응속도는 좀 희생하더라도 더 적은 부하로 처리할 수 있도록 고려되어 설계되어 서버에 찾아 올수 있는 순간적 과부하나 순간적 지체로 서버에 문제가 생길 수 있는 상황을 최소화할 수 있도록 되어 있습니다. 

비동기식 소켓 접속/종료 처리
 TCP 소켓의 경우 송수신의 알고리즘이나 구조 뿐만 아니라 접속 형태 역시 매우 다양하며 중요합니다.
 예를 들어 한번 접속을 하면 서버가 종료할 때까지 접속을 유지하는 서버간의 접속형태도 있으며 초당 수천번의 대규모 접속과 접속해제를 처리해야하는 접속 혹은 인증 처리와 같은 서버도 존재합니다.
CGCII는 이런 소켓의 접속과 접속해제에 있어서도 최적의 효율을 제공하기 위해 클라이언트/서버 소켓 모두 비동기식 접속을 지원합니다.
서버의 경우 비동기식 접속처리를 통해 엄청난 접속처리 능력을 제공받습니다.
그리고 클라이언트의 경우 효율적인 프로세스의 활용뿐만 아니라 자동 재접속 기능과 같은 기능도 제공해줍니다.

소켓 자원의 재사용 (Socket Resource Reuse)
빈번하게 TCP소켓이 접속되고 종료되는 서버의 경우 매번 TCP 소켓 자원을 생성하고 할당해제하는 것은 비효율적일 수 있습니다.
CGCII에서는 소켓 자원까지도 재활용을 제공해주어 빈번한 소켓의 접속과 해제를 해야하는 곳에서는 매우 높은 효율과 성능을 제공합니다.


6... 효율적인 DB세션 풀과 다중 쿼리 시스템

효율적인 쿼리 체계
MS-SQL, MySQL, Redis, HTTP 등과 같은 DB 혹은 서버에 질의(Query)를 효율적으로 처리해주기 위한 시스템을 제공해줍니다.
CGCII의 Querier는 세선 풀을 구성해 다중 쓰레드로 효율적인 질의 처리를 수행할 수 있도록 해준다. 
또 최대한 효율적인 질의처리를 위해 세션의 재활용이나 재접속의 최소화 같은 처리가 되도록 구현되어 있다.

다양한 체제에 최적화된 쿼리 체계
SQL을 사용하는 RDB와 Key-Value형 NoSQL 혹은 웹서버를 통한 Query등 모두 각각의 특성에 맞춰 최적화되어 있습니다.
또 이런 질의처리기 조차도 모두 구조와 재정의에 개방되어 있어 필요한 경우 자신이 직접 제작하거나 튜닝할 수도 있습니다.

효율적인 세션 Fail-Over
쿼리 수행중 세션에 문제가 생겼을 경우  문제가 발생한 세션만 제거후 해당 부분만 복구하는 최적화된 구조를 가지고 있습니다.