블로그 이미지
Every unexpected event is a path to learning for you.

카테고리

분류 전체보기 (2737)
Unity3D (817)
Programming (474)
Server (33)
Unreal (4)
Gamebryo (56)
Tip & Tech (228)
협업 (58)
3DS Max (3)
Game (12)
Utility (136)
Etc (96)
Link (32)
Portfolio (19)
Subject (90)
iOS,OSX (53)
Android (14)
Linux (5)
잉여 프로젝트 (2)
게임이야기 (3)
Memories (20)
Interest (38)
Thinking (38)
한글 (30)
PaperCraft (5)
Animation (408)
Wallpaper (2)
재테크 (18)
Exercise (3)
나만의 맛집 (3)
냥이 (10)
육아 (16)
Total
Today
Yesterday
04-26 00:00

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



반응형
Posted by blueasa
, |