C++의 직렬화 라이브러리
이 자습서에서는 다양한 C++ 직렬화 라이브러리에 대해 알아봅니다.
먼저 C++에서 직렬화와 직렬화의 목적에 대해 알아봅니다. 다음으로 C++의 직렬화 라이브러리와 이를 프로그램에서 사용하는 방법에 대해 설명합니다.
직렬화 개요
프로그래머는 일상적으로 메모리의 데이터 객체로 작업합니다. 그리고 때로는 프로그램 상태의 일부를 저장하기 위해 개체를 네트워크를 통해 보내거나 영구 저장소(일반적으로 파일)에 기록해야 합니다.
직렬화는 데이터 또는 개체 상태를 이진 형식으로 변환하는 프로세스/기술입니다. 이진 형식은 개체 상태를 저장/보존하거나 컴퓨터 네트워크를 통해 메모리, 데이터베이스, 파일 또는 디스크로 전송하기 위한 바이트 스트림입니다.
직렬화 프로세스의 역순을 역직렬화라고 합니다. 직렬화는 프로그램 실행 중 또는 실행 후에 구조화된 데이터(예: C++ 클래스 또는 구조체)의 상태를 유지하려는 경우에 이상적으로 적합합니다.
이 website에서 예제와 함께 serialize()
및 deserialize()
에 대해 읽을 수 있습니다.
직렬화는 소프트웨어 개체 값의 안정적인 바이트 표현을 제공합니다. 그런 다음 이러한 바이트는 다른 하드웨어 및 소프트웨어를 사용하는 향후 구현에서도 계속 올바르게 작동하는 네트워크를 통해 전송될 수 있습니다.
다양한 언어로 직렬화
계속 진행하기 전에 직렬화 프로세스는 언어마다 다르게 구현됩니다. 아래에서 살펴보겠습니다.
- Java에서 직렬화 방법은
writeObject
이며ObjectOutputStream
에서 구현됩니다. - Python에서 직렬화 방법은
pickle.dumps()
입니다. - Ruby에서 직렬화 방법은
marshal.dump()
입니다. - C++에서 메서드는
boost::archive::text_oarchive
a (파일 이름)입니다.<< 데이터;
직렬화 메서드 호출 - MFC(Microsoft Foundation Class Library)에서 직렬화 방법은
CObject
에서 클래스를 구동하는 것입니다.
우리의 주요 초점은 C++ 직렬화이므로 작동 방식을 살펴보겠습니다.
C++ Boost.Serialization은 텍스트 아카이브 개체를 사용합니다. 직렬화는 출력 데이터 스트림으로 작동하는 출력 아카이브 개체에 씁니다.
클래스 데이터 유형에 대해 호출될 때 >>
출력 연산자는 클래스를 호출하여 함수를 직렬화합니다. 각 직렬화 기능은 &
연산자를 사용하거나 >>
를 통해 중첩된 객체를 재귀적으로 직렬화하여 데이터 멤버를 저장하거나 로드합니다.
C++의 직렬화를 더 잘 이해하려면 이 website를 참조하십시오.
C++의 직렬화 라이브러리
C++는 Boost 직렬화를 제외하고 직렬화를 위한 많은 라이브러리를 제공합니다. 모든 라이브러리는 높은 직렬화 성능을 달성하는 데 도움이 되므로 몇 가지를 살펴보겠습니다.
프로토버프
프로토콜 버퍼(Protobufs), 데이터를 직렬화하는 데 사용되는 교차 플랫폼. 네트워크를 통한 프로그램 간의 통신에 유용합니다.
Protobuf 직렬화 메커니즘은 프로토콜 애플리케이션을 통해 제공됩니다. 이 컴파일러는 .proto
파일을 구문 분석하고 인수로 구성된 언어(이 경우 C++)에 따라 소스 파일을 출력으로 생성합니다.
Protobufs를 더 잘 이해하려면 이 링크에서 자습서를 읽을 수 있습니다.
플랫버퍼
FlatBuffers는 최대 메모리 효율성을 달성하는 데 사용되는 오픈 소스 크로스 플랫폼입니다. 순방향/역방향 호환성으로 구문 분석하지 않고 직렬화된 데이터에 직접 액세스할 수 있습니다.
FlatBuffers를 사용하면 먼저 --CPP
옵션으로 C++ 스키마를 생성합니다. 그런 다음 파일에 Flatbuffer를 포함하여 이 생성된 코드를 읽거나 쓸 수 있습니다.
이 링크에서 FlatBuffers를 사용한 직렬화 구현을 찾을 수 있습니다.
시리얼
Cereal은 헤더 전용 C++ 11 직렬화 라이브러리입니다. Cereal은 임의의 데이터 유형을 취하여 압축 이진 인코딩, XML 또는 JSON과 같은 다른 표현으로 가역적으로 변환합니다.
Cereal은 확장 가능하고 빠르며 단위 테스트를 거쳤으며 Boost와 같은 친숙한 구문을 제공합니다. 전체 시리얼 라이브러리를 다운로드하려면 여기를 클릭하십시오.
다음으로 시리얼 라이브러리의 사용을 보여주는 예제가 있습니다.
#include <cereal/archives/binary.hpp>
#include <cereal/types/memory.hpp>
#include <cereal/types/unordered_map.hpp>
#include <fstream>
struct MyRecord {
uint8_t x, y;
float z;
template <class Archive>
void serialize(Archive& ar) {
ar(x, y, z);
}
};
struct SomeData {
int32_t id;
std::shared_ptr<std::unordered_map<uint32_t, MyRecord>> data;
template <class Archive>
void save(Archive& ar) const {
ar(data);
}
template <class Archive>
void load(Archive& ar) {
static int32_t idGen = 0;
id = idGen++;
ar(data);
}
};
int main() {
std::ofstream out("out.cereal", std::ios::binary);
cereal::BinaryOutputArchive archive(out);
SomeData myData;
archive(myData);
return 0;
}
기본 함수에서 바이너리 모드로 os.cereal
이라는 바이너리 파일 이름을 만듭니다.
다음 줄에서는 시리얼 라이브러리의 아카이브 폴더에 정의된 binary.hpp
에서 BinaryOutputArchive
클래스의 개체를 만듭니다. 파일 개체를 BinaryOutputArchive
의 생성자에 전달하고 있습니다.
다음으로 직렬화할 데이터 개체, 즉 일부 데이터 클래스의 개체를 만듭니다. 마지막으로 기본 함수의 네 번째 줄에서 데이터 개체를 아카이브에 전달하고 save
함수를 간접적으로 호출하여 출력 파일에 데이터를 저장하고 직렬화된 개체를 출력 파일 out.cereal
에 저장합니다.
바이너리 파일 out.cereal
에는 직렬화된 데이터가 있습니다. 이 코드의 출력은 out.cereal
파일의 데이터입니다.
이 데이터는 바이너리 형식이며 다양한 운영 체제에서 사용할 수 있는 다양한 유틸리티/명령을 사용하여 확인할 수 있습니다.
HPS
HPS는 고성능 시뮬레이션 도구이며 C++11의 데이터 직렬화를 위한 헤더 전용 라이브러리입니다. HPS는 데이터를 압축 형식으로 인코딩하여 네트워크를 통해 쉽게 전달할 수 있습니다.
HPS는 표준 템플릿 라이브러리 및 기본 데이터 유형에 대한 코드 한 줄만 필요하므로 C++의 일반 부스트 직렬화보다 150% 더 빠릅니다.
write to_stream
및 from_stream
기능을 사용하여 파일에서 데이터를 읽고 쓸 수도 있습니다. HPS에 대한 더 나은 이해를 위해 이 웹사이트를 방문할 수도 있습니다.
GitHub 메시지팩
MessagePack은 오픈 소스 관련 직렬화 형식입니다. JSON 및 XML과 같은 다양한 형식의 데이터를 쉽게 교환할 수 있습니다.
정수 값은 데이터를 인코딩하는 데 1바이트만 필요하지만 문자열 값은 추가 바이트가 필요합니다.
msgpack의 추가 구현을 위해 링크를 방문할 수 있습니다.
부스트.직렬화
C++의 Boost Serialization 라이브러리를 사용하면 개체를 저장 및 로드하여 복원하기 위해 바이트로 변환할 수 있습니다. 다른 형식은 바이트 시퀀스를 생성합니다.
이러한 모든 형식은 Boost에서 지원됩니다. 직렬화는 이 라이브러리에서만 사용할 수 있습니다.
C++에서 직렬화하려는 각 개체는 직렬화
메서드를 구현해야 합니다. 아카이브를 인수로 취해야 합니다. 아카이브는 입력/출력 데이터 스트림과 유사합니다.
<<
또는 >>
연산자를 사용하는 대신 일반 연산자를 사용하여 봇 저장 및 로드 작업을 처리할 수 있습니다. 이 website에서 부스트 직렬화에 대해 읽을 수 있습니다.
아파치 아브로
Apache Avro는 데이터 직렬화 시스템입니다. Avro C++는 Avro 사양을 구현한 C++ 라이브러리로, 스트리밍 파이프라인에서 사용하기 위한 라이브러리입니다.
예를 들어 Apache Kafka는 중앙에서 관리되는 스키마로 데이터 직렬화 및 역직렬화를 수행합니다.
Avro는 코드 생성이 필요하지 않습니다. 코드 생성 도구를 사용할 수 있습니다. 코드 생성기는 스키마를 읽고 C++ 개체를 출력하여 .schema
의 스키마에 대한 데이터를 나타냅니다.
또한 이 개체를 직렬화하고 역직렬화하는 코드를 만듭니다. 여기에서 모든 무거운 코딩이 완료됩니다.
핵심 C++ 라이브러리를 사용하여 사용자 지정 직렬 변환기 또는 파서를 작성하려는 경우에도 생성된 코드는 이러한 라이브러리를 사용하는 방법의 예가 될 수 있습니다.
이 스타일은 작동할 수 있지만 완벽한 솔루션을 위해 구조체 또는 클래스를 직렬화할 수 있도록 만들 수 있습니다.
캡틴 프로토
Cap’n Proto는 RPC(원격 절차 호출) 시스템에 따라 기능이 달라지므로 데이터 형식을 쉽게 교환할 수 있습니다. Cap'n Proto
에는 인코딩/디코딩의 개념이 없습니다.
데이터 교환 형식은 인코딩 역할을 하며 메모리를 나타냅니다. 데이터를 구조화하여 디스크에서 바로 바이트를 쉽게 쓸 수 있습니다.
Cap’n Proto 페이지에서 가장 좋은 예를 찾을 수 있습니다.
절약
Apache Thrift는 언어 문제에 중점을 둔 직렬화 프레임워크입니다. IDL(인터페이스 정의 언어)에서 추상 데이터 유형을 정의할 수 있으며 지원되는 모든 언어의 소스 코드로 추가로 컴파일됩니다.
그런 다음 사용자 정의 유형에 대해 생성된 코드에 의해 완전한 직렬화가 제공됩니다. Apache Thrift는 모든 데이터 유형을 읽고 쓸 수 있도록 합니다.
이 페이지에서 Apache Thrift의 가장 좋은 예를 찾을 수 있습니다.
야스
YAS는 직렬화 속도가 느리기 때문에 Boost.serialization을 대체하기 위해 만들어졌습니다. 또한 헤더 전용 파일이며 타사 라이브러리가 필요하지 않습니다. 바이너리, 테스트 및 JSON 형식을 지원하며 C++11이 필요합니다.
이 페이지에서 YAS에 대해 읽을 수 있습니다.
모든 직렬화 라이브러리 간 비교
이 모든 라이브러리는 직렬화를 제공하며 서로 다른 기간에 있습니다. 우리는 이 라이브러리의 결과를 보여주고 있는 반면, 이 페이지에서 코드와 자세한 내용을 찾을 수 있습니다(동일한 줄은 이전 줄에서 이미 공유됨).
이 기사에서는 기사에서 가져온 결과를 보여줍니다.
이 코드는 Ubuntu 16.04를 실행하는 Intel Core i7 프로세서가 장착된 일반적인 데스크탑 컴퓨터에서 실행되었으며 평균 시간이 계산되었습니다.
시리얼라이저 | 물체의 크기 | 평균 총 시간 |
---|---|---|
중고품 바이너리 | 17017 | 1190.22 |
절약형 콤팩트 | 13378 | 3474.32 |
프로토버프 | 16116 | 2312.78 |
후원 | 17470 | 1195.04 |
msgpack | 13402 | 2560.6 |
시리얼 | 17416 | 1052.46 |
아브로 | 16384 | 4488.18 |
야스 | 17416 | 302.7 |
야스 컴팩트 | 13321 | 2063.34 |
Cap’n Proto 및 Flatbuffers는 직렬화된 형식으로 데이터를 저장합니다. 여기서 직렬화는 내부 저장소에 대한 포인터를 가져오는 것을 의미합니다. 따라서 Cap’n Proto에서는 전체 빌드/직렬화/역직렬화 주기를 측정합니다.
다른 라이브러리의 경우 이미 구축된 데이터 구조의 주기를 직렬화/역직렬화할 수도 있습니다.
시리얼라이저 | 물체의 크기 | 평균 총 시간 |
---|---|---|
캡앤프로토 | 17768 | 400.98 |
플랫버퍼 | 17632 | 491.5 |
크기에 따른 위의 데이터 표현을 보면 YAS는 다른 라이브러리보다 더 많은 개체 크기를 차지합니다. 그래도 YAS는 직렬화 시간을 고려하면 시간이 적게 걸립니다.
따라서 YAS는 모든 라이브러리 중에서 가장 빠른 직렬화를 보여줍니다.
참고: 크기는 바이트 단위로 측정되고 시간은 밀리초 단위로 측정됩니다.
이제 직렬화와 그 사용법을 이해하셨기를 바랍니다. 이제 C++에서 직렬화를 수행할 수 있는 라이브러리 또는 가장 빠르게 달성할 수 있는 라이브러리를 알 수 있습니다.