실패 한 protobuf 기준 테스트
이전에 pemelo 자 료 를 보 았 을 때 작 가 는 pemolo 에 대한 최적화, json 의 완전 직렬 화 는 서버 메시지 전달 의 병목 이 되 었 다 고 언급 한 적 이 있다. 현재 제 게임 서버 에서 protocbuf 를 프로 토 콜 로 사용 하고 있 습 니 다. 그 표현 은 매우 안정 적 입 니 다. 클 라 이언 트 와 저 는 프로 토 콜 에 대한 교류 가 원활 하고 양쪽 의 개발 효율 을 크게 향상 시 켰 습 니 다. 완벽 해 보이 지만 저 는 항상 은근히 불안 합 니 다. 저 는 가끔 의심 합 니 다.
현재 protobuf 의 방식 에 문제 가 있 지 않 습 니까? 서버 가 프로 토 콜 대상 에 대한 직렬 화 와 반 직렬 화 를 서버 의 성능 병목 으로 만 들 지 않 습 니까?
우리 게임 의 메시지 유형 이 비교적 많 기 때문에 약 100 가지 요청 이 있 습 니 다. 메시지 의 시퀀스 / 반 직렬 화 작업 을 편리 하 게 하기 위해 서 보통 큰 메 시 지 를 사용 합 니 다. 소포 하위 메시지 방식 으로 구성:
protobuf 의 공식 문서 에 따 르 면 유 니 온 type 의 조직 형식 을 묘사 하여 이 루어 집 니 다 (https://developers.google.com/protocol-buffers/docs/techniques):
message OneMessage {
enum Type { FOO = 1; BAR = 2; BAZ = 3; }
required Type type = 1;
optional Foo foo = 2;
optional Bar bar = 3;
optional Baz baz = 4;
}
구 글 그룹 이 필요 로 하 는 토론 에서 메시지 바이트 흐름 을 내장 하 는 방식 을 제시 했다.
message OneMessage {
enum Type { FOO = 1; BAR = 2; BAZ = 3; }
required Type type = 1;
required bytes innerMessage = 2;
}
나 는 결국 다음 방법 을 채택 했다. 왜냐하면 전 자 는 세 가지 단점 이 있 을 것 이 라 고 생각 하기 때문이다.
1. 큰 메시지 체 가 너무 지루 해서 하나의 키 메시지 유형 에 수백 가지 항목 이 있 을 수 있 으 므 로 유지 하기 어렵다.
2. 메시지 에 선택 할 수 있 는 메시지 필드 가 너무 많 습 니 다. 그러나 모두 null 입 니 다. 직렬 화 된 모든 메 시 지 는 쓸모없는 인용 메모 리 를 많이 차지 합 니 다. 메시지 대상 의 수량 은 바로 수량 이 가장 많 습 니 다. 위험 이 있 을 수 있 습 니 다.
3. 내장 대상 은 매번 직렬 화 되 어야 하 는 것 이 아 닙 니 다. 서버 는 대화 상 태 를 저장 하고 모든 상 태 는 유형의 메시지 만 보 낼 수 있 습 니 다. 클 라 이언 트 가 개선 한 메시지 유형 과 서버 상태 가 대응 하지 않 으 면 메 시 지 를 직접 버 릴 수 있 습 니 다. 내부 메 시 지 를 직렬 화 할 필요 가 없습니다.
이렇게 해서 프로젝트 는 한동안 안정 적 으로 실행 되 었 으 나 우연히 debug 를 통 해 protbuff 의 내부 코드 가 내부 메시지 의 시퀀스 에 성능 위험 이 존재 하 는 것 을 발견 했다.
protobuf 에서 바이트 에 대한 정의: required bytes innerMessage = 2;
Probobuf 는 직렬 화 할 때 변 하지 않 는 ByteString 대상 으로 바 뀌 지만 ByteString 대상 을 생 성 할 때 원본 메시지 바이트 배열 을 복사 하여 직렬 화 된 대상 에 게 전달 합 니 다 (CodedInputStream. readBytes () 참조).
protbuff 가 바이트 배열 의 복사 에 사용 하 는 것 은 System. array copy (native memcopy) 이지 만 기능 적 으로 이런 복사 가 저 에 게 는 전혀 필요 하지 않 습 니 다. (google groups 역시 이에 대해 의심 을 가지 고 있 습 니 다. https://groups.google.com/forum/?fromgroups#!topic/protobuf/ZaDigptdcHM).
일회 성 직렬 화 된 유 니 온 type 방식 에 비해 메시지 바이트 흐름 을 내장 하 는 방식 으로 바이트 배열 의 복사 본 을 한 번 더 할 수 있 습 니 다. 성능 에 문제 가 생 길 까 봐 걱정 입 니 다.
그래서 이 두 가지 방식 을 비교 하기 위해 서 나 는 간단 한 기본 테스트 를 했다.
message PBTestNestPacket {
required PBClientRequestType clientRequestType = 1; //
optional bytes requestData = 2; //
}
message PBTestUnionPacket {
required PBClientRequestType clientRequestType = 1; //
optional PBDummyRequest dummyRequest = 2;
.........
optional PBAutoBattleRequest autoBattleRequest = 100;
}
두 가지 내용 이 같은 메 시 지 를 만 들 고 메시지 의 직렬 화 된 바이트 배열 을 각각 생 성 한 다음 에 서로 다른 바이트 배열 의 깊이 를 직렬 화 합 니 다.
각각 다른 몇 개의 테스트 를 실시 한 결과 두 가지 방식 의 응답 시간 은 큰 차이 가 없 는 것 으로 나 타 났 다. 대부분 바이트 배열 을 포함 하 는 방식 으로 응답 시간 이 빠르다.
union .
report: size:20, testTurn:5000 : nest: 167 union: 216
report: size:100, testTurn:5000 nest 246 union 256
report: size:100, testTurn:50000 nest 1163 union 1236
report: size:500, testTurn:5000 nest 750 union 789
report: size:500, testTurn:50000 nest 10122 union 10129
report: size:1000, testTurn:5000 nest 1407 union 1421
report: size:5000, testTurn:5000 nest 9471 union 9690
비록 비 과학적 인 결과 가 나 왔 지만, 이번 테스트 는 적어도 나 자신 을 안심 시 켰 다. 현재 의 사용 협의 방식 은 다른 방식 에 비해 성능 에 있어 서 열세 가 없고, 유지 보수 성 이 많이 향상 되 었 다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Laravel Forge를 사용하여 GRPC 및 Protobuf 설치Laravel Forge로 GPRC와 Protobuf를 설치하는 것은 쉽습니다. 다음 단계를 따르십시오. 레시피로 이동 임의의 이름을 입력하십시오 사용자를 루트로 유지 스크립트 입력에 다음 스크립트를 추가하고 만들기...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.