[펌] 직렬화 방법, Facebook의 Thrift와 Protocol Buffers의 비교.
Thrift는 Facebook의 직렬화 방법이다. 2010년 3월 현재 apache의 인큐베이팅 프로젝트로 등록되어 있다. 전 구굴의 개발자가 만들었다고 하고 Protocol Buffers와 무척 유사하다. 하며, 다음과 같은 차이점이 있다.
- java API가 좀더 깔끔하다.
- 별도의 setter, getter없이 필드에 직접 접근
- 별도의 read only의 Message와 read & write의 Builder의 구분이 없다.
- c++의 경우 생성된 코드는 정의한 필드의 소대문자가 전부 소문자로 변하는데 반해 Thrift는 소대문자가 보존된다.
- Protocol Buffers : message->set_myname(2);
- Thrift : message->myName = 2;
- Protocol Buffers는 필드의 List만 지원하는데 반해 Thrift는 Set, Map, List를 지원한다.
- RPC 인터페이스 정의에 의한 구현코드가 자동생성된다. 서버, 클라이언트 코드의 작성이 쉽다.
이외의 것은 Protocol Buffers와 거의 똑같다.
장단점을 비교하면 다음과 같다.
Protocol Buffers
- 장점
- Thrfit에 비해 빠르다.(3배정도)
- 단점
- java의 경우 Message, Builder로 분리되어 있고, Builder를 사용한 코드가 다소 지저분하다.
- List만 처리 가능(과연 단점일까?)
Thrift
- 장점
- List, Set, Map 지원
- 단점
- c++의 경우 메시지가 다른 메시지 필드의 타입일 경우 손수 생성, 파괴하여야 한다.
- 문서가 거의 없다. 샘플도 거의 없다.
- 윈도우에서는 컴파일러를 컴파일하기 까다롭다.
- 자동 생성된 c++코드는 windows에서는 사용하지 못한다.
기타 특징은 다음과 같다.
- c++, c#, cocoa, java, perl, php, python, ruby를 지원한다.
- Apache License 2.0
- 상수와 enum을 지원
- 하위 호환
- 서비스의 상속 가능
- 비동기시 서비스 지원
- 예외 지원
성능 테스트
두가지 사이즈의 데이타에 대하여 테스트 하였다.
인코딩된 사이즈의 크기는 Protocol Buffers가 34, 1234 byte였으며 Thrift는 174, 1504 byte 였다.
c++의 경우 처리 건수는 Protocol Buffers가 초당 130만회, 11만회였으며, Thrift는 초당 36만회, 8만회였다.
java의 경우 처리 건수는 Protocol Buffers가 초당 87만회, 6만회 였으며, Thrift는 초당 14만회, 4만회였다.
코드 샘플
- c structure
typedef struct Css {
int srcCSID;
int newCSID;
} Css;
typedef struct Leg{
int srcCSID;
int newCSID;
int srcLegID;
int newLegID;
} Leg;
typedef struct StringValue {
int length;
char* str;
} StringValue;typedef struct Messsage {
int result;
int vcID;
int srcCSAID;
int targetCSAID;
Css[] csses;
Leg[] legs;
StringValue serviceID;
} Message;
- Protocol Buffers definition
message Css {
optional uint32 srcCSID = 1;
optional uint32 newCSID = 2;
}message Leg {
optional uint32 srcCSID = 1;
optional uint32 newCSID = 2;
optional uint32 srcLegID = 3;
optional uint32 newLegID = 4;
}
message StringValue {
optional uint32 length = 1;
optional string str = 2;
}message Message {
optional uint32 result = 1;
optional uint32 vcID = 2;
optional uint32 srcCSAID = 3;
optional uint32 targetCSAID = 4;
repeated Css css = 5;
repeated Leg leg = 6;
optional StringValue serviceID = 7;
}
- Thrift definition
struct Css {
1: i64 srcCSID,
2: i64 newCSID
}struct Leg {
1: i64 srcCSID,
2: i64 newCSID
3: i64 srcLegID,
4: i64 newLegID
}struct StringValue {
1: i64 length,
2: string str
}
struct Message {
1: i64 result,
2: i64 vcID,
3: i64 srcCSAID,
4: i64 targetCSAID,
5: list<Css> csses,
6: list<Leg> legs
7: StringValue serviceID
}
- c++ - Protocol Buffers
ShortTasMessage::Message* message = new ShortTasMessage::Message();
message->set_result(100);
message->set_vcid(9);
message->set_srccsaid(1);
message->set_targetcsaid(2);ShortTasMessage::Css* css = message->add_css();
css->set_srccsid(1);
css->set_newcsid(2);ShortTasMessage::Leg* leg0 = message->add_leg();
leg0->set_srccsid(1);
leg0->set_newcsid(2);
leg0->set_srclegid(1);
leg0->set_newlegid(3);ShortTasMessage::Leg* leg1 = message->add_leg();
leg1->set_srccsid(1);
leg1->set_newcsid(2);
leg1->set_srclegid(2);
leg1->set_newlegid(4);
LongTasMessage::StringValue* serviceID = message->mutable_serviceid();
serviceID->set_length(3);
serviceID->set_str("CHD");
c++ - Thrift
ShortTasMessage::Message* message = new ShortTasMessage::Message();
message->result = 100;
message->vcID = 9;
message->srcCSAID = 1;
message->targetCSAID = 2;ShortTasMessage::Css* css = new ShortTasMessage::Css();
css->srcCSID = 1;
css->newCSID = 2;
message->csses.push_back(*css); // csses is List
delete css; css = NULL;ShortTasMessage::Leg* leg0 = new ShortTasMessage::Leg();
leg0->srcCSID = 1;
leg0->newCSID = 2;
leg0->srcLegID = 1;
leg0->newLegID = 3;
message->legs.push_back(*leg0);
delete leg0; leg0 = NULL;ShortTasMessage::Leg* leg1 = new ShortTasMessage::Leg();
leg1->srcCSID = 1;
leg1->newCSID = 2;
leg1->srcLegID = 2;
leg1->newLegID = 4;
message->legs.push_back(*leg1);
delete leg1; leg1 = NULL;
message->serviceID.length = 3;
message->serviceID.str = "CHD";
java - protocol buffers
ShortTasMessage.Message.Builder message = ShortTasMessage.Message.newBuilder();
message.setResult(100);
message.setVcID(9);
message.setSrcCSAID(1);
message.setTargetCSAID(2);
ShortTasMessage.Css.Builder css = ShortTasMessage.Css.newBuilder();
css.setSrcCSID(1);
css.setNewCSID(2);
message.addCss(css);ShortTasMessage.Leg.Builder leg0 = ShortTasMessage.Leg.newBuilder();
leg0.setSrcCSID(1);
leg0.setNewCSID(2);
leg0.setSrcLegID(1);
leg0.setNewLegID(3);
message.addLeg(leg0);ShortTasMessage.Leg.Builder leg1 = ShortTasMessage.Leg.newBuilder();
leg1.setSrcCSID(1);
leg1.setNewCSID(2);
leg1.setSrcLegID(2);
leg1.setNewLegID(4);
message.addLeg(leg1);
LongTasMessage.StringValue.Builder serviceID = LongTasMessage.StringValue.newBuilder();
serviceID.setLength(3);
serviceID.setStr("CHD");
message.setServiceID(serviceID);
java - Thrift
ShortTasMessage.Message message = new ShortTasMessage.Message();
message.setResult(100);
message.setVcID(9);
message.setSrcCSAID(1);
message.setTargetCSAID(2);ShortTasMessage.Css css = new ShortTasMessage.Css();
css.setSrcCSID(1);
css.setNewCSID(2);
message.addToCsses(css);ShortTasMessage.Leg leg0 = new ShortTasMessage.Leg();
leg0.setSrcCSID(1);
leg0.setNewCSID(2);
leg0.setSrcLegID(1);
leg0.setNewLegID(3);
message.addToLegs(leg0);ShortTasMessage.Leg leg1 = new ShortTasMessage.Leg();
leg1.setSrcCSID(1);
leg1.setNewCSID(2);
leg1.setSrcLegID(2);
leg1.setNewLegID(4);
message.addToLegs(leg1);
LongTasMessage.StringValue serviceID = new LongTasMessage.StringValue();
serviceID.setLength(3);
serviceID.setStr("CHD");
message.setServiceID(serviceID);
Reference
demo client code
http://www.google.co.kr/codesearch/p?hl=ko#W9kbJs3X16M/trunk/src/examples/thrift/DemoClient.cpp&q=TBinaryProtocol&d=4
benchmark of thrift
http://www.google.co.kr/codesearch/p?hl=ko#NPWGicy0Ryg/trunk/test/Benchmark.cpp&q=TBinaryProtocol%20lang:c%2B%2B&sa=N&cd=9&ct=rc
Simple tutorial
http://skorage.org/2009/03/08/simple-thrift-tutorial/
Link : http://egloos.zum.com/aploit/v/5233573
'Server > Thrift' 카테고리의 다른 글
[번역] 에이브로(Avro), 프로토콜 버퍼(Protocol Buffers) 그리고 스리프트(Thrift)의 스키마 변경(evolution) (0) | 2016.05.17 |
---|---|
Thrift vs Protocol Buffers 비교문 요점 정리 (0) | 2014.12.26 |