├── .gitignore ├── .ycm_extra_conf.py ├── CMakeLists.txt ├── README.md ├── benchmark.json ├── conanfile.txt ├── idl ├── capnp_service.capnp ├── grpc_service.proto └── thrift_service.thrift ├── include ├── capnp │ ├── capnp_service.capnp.h │ ├── fixture.h │ └── struct_helpers.h ├── direct │ └── fixture.h ├── grpc │ ├── fixture.h │ ├── grpc_service.grpc.pb.h │ ├── grpc_service.pb.h │ └── struct_helpers.h ├── port_numbers.h ├── rpclib │ ├── fixture.h │ └── struct_helpers.h ├── target_code.h └── thrift │ ├── ThriftServiceBenchmark.h │ ├── fixture.h │ ├── struct_helpers.h │ ├── thrift_service_constants.h │ └── thrift_service_types.h ├── plots ├── get_answer_cpu_linear.svg ├── get_answer_real_linear.svg ├── get_blob_cpu_linear.svg ├── get_blob_cpu_log.svg ├── get_blob_real_linear.svg ├── get_blob_real_log.svg ├── get_structs_cpu_linear.svg └── get_structs_real_linear.svg ├── rpclib benchmark results.ipynb ├── run_benchmarks.sh ├── scripts └── run_codegens.sh └── src ├── benchmark.cc ├── capnp ├── capnp_service.capnp.c++ └── struct_helpers.cc ├── grpc ├── grpc_service.grpc.pb.cc ├── grpc_service.pb.cc └── struct_helpers.cc ├── rpclib └── struct_helpers.cc ├── target_code.cc └── thrift ├── ThriftServiceBenchmark.cpp ├── ThriftServiceBenchmark_server.skeleton.cpp ├── struct_helpers.cc ├── thrift_service_constants.cpp └── thrift_service_types.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | build/ 2 | compile_commands.json 3 | -------------------------------------------------------------------------------- /.ycm_extra_conf.py: -------------------------------------------------------------------------------- 1 | import os 2 | import ycm_core 3 | import json 4 | 5 | def current_path(): 6 | return os.path.dirname(os.path.abspath(__file__)) 7 | 8 | compilation_database_folder = current_path() 9 | 10 | if os.path.exists(compilation_database_folder): 11 | database = ycm_core.CompilationDatabase(compilation_database_folder) 12 | else: 13 | database = None 14 | 15 | SOURCE_EXTENSIONS = ['.cc', '.inl'] 16 | 17 | def MakeRelativePathsInFlagsAbsolute(flags, working_directory): 18 | if not working_directory: 19 | return list(flags) 20 | new_flags = [] 21 | make_next_absolute = False 22 | path_flags = [ '-isystem', '-I', '-iquote', '--sysroot=' ] 23 | for flag in flags: 24 | new_flag = flag 25 | if make_next_absolute: 26 | make_next_absolute = False 27 | if not flag.startswith('/'): 28 | new_flag = os.path.join(working_directory, flag) 29 | for path_flag in path_flags: 30 | if flag == path_flag: 31 | make_next_absolute = True 32 | break 33 | if flag.startswith(path_flag): 34 | path = flag[ len(path_flag): ] 35 | new_flag = path_flag + os.path.join(working_directory, path) 36 | break 37 | if new_flag: 38 | new_flags.append(new_flag) 39 | return new_flags 40 | 41 | 42 | def IsHeaderFile(filename): 43 | extension = os.path.splitext(filename)[ 1 ] 44 | return extension in [ '.h', '.hxx', '.hpp', '.hh', '.inl' ] 45 | 46 | 47 | # load the flags of the first entry from the compilation db. 48 | def LoadDefaultFlags(): 49 | db = json.load(open(os.path.join(compilation_database_folder, 'compile_commands.json'))) 50 | return db[0]['command'].split()[1:-4] 51 | 52 | default_flags = LoadDefaultFlags() 53 | 54 | extra_flags = [ 55 | '-fexceptions', 56 | '-DNDEBUG', 57 | '-std=c++14', 58 | '-x', 59 | 'c++', 60 | '-I', os.path.join(current_path(), 'include'), 61 | '-isystem/usr/bin/../include/c++/v1', 62 | '-isystem/usr/local/include', 63 | '-isystem/usr/bin/../lib/clang/3.9.1/include', 64 | '-isystem/usr/include' 65 | ] 66 | 67 | 68 | # The compilation_commands.json file generated by CMake does not have entries 69 | # for header files. So we do our best by asking the db for flags for a 70 | # corresponding source file, if any. If one exists, the flags for that file 71 | # should be good enough. 72 | def GetCompilationInfoForFile(filename): 73 | if IsHeaderFile(filename): 74 | basename = os.path.splitext(filename)[0].replace('include', 'lib') 75 | replacement_file = basename + '.cc' 76 | if os.path.exists(replacement_file): 77 | compilation_info = database.GetCompilationInfoForFile( 78 | replacement_file) 79 | if compilation_info.compiler_flags_: 80 | return compilation_info 81 | return None 82 | return database.GetCompilationInfoForFile(filename) 83 | 84 | 85 | def FlagsForFile(filename, **kwargs): 86 | global extra_flags 87 | global default_flags 88 | if database: 89 | compilation_info = GetCompilationInfoForFile(filename) 90 | if not compilation_info: 91 | final_flags = default_flags 92 | else: 93 | final_flags = MakeRelativePathsInFlagsAbsolute( 94 | compilation_info.compiler_flags_, 95 | compilation_info.compiler_working_dir_) 96 | else: 97 | relative_to = current_path() 98 | final_flags = MakeRelativePathsInFlagsAbsolute(flags, relative_to) 99 | 100 | final_flags.extend(extra_flags) 101 | 102 | return {'flags': final_flags, 'do_cache': True} 103 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.0.0) 2 | project(rpclib_benchmark) 3 | 4 | macro(remove_cxx_flag flag) 5 | string(REPLACE "${flag}" "" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}") 6 | endmacro() 7 | 8 | option(USE_O2 "Use -O2 instead of the default -O3" OFF) 9 | 10 | if (NOT CMAKE_BUILD_TYPE STREQUAL "Release") 11 | message(WARNING "Not building in release mode!") 12 | else() 13 | if (USE_O2) 14 | remove_cxx_flag("-O3") 15 | set(CMAKE_CXX_FLAGS_RELEASE "-O2 ${CMAKE_CXX_FLAGS_RELEASE}") 16 | endif() 17 | message(STATUS "Release flags: ${CMAKE_CXX_FLAGS_RELEASE}") 18 | endif() 19 | 20 | 21 | set(CMAKE_EXPORT_COMPILE_COMMANDS "ON") # for YCM 22 | 23 | if(EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/build/conanbuildinfo.cmake) #Clion, with conanbuildinfo.cmake in build folder 24 | include(${CMAKE_CURRENT_SOURCE_DIR}/build/conanbuildinfo.cmake) 25 | else() 26 | include(${CMAKE_BINARY_DIR}/conanbuildinfo.cmake) # Not CLion 27 | endif() 28 | 29 | conan_basic_setup() 30 | 31 | add_executable(rpclib_benchmark 32 | src/target_code.cc 33 | src/benchmark.cc 34 | src/capnp/capnp_service.capnp.c++ 35 | src/thrift/thrift_service_constants.cpp 36 | src/thrift/thrift_service_types.cpp 37 | src/thrift/ThriftServiceBenchmark.cpp 38 | src/thrift/struct_helpers.cc 39 | src/grpc/grpc_service.pb.cc 40 | src/grpc/grpc_service.grpc.pb.cc 41 | src/grpc/struct_helpers.cc 42 | src/rpclib/struct_helpers.cc 43 | src/capnp/struct_helpers.cc 44 | ) 45 | 46 | target_link_libraries(rpclib_benchmark ${CONAN_LIBS}) 47 | set_target_properties( 48 | rpclib_benchmark 49 | PROPERTIES 50 | CXX_STANDARD 14) 51 | target_compile_definitions(rpclib_benchmark PUBLIC ${CONAN_DEFINES}) 52 | target_include_directories(rpclib_benchmark PUBLIC include) 53 | target_include_directories(rpclib_benchmark PUBLIC include/thrift) 54 | target_include_directories(rpclib_benchmark PUBLIC include/capnp) 55 | target_include_directories(rpclib_benchmark PUBLIC include/grpc) 56 | 57 | add_custom_command(TARGET rpclib_benchmark POST_BUILD 58 | COMMAND ${CMAKE_COMMAND} -E 59 | copy ${CMAKE_BINARY_DIR}/compile_commands.json ${CMAKE_BINARY_DIR}/../compile_commands.json) 60 | 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # rpclib benchmarks 2 | 3 | This is a set of benchmarks that compares the performance of various RPC libraries/frameworks in 4 | specific situations. The benchmark suite is created as part of the [rpclib](http://rpclib.net) 5 | project. 6 | 7 | ## Libraries 8 | 9 | The following libraries are or will be benchmarked: 10 | 11 | - [x] [rpclib](http://rpclib.net) 12 | - [x] [cap'n'proto rpc](https://capnproto.org/cxxrpc.html) 13 | - [x] [Apache Thrift](https://thrift.apache.org/) 14 | - [x] [grpc](https://grpc.io) 15 | - [x] +1: Direct function calls (for comparison) 16 | 17 | ## Results 18 | 19 | The results can be found in this repository (json files and plots, plus a [Jupyter Notebook](https://github.com/rpclib/benchmarks/blob/master/rpclib%20benchmark%20results.ipynb)). I've also written a blog post about this: http://szelei.me/rpc-benchmark-part1/ 20 | 21 | ## Compiling and running 22 | 23 | Currently, this benchmark set can only be compiled on Linux. Even though all libraries are cross-platform, the conan packages I'm using aren't. 24 | 25 | ### Requirements 26 | 27 | * A reasonably modern Linux distribution (tested on Arch Linux and Ubuntu 16.04) 28 | * g++ 5.4 or later, or clang-3.8 or later 29 | * cmake 3.x 30 | 31 | #### Build steps 32 | 33 | ``` 34 | mkdir build && cd build 35 | conan install .. --build missing 36 | cmake .. 37 | make 38 | ``` 39 | 40 | #### Running the benchmarks 41 | 42 | I suggest using the `run_benchmarks.sh` script. It took about 40 minutes no my machine to complete all benchmark runs. 43 | 44 | ## FAQ 45 | 46 | ### What kind of benchmarks are performed? 47 | 48 | These are the benchmarks that are implemented or will be implemented for each 49 | library from the above list. 50 | 51 | - [x] `get_answer`: Perform a function call that returns a number and deserialize 52 | the result (so that it's available for the user code as an `int`) 53 | - [x] `get_blob`: Perform a function call that returns a large blob and deserialize it into 54 | a byte buffer. This is performed in increasing sizes. 55 | - [x] `get_struct`: Perform a function call that returns a nested struct with lots of 56 | fields and lots of data in it and intentionally bad alignment. 57 | 58 | Each library is set up to create local client and server that communicate through a TCP socket. 59 | 60 | ### How are the benchmarks ran? 61 | 62 | This benchmark suite uses [Google Benchmark](https://github.com/google/benchmark) to manage the 63 | benchmarking. Each library has a fixture that is set up and torn down in each benchmark run once 64 | (similarly to unit tests). The setup and teardown performance is not measured. Each microbenchmark is performed in a number of 65 | iterations (determined by Google Benchmark). All runs are performed five times. The results are the means, medians and standard deviations of the 66 | remaining three measured times. 67 | 68 | ### What is `rpclib`? 69 | 70 | `rpclib` is a modern msgpack-rpc implementation for C++. It provides a very clean interface 71 | inspired by Boost.Python. See [rpclib.net](http://rpclib.net) for more information. 72 | 73 | ### I think your implementation for library XYZ is suboptimal. Will you change it? 74 | 75 | Probably yes, please send a PR. I'm not an expert in the other libraries, so it's entirely possible 76 | that I used them wrong. 77 | 78 | ### Why don't you measure against library XYZ? 79 | 80 | One or more of the following reasons: 81 | 82 | * I did not know about the library 83 | * There was no conan package for it and I didn't have time to make one 84 | * I didn't have time to learn the library 85 | * The library wasn't to my knowledge widespread enough to be interesting for this comparison. 86 | 87 | However, by all means, please let me know if there is one that is worth looking at. Bonus points if 88 | you make a conan package and/or pull request with benchmark code for it. 89 | 90 | -------------------------------------------------------------------------------- /conanfile.txt: -------------------------------------------------------------------------------- 1 | [requires] 2 | google-benchmark/1.1.0@cpace6/stable 3 | capnproto/0.5.3@lasote/stable 4 | thrift/0.9.3@sztomi/testing 5 | grpc/1.1.0@sztomi/testing 6 | rpclib/1.0.0@sztomi/testing 7 | 8 | [options] 9 | rpclib:enable_logging=False 10 | protobuf:shared=True 11 | 12 | [generators] 13 | cmake 14 | virtualenv 15 | -------------------------------------------------------------------------------- /idl/capnp_service.capnp: -------------------------------------------------------------------------------- 1 | 2 | @0xd4857e0f5efbe114; 3 | 4 | using Cxx = import "/capnp/c++.capnp"; 5 | $Cxx.namespace("capnp_code"); 6 | 7 | struct Date { 8 | year @0 :Int32; 9 | month @1 :Int8; 10 | day @2 :Int8; 11 | } 12 | 13 | struct Address { 14 | city @0 :Text; 15 | zipcode @1 :Int32; 16 | street @2 :Text; 17 | number @3 :Int16; 18 | } 19 | 20 | struct School { 21 | name @0 :Text; 22 | address @1 :Address; 23 | foundation @2 :Date; 24 | emailAddresses @3 :List(Text); 25 | } 26 | 27 | struct Subject { 28 | id @0 :Int32; 29 | title @1 :Text; 30 | code @2 :Text; 31 | } 32 | 33 | struct Student { 34 | name @0 :Text; 35 | friends @1 :Int32; 36 | homeAddress @2 :Address; 37 | birthPlace @3 :Address; 38 | birth @4 :Date; 39 | favoriteSubjects @5 :List(Subject); 40 | emailAddresses @6 :List(Text); 41 | schools @7 :List(School); 42 | } 43 | 44 | struct StudentDataResponse { 45 | students @0 :List(Student); 46 | } 47 | 48 | interface CapnpServiceBenchmark { 49 | getAnswer @0 (number :Int32) -> (result :Int32); 50 | getBlob @1 () -> (result :Data); 51 | getStructs @2 () -> (result :StudentDataResponse); 52 | } 53 | -------------------------------------------------------------------------------- /idl/grpc_service.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | package grpc_code; 4 | 5 | message AnswerRequest { 6 | int32 number = 1; 7 | } 8 | 9 | message AnswerReply { 10 | int32 result = 1; 11 | } 12 | 13 | message EmptyRequest { } 14 | 15 | message BlobResponse { 16 | bytes data = 1; 17 | } 18 | 19 | message Date { 20 | int32 year = 1; 21 | // note: no fixed 1-byte type in protobuf, 22 | // but during encoding it is going to use the 23 | // smallest possible size anyway (like many others) 24 | int32 month = 2; 25 | int32 day = 3; 26 | } 27 | 28 | message Address { 29 | string city = 1; 30 | int32 zipcode = 2; 31 | string street = 3; 32 | int32 number = 4; 33 | } 34 | 35 | message School { 36 | string name = 1; 37 | Address address = 2; 38 | Date foundation = 3; 39 | repeated string email_addresses = 4; 40 | } 41 | 42 | message Subject { 43 | int32 id = 1; 44 | string title = 2; 45 | string code = 3; 46 | } 47 | 48 | message Student { 49 | string name = 1; 50 | int32 friends = 2; 51 | Address home_address = 3; 52 | Address birth_place = 4; 53 | Date birth = 5; 54 | repeated Subject favorite_subjects = 6; 55 | repeated string email_addresses = 7; 56 | repeated School schools = 8; 57 | } 58 | 59 | message StudentDataResponse { 60 | repeated Student students = 1; 61 | } 62 | 63 | service GrpcServiceBenchmark { 64 | rpc get_answer (AnswerRequest) returns (AnswerReply) {} 65 | rpc get_blob (EmptyRequest) returns (BlobResponse) {} 66 | rpc get_structs (EmptyRequest) returns (StudentDataResponse) {} 67 | } 68 | 69 | -------------------------------------------------------------------------------- /idl/thrift_service.thrift: -------------------------------------------------------------------------------- 1 | namespace cpp thrift_code 2 | 3 | struct Date { 4 | 1:i32 year; 5 | 2:byte month; 6 | 3:byte day; 7 | } 8 | 9 | struct Address { 10 | 1:string city; 11 | 2:i32 zipcode; 12 | 3:string street; 13 | 4:i16 number; 14 | } 15 | 16 | struct School { 17 | 1:string name; 18 | 2:Address address; 19 | 3:Date foundation; 20 | 4:list email_addresses; 21 | } 22 | 23 | struct Subject { 24 | 1:i32 id; 25 | 2:string title; 26 | 3:string code; 27 | } 28 | 29 | struct Student { 30 | 1:string name; 31 | 2:i32 friends; 32 | 3:Address home_address; 33 | 4:Address birth_place; 34 | 5:Date birth; 35 | 6:list favorite_subjects; 36 | 7:list email_addresses; 37 | 8:list schools; 38 | } 39 | 40 | service ThriftServiceBenchmark { 41 | i32 get_answer(1:i32 number); 42 | binary get_blob(); 43 | list get_structs(); 44 | } 45 | 46 | -------------------------------------------------------------------------------- /include/capnp/fixture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef FIXTURE_H_NNOJDJZG 4 | #define FIXTURE_H_NNOJDJZG 5 | 6 | #include "benchmark/benchmark.h" 7 | 8 | #include 9 | 10 | #include "capnp/capnp_service.capnp.h" 11 | #include "capnp/struct_helpers.h" 12 | #include "target_code.h" 13 | #include "port_numbers.h" 14 | 15 | class capnp_bench : public benchmark::Fixture { 16 | private: 17 | static int blob_size_; 18 | class capnp_server : public capnp_code::CapnpServiceBenchmark::Server { 19 | public: 20 | kj::Promise getAnswer(GetAnswerContext context) override { 21 | auto num = context.getParams().getNumber(); 22 | context.getResults().setResult(::get_answer(num)); 23 | return kj::READY_NOW; 24 | } 25 | 26 | kj::Promise getBlob(GetBlobContext context) override { 27 | auto& blob = ::get_blob(blob_size_); 28 | kj::ArrayPtr arr((unsigned char *)blob.data(), 29 | blob.size()); 30 | context.getResults().setResult(capnp::Data::Reader(arr)); 31 | return kj::READY_NOW; 32 | } 33 | 34 | kj::Promise getStructs(GetStructsContext context) override { 35 | context.getResults().setResult(capnp_code::get_structs()); 36 | return kj::READY_NOW; 37 | } 38 | }; 39 | 40 | public: 41 | void SetUp(benchmark::State &) override { 42 | using std::make_unique; 43 | server_addr_ = "127.0.0.1:" + std::to_string(capnp_port); 44 | server = make_unique(kj::heap(), 45 | server_addr_); 46 | reader_options = {256 * 1024 * 1024, 64}; 47 | client_thing = 48 | make_unique(server_addr_, 8080, reader_options); 49 | client = make_unique( 50 | client_thing->getMain()); 51 | auto &wait_scope = server->getWaitScope(); 52 | server->getPort().wait(wait_scope); 53 | } 54 | 55 | void TearDown(benchmark::State &) override { 56 | server.reset(); 57 | client.reset(); 58 | client_thing.reset(); 59 | } 60 | 61 | void get_answer(int param) { 62 | (void)param; 63 | auto request = client->getAnswerRequest(); 64 | request.setNumber(23); 65 | auto resultPromise = request.send(); 66 | int a; 67 | benchmark::DoNotOptimize( 68 | a = resultPromise.wait(client_thing->getWaitScope()).getResult()); 69 | } 70 | 71 | void get_blob(int param) { 72 | blob_size_ = param; 73 | auto request = client->getBlobRequest(); 74 | auto resultPromise = request.send(); 75 | auto result = resultPromise.wait(client_thing->getWaitScope()); 76 | benchmark::DoNotOptimize(result.getResult().size()); 77 | } 78 | 79 | void get_structs(int param) { 80 | (void)param; 81 | auto request = client->getStructsRequest(); 82 | auto resultPromise = request.send(); 83 | auto result = resultPromise.wait(client_thing->getWaitScope()) 84 | .getResult() 85 | .getStudents(); 86 | std::size_t count; 87 | benchmark::DoNotOptimize(count = result.size()); 88 | } 89 | 90 | ~capnp_bench() noexcept {} 91 | 92 | std::unique_ptr server; 93 | capnp::ReaderOptions reader_options; 94 | std::unique_ptr client_thing; 95 | std::unique_ptr client; 96 | std::string server_addr_; 97 | }; 98 | 99 | #endif /* end of include guard: FIXTURE_H_NNOJDJZG */ 100 | -------------------------------------------------------------------------------- /include/capnp/struct_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef STRUCT_HELPERS_H_8D7IKUZ5 4 | #define STRUCT_HELPERS_H_8D7IKUZ5 5 | 6 | #include 7 | #include 8 | 9 | #include "capnp/capnp_service.capnp.h" 10 | 11 | namespace capnp_code { 12 | 13 | StudentDataResponse::Builder& get_structs(); 14 | void fill_struct_cache(); 15 | 16 | } /* capnp_code */ 17 | 18 | #endif /* end of include guard: STRUCT_HELPERS_H_8D7IKUZ5 */ 19 | -------------------------------------------------------------------------------- /include/direct/fixture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef FIXTURE_H_RFGFCJ3X 4 | #define FIXTURE_H_RFGFCJ3X 5 | 6 | #include "benchmark/benchmark.h" 7 | 8 | #include "target_code.h" 9 | #include "rpclib/struct_helpers.h" 10 | 11 | // direct function call 12 | class direct_bench : public benchmark::Fixture { 13 | public: 14 | void get_answer(int param) { 15 | (void)param; 16 | int a; 17 | benchmark::DoNotOptimize(a = ::get_answer(23)); 18 | } 19 | 20 | void get_blob(int param) { 21 | const std::string* s; 22 | benchmark::DoNotOptimize(s = &::get_blob(param)); 23 | std::size_t size; 24 | benchmark::DoNotOptimize(size = s->size()); 25 | } 26 | 27 | void get_structs(int param) { 28 | std::vector result; 29 | benchmark::DoNotOptimize(result = rpclib_code::get_structs()); 30 | } 31 | }; 32 | 33 | #endif /* end of include guard: FIXTURE_H_RFGFCJ3X */ 34 | -------------------------------------------------------------------------------- /include/grpc/fixture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef FIXTURE_H_EQKIMOI3 4 | #define FIXTURE_H_EQKIMOI3 5 | 6 | #include 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "benchmark/benchmark.h" 18 | 19 | #include "grpc/grpc_service.grpc.pb.h" 20 | #include "grpc/struct_helpers.h" 21 | 22 | #include "target_code.h" 23 | #include "port_numbers.h" 24 | 25 | 26 | class grpc_service : public grpc_code::GrpcServiceBenchmark::Service { 27 | public: 28 | ::grpc::Status get_answer(::grpc::ServerContext *context, 29 | const grpc_code::AnswerRequest *request, 30 | grpc_code::AnswerReply *response) override { 31 | auto num = request->number(); 32 | response->set_result(::get_answer(num)); 33 | return ::grpc::Status::OK; 34 | } 35 | 36 | ::grpc::Status get_blob(::grpc::ServerContext *context, 37 | const grpc_code::EmptyRequest *request, 38 | grpc_code::BlobResponse *response) override { 39 | response->set_data(::get_blob(blob_size_)); 40 | return ::grpc::Status::OK; 41 | } 42 | 43 | ::grpc::Status 44 | get_structs(::grpc::ServerContext *context, 45 | const grpc_code::EmptyRequest *request, 46 | grpc_code::StudentDataResponse *response) override { 47 | response->CopyFrom(grpc_code::get_structs()); 48 | return ::grpc::Status::OK; 49 | } 50 | int blob_size_; 51 | }; 52 | 53 | class grpc_bench : public benchmark::Fixture { 54 | public: 55 | grpc_bench() 56 | : server_addr_("localhost:" + std::to_string(grpc_port)), 57 | channel_(grpc::CreateChannel(server_addr_, 58 | grpc::InsecureChannelCredentials())), 59 | client_(channel_) { 60 | grpc::ServerBuilder b; 61 | b.AddListeningPort(server_addr_, grpc::InsecureServerCredentials()); 62 | b.RegisterService(&service_impl_); 63 | server_ = b.BuildAndStart(); 64 | } 65 | 66 | void get_answer(int param) { 67 | (void)param; 68 | grpc::ClientContext client_context; 69 | grpc_code::AnswerRequest request; 70 | grpc_code::AnswerReply response; 71 | request.set_number(23); 72 | auto status = client_.get_answer(&client_context, request, &response); 73 | int a; 74 | benchmark::DoNotOptimize(a = response.result()); 75 | } 76 | 77 | void get_blob(int param) { 78 | service_impl_.blob_size_ = param; 79 | grpc::ClientContext client_context; 80 | grpc_code::EmptyRequest request; 81 | grpc_code::BlobResponse response; 82 | auto status = client_.get_blob(&client_context, request, &response); 83 | std::string const& s = response.data(); 84 | std::size_t size; 85 | benchmark::DoNotOptimize(size = s.size()); 86 | } 87 | 88 | void get_structs(int param) { 89 | (void)param; 90 | grpc::ClientContext client_context; 91 | grpc_code::EmptyRequest request; 92 | grpc_code::StudentDataResponse response; 93 | auto status = client_.get_structs(&client_context, request, &response); 94 | std::size_t count; 95 | benchmark::DoNotOptimize(count = response.students_size()); 96 | } 97 | 98 | ~grpc_bench() noexcept { server_->Shutdown(); } 99 | 100 | std::string server_addr_; 101 | std::shared_ptr channel_; 102 | grpc_code::GrpcServiceBenchmark::Stub client_; 103 | std::unique_ptr server_; 104 | grpc_service service_impl_; 105 | }; 106 | 107 | #endif /* end of include guard: FIXTURE_H_EQKIMOI3 */ 108 | -------------------------------------------------------------------------------- /include/grpc/grpc_service.grpc.pb.h: -------------------------------------------------------------------------------- 1 | // Generated by the gRPC protobuf plugin. 2 | // If you make any local change, they will be lost. 3 | // source: grpc_service.proto 4 | #ifndef GRPC_grpc_5fservice_2eproto__INCLUDED 5 | #define GRPC_grpc_5fservice_2eproto__INCLUDED 6 | 7 | #include "grpc_service.pb.h" 8 | 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | namespace grpc { 20 | class CompletionQueue; 21 | class Channel; 22 | class RpcService; 23 | class ServerCompletionQueue; 24 | class ServerContext; 25 | } // namespace grpc 26 | 27 | namespace grpc_code { 28 | 29 | class GrpcServiceBenchmark final { 30 | public: 31 | class StubInterface { 32 | public: 33 | virtual ~StubInterface() {} 34 | virtual ::grpc::Status get_answer(::grpc::ClientContext* context, const ::grpc_code::AnswerRequest& request, ::grpc_code::AnswerReply* response) = 0; 35 | std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::grpc_code::AnswerReply>> Asyncget_answer(::grpc::ClientContext* context, const ::grpc_code::AnswerRequest& request, ::grpc::CompletionQueue* cq) { 36 | return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::grpc_code::AnswerReply>>(Asyncget_answerRaw(context, request, cq)); 37 | } 38 | virtual ::grpc::Status get_blob(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc_code::BlobResponse* response) = 0; 39 | std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::grpc_code::BlobResponse>> Asyncget_blob(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) { 40 | return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::grpc_code::BlobResponse>>(Asyncget_blobRaw(context, request, cq)); 41 | } 42 | virtual ::grpc::Status get_structs(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc_code::StudentDataResponse* response) = 0; 43 | std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::grpc_code::StudentDataResponse>> Asyncget_structs(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) { 44 | return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::grpc_code::StudentDataResponse>>(Asyncget_structsRaw(context, request, cq)); 45 | } 46 | private: 47 | virtual ::grpc::ClientAsyncResponseReaderInterface< ::grpc_code::AnswerReply>* Asyncget_answerRaw(::grpc::ClientContext* context, const ::grpc_code::AnswerRequest& request, ::grpc::CompletionQueue* cq) = 0; 48 | virtual ::grpc::ClientAsyncResponseReaderInterface< ::grpc_code::BlobResponse>* Asyncget_blobRaw(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) = 0; 49 | virtual ::grpc::ClientAsyncResponseReaderInterface< ::grpc_code::StudentDataResponse>* Asyncget_structsRaw(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) = 0; 50 | }; 51 | class Stub final : public StubInterface { 52 | public: 53 | Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel); 54 | ::grpc::Status get_answer(::grpc::ClientContext* context, const ::grpc_code::AnswerRequest& request, ::grpc_code::AnswerReply* response) override; 55 | std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc_code::AnswerReply>> Asyncget_answer(::grpc::ClientContext* context, const ::grpc_code::AnswerRequest& request, ::grpc::CompletionQueue* cq) { 56 | return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc_code::AnswerReply>>(Asyncget_answerRaw(context, request, cq)); 57 | } 58 | ::grpc::Status get_blob(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc_code::BlobResponse* response) override; 59 | std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc_code::BlobResponse>> Asyncget_blob(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) { 60 | return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc_code::BlobResponse>>(Asyncget_blobRaw(context, request, cq)); 61 | } 62 | ::grpc::Status get_structs(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc_code::StudentDataResponse* response) override; 63 | std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc_code::StudentDataResponse>> Asyncget_structs(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) { 64 | return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::grpc_code::StudentDataResponse>>(Asyncget_structsRaw(context, request, cq)); 65 | } 66 | 67 | private: 68 | std::shared_ptr< ::grpc::ChannelInterface> channel_; 69 | ::grpc::ClientAsyncResponseReader< ::grpc_code::AnswerReply>* Asyncget_answerRaw(::grpc::ClientContext* context, const ::grpc_code::AnswerRequest& request, ::grpc::CompletionQueue* cq) override; 70 | ::grpc::ClientAsyncResponseReader< ::grpc_code::BlobResponse>* Asyncget_blobRaw(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) override; 71 | ::grpc::ClientAsyncResponseReader< ::grpc_code::StudentDataResponse>* Asyncget_structsRaw(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) override; 72 | const ::grpc::RpcMethod rpcmethod_get_answer_; 73 | const ::grpc::RpcMethod rpcmethod_get_blob_; 74 | const ::grpc::RpcMethod rpcmethod_get_structs_; 75 | }; 76 | static std::unique_ptr NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options = ::grpc::StubOptions()); 77 | 78 | class Service : public ::grpc::Service { 79 | public: 80 | Service(); 81 | virtual ~Service(); 82 | virtual ::grpc::Status get_answer(::grpc::ServerContext* context, const ::grpc_code::AnswerRequest* request, ::grpc_code::AnswerReply* response); 83 | virtual ::grpc::Status get_blob(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::BlobResponse* response); 84 | virtual ::grpc::Status get_structs(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::StudentDataResponse* response); 85 | }; 86 | template 87 | class WithAsyncMethod_get_answer : public BaseClass { 88 | private: 89 | void BaseClassMustBeDerivedFromService(const Service *service) {} 90 | public: 91 | WithAsyncMethod_get_answer() { 92 | ::grpc::Service::MarkMethodAsync(0); 93 | } 94 | ~WithAsyncMethod_get_answer() override { 95 | BaseClassMustBeDerivedFromService(this); 96 | } 97 | // disable synchronous version of this method 98 | ::grpc::Status get_answer(::grpc::ServerContext* context, const ::grpc_code::AnswerRequest* request, ::grpc_code::AnswerReply* response) final override { 99 | abort(); 100 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 101 | } 102 | void Requestget_answer(::grpc::ServerContext* context, ::grpc_code::AnswerRequest* request, ::grpc::ServerAsyncResponseWriter< ::grpc_code::AnswerReply>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { 103 | ::grpc::Service::RequestAsyncUnary(0, context, request, response, new_call_cq, notification_cq, tag); 104 | } 105 | }; 106 | template 107 | class WithAsyncMethod_get_blob : public BaseClass { 108 | private: 109 | void BaseClassMustBeDerivedFromService(const Service *service) {} 110 | public: 111 | WithAsyncMethod_get_blob() { 112 | ::grpc::Service::MarkMethodAsync(1); 113 | } 114 | ~WithAsyncMethod_get_blob() override { 115 | BaseClassMustBeDerivedFromService(this); 116 | } 117 | // disable synchronous version of this method 118 | ::grpc::Status get_blob(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::BlobResponse* response) final override { 119 | abort(); 120 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 121 | } 122 | void Requestget_blob(::grpc::ServerContext* context, ::grpc_code::EmptyRequest* request, ::grpc::ServerAsyncResponseWriter< ::grpc_code::BlobResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { 123 | ::grpc::Service::RequestAsyncUnary(1, context, request, response, new_call_cq, notification_cq, tag); 124 | } 125 | }; 126 | template 127 | class WithAsyncMethod_get_structs : public BaseClass { 128 | private: 129 | void BaseClassMustBeDerivedFromService(const Service *service) {} 130 | public: 131 | WithAsyncMethod_get_structs() { 132 | ::grpc::Service::MarkMethodAsync(2); 133 | } 134 | ~WithAsyncMethod_get_structs() override { 135 | BaseClassMustBeDerivedFromService(this); 136 | } 137 | // disable synchronous version of this method 138 | ::grpc::Status get_structs(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::StudentDataResponse* response) final override { 139 | abort(); 140 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 141 | } 142 | void Requestget_structs(::grpc::ServerContext* context, ::grpc_code::EmptyRequest* request, ::grpc::ServerAsyncResponseWriter< ::grpc_code::StudentDataResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { 143 | ::grpc::Service::RequestAsyncUnary(2, context, request, response, new_call_cq, notification_cq, tag); 144 | } 145 | }; 146 | typedef WithAsyncMethod_get_answer > > AsyncService; 147 | template 148 | class WithGenericMethod_get_answer : public BaseClass { 149 | private: 150 | void BaseClassMustBeDerivedFromService(const Service *service) {} 151 | public: 152 | WithGenericMethod_get_answer() { 153 | ::grpc::Service::MarkMethodGeneric(0); 154 | } 155 | ~WithGenericMethod_get_answer() override { 156 | BaseClassMustBeDerivedFromService(this); 157 | } 158 | // disable synchronous version of this method 159 | ::grpc::Status get_answer(::grpc::ServerContext* context, const ::grpc_code::AnswerRequest* request, ::grpc_code::AnswerReply* response) final override { 160 | abort(); 161 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 162 | } 163 | }; 164 | template 165 | class WithGenericMethod_get_blob : public BaseClass { 166 | private: 167 | void BaseClassMustBeDerivedFromService(const Service *service) {} 168 | public: 169 | WithGenericMethod_get_blob() { 170 | ::grpc::Service::MarkMethodGeneric(1); 171 | } 172 | ~WithGenericMethod_get_blob() override { 173 | BaseClassMustBeDerivedFromService(this); 174 | } 175 | // disable synchronous version of this method 176 | ::grpc::Status get_blob(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::BlobResponse* response) final override { 177 | abort(); 178 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 179 | } 180 | }; 181 | template 182 | class WithGenericMethod_get_structs : public BaseClass { 183 | private: 184 | void BaseClassMustBeDerivedFromService(const Service *service) {} 185 | public: 186 | WithGenericMethod_get_structs() { 187 | ::grpc::Service::MarkMethodGeneric(2); 188 | } 189 | ~WithGenericMethod_get_structs() override { 190 | BaseClassMustBeDerivedFromService(this); 191 | } 192 | // disable synchronous version of this method 193 | ::grpc::Status get_structs(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::StudentDataResponse* response) final override { 194 | abort(); 195 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 196 | } 197 | }; 198 | template 199 | class WithStreamedUnaryMethod_get_answer : public BaseClass { 200 | private: 201 | void BaseClassMustBeDerivedFromService(const Service *service) {} 202 | public: 203 | WithStreamedUnaryMethod_get_answer() { 204 | ::grpc::Service::MarkMethodStreamed(0, 205 | new ::grpc::StreamedUnaryHandler< ::grpc_code::AnswerRequest, ::grpc_code::AnswerReply>(std::bind(&WithStreamedUnaryMethod_get_answer::Streamedget_answer, this, std::placeholders::_1, std::placeholders::_2))); 206 | } 207 | ~WithStreamedUnaryMethod_get_answer() override { 208 | BaseClassMustBeDerivedFromService(this); 209 | } 210 | // disable regular version of this method 211 | ::grpc::Status get_answer(::grpc::ServerContext* context, const ::grpc_code::AnswerRequest* request, ::grpc_code::AnswerReply* response) final override { 212 | abort(); 213 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 214 | } 215 | // replace default version of method with streamed unary 216 | virtual ::grpc::Status Streamedget_answer(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::grpc_code::AnswerRequest,::grpc_code::AnswerReply>* server_unary_streamer) = 0; 217 | }; 218 | template 219 | class WithStreamedUnaryMethod_get_blob : public BaseClass { 220 | private: 221 | void BaseClassMustBeDerivedFromService(const Service *service) {} 222 | public: 223 | WithStreamedUnaryMethod_get_blob() { 224 | ::grpc::Service::MarkMethodStreamed(1, 225 | new ::grpc::StreamedUnaryHandler< ::grpc_code::EmptyRequest, ::grpc_code::BlobResponse>(std::bind(&WithStreamedUnaryMethod_get_blob::Streamedget_blob, this, std::placeholders::_1, std::placeholders::_2))); 226 | } 227 | ~WithStreamedUnaryMethod_get_blob() override { 228 | BaseClassMustBeDerivedFromService(this); 229 | } 230 | // disable regular version of this method 231 | ::grpc::Status get_blob(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::BlobResponse* response) final override { 232 | abort(); 233 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 234 | } 235 | // replace default version of method with streamed unary 236 | virtual ::grpc::Status Streamedget_blob(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::grpc_code::EmptyRequest,::grpc_code::BlobResponse>* server_unary_streamer) = 0; 237 | }; 238 | template 239 | class WithStreamedUnaryMethod_get_structs : public BaseClass { 240 | private: 241 | void BaseClassMustBeDerivedFromService(const Service *service) {} 242 | public: 243 | WithStreamedUnaryMethod_get_structs() { 244 | ::grpc::Service::MarkMethodStreamed(2, 245 | new ::grpc::StreamedUnaryHandler< ::grpc_code::EmptyRequest, ::grpc_code::StudentDataResponse>(std::bind(&WithStreamedUnaryMethod_get_structs::Streamedget_structs, this, std::placeholders::_1, std::placeholders::_2))); 246 | } 247 | ~WithStreamedUnaryMethod_get_structs() override { 248 | BaseClassMustBeDerivedFromService(this); 249 | } 250 | // disable regular version of this method 251 | ::grpc::Status get_structs(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::StudentDataResponse* response) final override { 252 | abort(); 253 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 254 | } 255 | // replace default version of method with streamed unary 256 | virtual ::grpc::Status Streamedget_structs(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::grpc_code::EmptyRequest,::grpc_code::StudentDataResponse>* server_unary_streamer) = 0; 257 | }; 258 | typedef WithStreamedUnaryMethod_get_answer > > StreamedUnaryService; 259 | typedef Service SplitStreamedService; 260 | typedef WithStreamedUnaryMethod_get_answer > > StreamedService; 261 | }; 262 | 263 | } // namespace grpc_code 264 | 265 | 266 | #endif // GRPC_grpc_5fservice_2eproto__INCLUDED 267 | -------------------------------------------------------------------------------- /include/grpc/struct_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef STRUCT_HELPERS_H_9WVRLQU4 4 | #define STRUCT_HELPERS_H_9WVRLQU4 5 | 6 | #include 7 | #include "grpc/grpc_service.pb.h" 8 | 9 | namespace grpc_code { 10 | 11 | StudentDataResponse& get_structs(); 12 | void fill_struct_cache(); 13 | 14 | } 15 | 16 | #endif /* end of include guard: STRUCT_HELPERS_H_9WVRLQU4 */ 17 | -------------------------------------------------------------------------------- /include/port_numbers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef PORT_NUMBERS_H_JXF3U5KE 4 | #define PORT_NUMBERS_H_JXF3U5KE 5 | 6 | static constexpr unsigned short rpclib_port = 12890; 7 | static constexpr unsigned short capnp_port = 12891; 8 | static constexpr unsigned short thrift_port = 12892; 9 | static constexpr unsigned short grpc_port = 12893; 10 | 11 | 12 | #endif /* end of include guard: PORT_NUMBERS_H_JXF3U5KE */ 13 | -------------------------------------------------------------------------------- /include/rpclib/fixture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef FIXTURE_H_EWLDRJT7 4 | #define FIXTURE_H_EWLDRJT7 5 | 6 | #include "benchmark/benchmark.h" 7 | 8 | #include "target_code.h" 9 | #include "rpclib/struct_helpers.h" 10 | #include "port_numbers.h" 11 | 12 | #include "rpc/client.h" 13 | #include "rpc/server.h" 14 | 15 | class rpclib_bench : public benchmark::Fixture { 16 | public: 17 | void SetUp(benchmark::State&) override { 18 | // losing a bit of perf. on indirection, but gbenchmark creates all 19 | // fixtures on startup and destroys them only on exit which in the case of 20 | // rpclib will throw an exception due to reusing the port. Rather then 21 | // pulling tricks like randomizing port numbers, let's just accept that this 22 | // is something to be improved in rpclib. 23 | server = std::make_unique(rpclib_port); 24 | client = std::make_unique("localhost", rpclib_port); 25 | 26 | server->bind("get_answer", &::get_answer); 27 | server->bind("get_blob", [this]() { return ::get_blob(blob_size_); }); 28 | server->bind("get_structs", &rpclib_code::get_structs); 29 | server->async_run(1); 30 | } 31 | 32 | void TearDown(benchmark::State&) override { 33 | server->stop(); 34 | server.reset(); 35 | client.reset(); 36 | } 37 | 38 | void get_answer(int param) { 39 | (void)param; 40 | int a; 41 | benchmark::DoNotOptimize(a = client->call("get_answer", 23).as()); 42 | } 43 | 44 | void get_blob(int param) { 45 | blob_size_ = param; 46 | std::string s; 47 | benchmark::DoNotOptimize(s = client->call("get_blob").as()); 48 | std::size_t size; 49 | benchmark::DoNotOptimize(size = s.size()); 50 | } 51 | 52 | void get_structs(int param) { 53 | std::vector result; 54 | benchmark::DoNotOptimize( 55 | result = 56 | client->call("get_structs").as>()); 57 | std::size_t size; 58 | benchmark::DoNotOptimize(size = result.size()); 59 | } 60 | 61 | int blob_size_; 62 | std::unique_ptr server; 63 | std::unique_ptr client; 64 | }; 65 | 66 | #endif /* end of include guard: FIXTURE_H_EWLDRJT7 */ 67 | -------------------------------------------------------------------------------- /include/rpclib/struct_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef STRUCT_DEFINITIONS_H_NIWXDNSU 4 | #define STRUCT_DEFINITIONS_H_NIWXDNSU 5 | 6 | #include 7 | 8 | #include "target_code.h" 9 | 10 | namespace rpclib_code { 11 | 12 | struct Date { 13 | int year; 14 | char month; 15 | char day; 16 | static Date random() { 17 | return {rand() % 30 + 1900, static_cast(rand() % 12 + 1), 18 | static_cast(rand() % 30 + 1)}; 19 | } 20 | MSGPACK_DEFINE(year, month, day); 21 | }; 22 | 23 | struct Address { 24 | std::string city; 25 | int zipcode; 26 | std::string street; 27 | short number; 28 | static Address random() { 29 | return {rand_str(12), rand() % 3000 + 5000, rand_str(16), 30 | static_cast(rand() % 125 + 1)}; 31 | } 32 | MSGPACK_DEFINE(city, zipcode, street, number); 33 | }; 34 | 35 | struct School { 36 | std::string name; 37 | Address address; 38 | Date foundation; 39 | std::vector email_addresses; 40 | static School random() { 41 | School result{rand_str(36), Address::random(), Date::random(), {}}; 42 | for (size_t i = 0; i < item_count; ++i) { 43 | result.email_addresses.push_back(rand_str(37)); 44 | } 45 | return result; 46 | } 47 | MSGPACK_DEFINE(name, address, foundation, email_addresses); 48 | }; 49 | 50 | struct Subject { 51 | int id; 52 | std::string title; 53 | std::string code; 54 | static Subject random() { 55 | return {rand() % 28345, rand_str(22), rand_str(16)}; 56 | } 57 | MSGPACK_DEFINE(id, title, code); 58 | }; 59 | 60 | struct Student { 61 | std::string name; 62 | int friends; 63 | Address home_address; 64 | Address birth_place; 65 | Date birth; 66 | std::vector favorite_subjects; 67 | std::vector email_addresses; 68 | std::vector schools; 69 | static Student random() { 70 | Student result{rand_str(43), 71 | rand() % 600, 72 | Address::random(), 73 | Address::random(), 74 | Date::random(), 75 | {}, 76 | {}, 77 | {}}; 78 | for (size_t i = 0; i < item_count; ++i) { 79 | result.favorite_subjects.push_back(Subject::random()); 80 | result.email_addresses.push_back(rand_str(37)); 81 | result.schools.push_back(School::random()); 82 | } 83 | return result; 84 | } 85 | MSGPACK_DEFINE(name, friends, home_address, birth_place, birth, 86 | favorite_subjects, email_addresses, schools); 87 | }; 88 | 89 | std::vector& get_structs(); 90 | 91 | void fill_struct_cache(); 92 | 93 | } 94 | 95 | #endif /* end of include guard: STRUCT_DEFINITIONS_H_NIWXDNSU */ 96 | -------------------------------------------------------------------------------- /include/target_code.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef TARGET_CODE_H_MNJDLMEV 4 | #define TARGET_CODE_H_MNJDLMEV 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | 12 | 13 | int get_answer(int num); 14 | const std::string& get_blob(int size); 15 | 16 | std::string rand_str(std::size_t length); 17 | 18 | static constexpr std::size_t item_count = 34; 19 | 20 | 21 | #endif /* end of include guard: TARGET_CODE_H_MNJDLMEV */ 22 | -------------------------------------------------------------------------------- /include/thrift/ThriftServiceBenchmark.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.3) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #ifndef ThriftServiceBenchmark_H 8 | #define ThriftServiceBenchmark_H 9 | 10 | #include 11 | #include 12 | #include "thrift_service_types.h" 13 | 14 | namespace thrift_code { 15 | 16 | #ifdef _WIN32 17 | #pragma warning( push ) 18 | #pragma warning (disable : 4250 ) //inheriting methods via dominance 19 | #endif 20 | 21 | class ThriftServiceBenchmarkIf { 22 | public: 23 | virtual ~ThriftServiceBenchmarkIf() {} 24 | virtual int32_t get_answer(const int32_t number) = 0; 25 | virtual void get_blob(std::string& _return) = 0; 26 | virtual void get_structs(std::vector & _return) = 0; 27 | }; 28 | 29 | class ThriftServiceBenchmarkIfFactory { 30 | public: 31 | typedef ThriftServiceBenchmarkIf Handler; 32 | 33 | virtual ~ThriftServiceBenchmarkIfFactory() {} 34 | 35 | virtual ThriftServiceBenchmarkIf* getHandler(const ::apache::thrift::TConnectionInfo& connInfo) = 0; 36 | virtual void releaseHandler(ThriftServiceBenchmarkIf* /* handler */) = 0; 37 | }; 38 | 39 | class ThriftServiceBenchmarkIfSingletonFactory : virtual public ThriftServiceBenchmarkIfFactory { 40 | public: 41 | ThriftServiceBenchmarkIfSingletonFactory(const boost::shared_ptr& iface) : iface_(iface) {} 42 | virtual ~ThriftServiceBenchmarkIfSingletonFactory() {} 43 | 44 | virtual ThriftServiceBenchmarkIf* getHandler(const ::apache::thrift::TConnectionInfo&) { 45 | return iface_.get(); 46 | } 47 | virtual void releaseHandler(ThriftServiceBenchmarkIf* /* handler */) {} 48 | 49 | protected: 50 | boost::shared_ptr iface_; 51 | }; 52 | 53 | class ThriftServiceBenchmarkNull : virtual public ThriftServiceBenchmarkIf { 54 | public: 55 | virtual ~ThriftServiceBenchmarkNull() {} 56 | int32_t get_answer(const int32_t /* number */) { 57 | int32_t _return = 0; 58 | return _return; 59 | } 60 | void get_blob(std::string& /* _return */) { 61 | return; 62 | } 63 | void get_structs(std::vector & /* _return */) { 64 | return; 65 | } 66 | }; 67 | 68 | typedef struct _ThriftServiceBenchmark_get_answer_args__isset { 69 | _ThriftServiceBenchmark_get_answer_args__isset() : number(false) {} 70 | bool number :1; 71 | } _ThriftServiceBenchmark_get_answer_args__isset; 72 | 73 | class ThriftServiceBenchmark_get_answer_args { 74 | public: 75 | 76 | ThriftServiceBenchmark_get_answer_args(const ThriftServiceBenchmark_get_answer_args&); 77 | ThriftServiceBenchmark_get_answer_args& operator=(const ThriftServiceBenchmark_get_answer_args&); 78 | ThriftServiceBenchmark_get_answer_args() : number(0) { 79 | } 80 | 81 | virtual ~ThriftServiceBenchmark_get_answer_args() throw(); 82 | int32_t number; 83 | 84 | _ThriftServiceBenchmark_get_answer_args__isset __isset; 85 | 86 | void __set_number(const int32_t val); 87 | 88 | bool operator == (const ThriftServiceBenchmark_get_answer_args & rhs) const 89 | { 90 | if (!(number == rhs.number)) 91 | return false; 92 | return true; 93 | } 94 | bool operator != (const ThriftServiceBenchmark_get_answer_args &rhs) const { 95 | return !(*this == rhs); 96 | } 97 | 98 | bool operator < (const ThriftServiceBenchmark_get_answer_args & ) const; 99 | 100 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 101 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 102 | 103 | }; 104 | 105 | 106 | class ThriftServiceBenchmark_get_answer_pargs { 107 | public: 108 | 109 | 110 | virtual ~ThriftServiceBenchmark_get_answer_pargs() throw(); 111 | const int32_t* number; 112 | 113 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 114 | 115 | }; 116 | 117 | typedef struct _ThriftServiceBenchmark_get_answer_result__isset { 118 | _ThriftServiceBenchmark_get_answer_result__isset() : success(false) {} 119 | bool success :1; 120 | } _ThriftServiceBenchmark_get_answer_result__isset; 121 | 122 | class ThriftServiceBenchmark_get_answer_result { 123 | public: 124 | 125 | ThriftServiceBenchmark_get_answer_result(const ThriftServiceBenchmark_get_answer_result&); 126 | ThriftServiceBenchmark_get_answer_result& operator=(const ThriftServiceBenchmark_get_answer_result&); 127 | ThriftServiceBenchmark_get_answer_result() : success(0) { 128 | } 129 | 130 | virtual ~ThriftServiceBenchmark_get_answer_result() throw(); 131 | int32_t success; 132 | 133 | _ThriftServiceBenchmark_get_answer_result__isset __isset; 134 | 135 | void __set_success(const int32_t val); 136 | 137 | bool operator == (const ThriftServiceBenchmark_get_answer_result & rhs) const 138 | { 139 | if (!(success == rhs.success)) 140 | return false; 141 | return true; 142 | } 143 | bool operator != (const ThriftServiceBenchmark_get_answer_result &rhs) const { 144 | return !(*this == rhs); 145 | } 146 | 147 | bool operator < (const ThriftServiceBenchmark_get_answer_result & ) const; 148 | 149 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 150 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 151 | 152 | }; 153 | 154 | typedef struct _ThriftServiceBenchmark_get_answer_presult__isset { 155 | _ThriftServiceBenchmark_get_answer_presult__isset() : success(false) {} 156 | bool success :1; 157 | } _ThriftServiceBenchmark_get_answer_presult__isset; 158 | 159 | class ThriftServiceBenchmark_get_answer_presult { 160 | public: 161 | 162 | 163 | virtual ~ThriftServiceBenchmark_get_answer_presult() throw(); 164 | int32_t* success; 165 | 166 | _ThriftServiceBenchmark_get_answer_presult__isset __isset; 167 | 168 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 169 | 170 | }; 171 | 172 | 173 | class ThriftServiceBenchmark_get_blob_args { 174 | public: 175 | 176 | ThriftServiceBenchmark_get_blob_args(const ThriftServiceBenchmark_get_blob_args&); 177 | ThriftServiceBenchmark_get_blob_args& operator=(const ThriftServiceBenchmark_get_blob_args&); 178 | ThriftServiceBenchmark_get_blob_args() { 179 | } 180 | 181 | virtual ~ThriftServiceBenchmark_get_blob_args() throw(); 182 | 183 | bool operator == (const ThriftServiceBenchmark_get_blob_args & /* rhs */) const 184 | { 185 | return true; 186 | } 187 | bool operator != (const ThriftServiceBenchmark_get_blob_args &rhs) const { 188 | return !(*this == rhs); 189 | } 190 | 191 | bool operator < (const ThriftServiceBenchmark_get_blob_args & ) const; 192 | 193 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 194 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 195 | 196 | }; 197 | 198 | 199 | class ThriftServiceBenchmark_get_blob_pargs { 200 | public: 201 | 202 | 203 | virtual ~ThriftServiceBenchmark_get_blob_pargs() throw(); 204 | 205 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 206 | 207 | }; 208 | 209 | typedef struct _ThriftServiceBenchmark_get_blob_result__isset { 210 | _ThriftServiceBenchmark_get_blob_result__isset() : success(false) {} 211 | bool success :1; 212 | } _ThriftServiceBenchmark_get_blob_result__isset; 213 | 214 | class ThriftServiceBenchmark_get_blob_result { 215 | public: 216 | 217 | ThriftServiceBenchmark_get_blob_result(const ThriftServiceBenchmark_get_blob_result&); 218 | ThriftServiceBenchmark_get_blob_result& operator=(const ThriftServiceBenchmark_get_blob_result&); 219 | ThriftServiceBenchmark_get_blob_result() : success() { 220 | } 221 | 222 | virtual ~ThriftServiceBenchmark_get_blob_result() throw(); 223 | std::string success; 224 | 225 | _ThriftServiceBenchmark_get_blob_result__isset __isset; 226 | 227 | void __set_success(const std::string& val); 228 | 229 | bool operator == (const ThriftServiceBenchmark_get_blob_result & rhs) const 230 | { 231 | if (!(success == rhs.success)) 232 | return false; 233 | return true; 234 | } 235 | bool operator != (const ThriftServiceBenchmark_get_blob_result &rhs) const { 236 | return !(*this == rhs); 237 | } 238 | 239 | bool operator < (const ThriftServiceBenchmark_get_blob_result & ) const; 240 | 241 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 242 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 243 | 244 | }; 245 | 246 | typedef struct _ThriftServiceBenchmark_get_blob_presult__isset { 247 | _ThriftServiceBenchmark_get_blob_presult__isset() : success(false) {} 248 | bool success :1; 249 | } _ThriftServiceBenchmark_get_blob_presult__isset; 250 | 251 | class ThriftServiceBenchmark_get_blob_presult { 252 | public: 253 | 254 | 255 | virtual ~ThriftServiceBenchmark_get_blob_presult() throw(); 256 | std::string* success; 257 | 258 | _ThriftServiceBenchmark_get_blob_presult__isset __isset; 259 | 260 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 261 | 262 | }; 263 | 264 | 265 | class ThriftServiceBenchmark_get_structs_args { 266 | public: 267 | 268 | ThriftServiceBenchmark_get_structs_args(const ThriftServiceBenchmark_get_structs_args&); 269 | ThriftServiceBenchmark_get_structs_args& operator=(const ThriftServiceBenchmark_get_structs_args&); 270 | ThriftServiceBenchmark_get_structs_args() { 271 | } 272 | 273 | virtual ~ThriftServiceBenchmark_get_structs_args() throw(); 274 | 275 | bool operator == (const ThriftServiceBenchmark_get_structs_args & /* rhs */) const 276 | { 277 | return true; 278 | } 279 | bool operator != (const ThriftServiceBenchmark_get_structs_args &rhs) const { 280 | return !(*this == rhs); 281 | } 282 | 283 | bool operator < (const ThriftServiceBenchmark_get_structs_args & ) const; 284 | 285 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 286 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 287 | 288 | }; 289 | 290 | 291 | class ThriftServiceBenchmark_get_structs_pargs { 292 | public: 293 | 294 | 295 | virtual ~ThriftServiceBenchmark_get_structs_pargs() throw(); 296 | 297 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 298 | 299 | }; 300 | 301 | typedef struct _ThriftServiceBenchmark_get_structs_result__isset { 302 | _ThriftServiceBenchmark_get_structs_result__isset() : success(false) {} 303 | bool success :1; 304 | } _ThriftServiceBenchmark_get_structs_result__isset; 305 | 306 | class ThriftServiceBenchmark_get_structs_result { 307 | public: 308 | 309 | ThriftServiceBenchmark_get_structs_result(const ThriftServiceBenchmark_get_structs_result&); 310 | ThriftServiceBenchmark_get_structs_result& operator=(const ThriftServiceBenchmark_get_structs_result&); 311 | ThriftServiceBenchmark_get_structs_result() { 312 | } 313 | 314 | virtual ~ThriftServiceBenchmark_get_structs_result() throw(); 315 | std::vector success; 316 | 317 | _ThriftServiceBenchmark_get_structs_result__isset __isset; 318 | 319 | void __set_success(const std::vector & val); 320 | 321 | bool operator == (const ThriftServiceBenchmark_get_structs_result & rhs) const 322 | { 323 | if (!(success == rhs.success)) 324 | return false; 325 | return true; 326 | } 327 | bool operator != (const ThriftServiceBenchmark_get_structs_result &rhs) const { 328 | return !(*this == rhs); 329 | } 330 | 331 | bool operator < (const ThriftServiceBenchmark_get_structs_result & ) const; 332 | 333 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 334 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 335 | 336 | }; 337 | 338 | typedef struct _ThriftServiceBenchmark_get_structs_presult__isset { 339 | _ThriftServiceBenchmark_get_structs_presult__isset() : success(false) {} 340 | bool success :1; 341 | } _ThriftServiceBenchmark_get_structs_presult__isset; 342 | 343 | class ThriftServiceBenchmark_get_structs_presult { 344 | public: 345 | 346 | 347 | virtual ~ThriftServiceBenchmark_get_structs_presult() throw(); 348 | std::vector * success; 349 | 350 | _ThriftServiceBenchmark_get_structs_presult__isset __isset; 351 | 352 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 353 | 354 | }; 355 | 356 | class ThriftServiceBenchmarkClient : virtual public ThriftServiceBenchmarkIf { 357 | public: 358 | ThriftServiceBenchmarkClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) { 359 | setProtocol(prot); 360 | } 361 | ThriftServiceBenchmarkClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) { 362 | setProtocol(iprot,oprot); 363 | } 364 | private: 365 | void setProtocol(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) { 366 | setProtocol(prot,prot); 367 | } 368 | void setProtocol(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) { 369 | piprot_=iprot; 370 | poprot_=oprot; 371 | iprot_ = iprot.get(); 372 | oprot_ = oprot.get(); 373 | } 374 | public: 375 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() { 376 | return piprot_; 377 | } 378 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() { 379 | return poprot_; 380 | } 381 | int32_t get_answer(const int32_t number); 382 | void send_get_answer(const int32_t number); 383 | int32_t recv_get_answer(); 384 | void get_blob(std::string& _return); 385 | void send_get_blob(); 386 | void recv_get_blob(std::string& _return); 387 | void get_structs(std::vector & _return); 388 | void send_get_structs(); 389 | void recv_get_structs(std::vector & _return); 390 | protected: 391 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_; 392 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_; 393 | ::apache::thrift::protocol::TProtocol* iprot_; 394 | ::apache::thrift::protocol::TProtocol* oprot_; 395 | }; 396 | 397 | class ThriftServiceBenchmarkProcessor : public ::apache::thrift::TDispatchProcessor { 398 | protected: 399 | boost::shared_ptr iface_; 400 | virtual bool dispatchCall(::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, void* callContext); 401 | private: 402 | typedef void (ThriftServiceBenchmarkProcessor::*ProcessFunction)(int32_t, ::apache::thrift::protocol::TProtocol*, ::apache::thrift::protocol::TProtocol*, void*); 403 | typedef std::map ProcessMap; 404 | ProcessMap processMap_; 405 | void process_get_answer(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); 406 | void process_get_blob(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); 407 | void process_get_structs(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext); 408 | public: 409 | ThriftServiceBenchmarkProcessor(boost::shared_ptr iface) : 410 | iface_(iface) { 411 | processMap_["get_answer"] = &ThriftServiceBenchmarkProcessor::process_get_answer; 412 | processMap_["get_blob"] = &ThriftServiceBenchmarkProcessor::process_get_blob; 413 | processMap_["get_structs"] = &ThriftServiceBenchmarkProcessor::process_get_structs; 414 | } 415 | 416 | virtual ~ThriftServiceBenchmarkProcessor() {} 417 | }; 418 | 419 | class ThriftServiceBenchmarkProcessorFactory : public ::apache::thrift::TProcessorFactory { 420 | public: 421 | ThriftServiceBenchmarkProcessorFactory(const ::boost::shared_ptr< ThriftServiceBenchmarkIfFactory >& handlerFactory) : 422 | handlerFactory_(handlerFactory) {} 423 | 424 | ::boost::shared_ptr< ::apache::thrift::TProcessor > getProcessor(const ::apache::thrift::TConnectionInfo& connInfo); 425 | 426 | protected: 427 | ::boost::shared_ptr< ThriftServiceBenchmarkIfFactory > handlerFactory_; 428 | }; 429 | 430 | class ThriftServiceBenchmarkMultiface : virtual public ThriftServiceBenchmarkIf { 431 | public: 432 | ThriftServiceBenchmarkMultiface(std::vector >& ifaces) : ifaces_(ifaces) { 433 | } 434 | virtual ~ThriftServiceBenchmarkMultiface() {} 435 | protected: 436 | std::vector > ifaces_; 437 | ThriftServiceBenchmarkMultiface() {} 438 | void add(boost::shared_ptr iface) { 439 | ifaces_.push_back(iface); 440 | } 441 | public: 442 | int32_t get_answer(const int32_t number) { 443 | size_t sz = ifaces_.size(); 444 | size_t i = 0; 445 | for (; i < (sz - 1); ++i) { 446 | ifaces_[i]->get_answer(number); 447 | } 448 | return ifaces_[i]->get_answer(number); 449 | } 450 | 451 | void get_blob(std::string& _return) { 452 | size_t sz = ifaces_.size(); 453 | size_t i = 0; 454 | for (; i < (sz - 1); ++i) { 455 | ifaces_[i]->get_blob(_return); 456 | } 457 | ifaces_[i]->get_blob(_return); 458 | return; 459 | } 460 | 461 | void get_structs(std::vector & _return) { 462 | size_t sz = ifaces_.size(); 463 | size_t i = 0; 464 | for (; i < (sz - 1); ++i) { 465 | ifaces_[i]->get_structs(_return); 466 | } 467 | ifaces_[i]->get_structs(_return); 468 | return; 469 | } 470 | 471 | }; 472 | 473 | // The 'concurrent' client is a thread safe client that correctly handles 474 | // out of order responses. It is slower than the regular client, so should 475 | // only be used when you need to share a connection among multiple threads 476 | class ThriftServiceBenchmarkConcurrentClient : virtual public ThriftServiceBenchmarkIf { 477 | public: 478 | ThriftServiceBenchmarkConcurrentClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) { 479 | setProtocol(prot); 480 | } 481 | ThriftServiceBenchmarkConcurrentClient(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) { 482 | setProtocol(iprot,oprot); 483 | } 484 | private: 485 | void setProtocol(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> prot) { 486 | setProtocol(prot,prot); 487 | } 488 | void setProtocol(boost::shared_ptr< ::apache::thrift::protocol::TProtocol> iprot, boost::shared_ptr< ::apache::thrift::protocol::TProtocol> oprot) { 489 | piprot_=iprot; 490 | poprot_=oprot; 491 | iprot_ = iprot.get(); 492 | oprot_ = oprot.get(); 493 | } 494 | public: 495 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getInputProtocol() { 496 | return piprot_; 497 | } 498 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> getOutputProtocol() { 499 | return poprot_; 500 | } 501 | int32_t get_answer(const int32_t number); 502 | int32_t send_get_answer(const int32_t number); 503 | int32_t recv_get_answer(const int32_t seqid); 504 | void get_blob(std::string& _return); 505 | int32_t send_get_blob(); 506 | void recv_get_blob(std::string& _return, const int32_t seqid); 507 | void get_structs(std::vector & _return); 508 | int32_t send_get_structs(); 509 | void recv_get_structs(std::vector & _return, const int32_t seqid); 510 | protected: 511 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> piprot_; 512 | boost::shared_ptr< ::apache::thrift::protocol::TProtocol> poprot_; 513 | ::apache::thrift::protocol::TProtocol* iprot_; 514 | ::apache::thrift::protocol::TProtocol* oprot_; 515 | ::apache::thrift::async::TConcurrentClientSyncInfo sync_; 516 | }; 517 | 518 | #ifdef _WIN32 519 | #pragma warning( pop ) 520 | #endif 521 | 522 | } // namespace 523 | 524 | #endif 525 | -------------------------------------------------------------------------------- /include/thrift/fixture.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #ifndef FIXTURE_H_ALZERDCI 4 | #define FIXTURE_H_ALZERDCI 5 | 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "benchmark/benchmark.h" 12 | 13 | #include "ThriftServiceBenchmark.h" 14 | #include "thrift/protocol/TBinaryProtocol.h" 15 | #include "thrift/server/TSimpleServer.h" 16 | #include "thrift/transport/TBufferTransports.h" 17 | #include "thrift/transport/TServerSocket.h" 18 | #include "thrift/transport/TSocket.h" 19 | #include "thrift/transport/TTransportUtils.h" 20 | 21 | #include "target_code.h" 22 | #include "thrift/struct_helpers.h" 23 | #include "port_numbers.h" 24 | 25 | class thrift_server : virtual public thrift_code::ThriftServiceBenchmarkIf { 26 | public: 27 | int32_t get_answer(const int32_t number) override { 28 | return ::get_answer(number); 29 | } 30 | 31 | void get_blob(std::string &_return) override { 32 | _return = ::get_blob(blob_size); 33 | } 34 | 35 | void get_structs(std::vector &_return) override { 36 | _return = thrift_code::get_structs(); 37 | } 38 | 39 | int blob_size; 40 | }; 41 | 42 | class thrift_bench : public benchmark::Fixture { 43 | public: 44 | void SetUp(benchmark::State &) override { 45 | using boost::make_shared; 46 | using std::make_unique; 47 | handler = make_shared(); 48 | processor = 49 | make_shared(handler); 50 | serverTransport = 51 | make_shared(thrift_port); 52 | transportFactory = 53 | make_shared(); 54 | protocolFactory = 55 | make_shared(); 56 | clientSocket = make_shared("127.0.0.1", 57 | thrift_port); 58 | clientTransport = 59 | make_shared( 60 | clientSocket); 61 | clientProtocol = 62 | make_shared(clientTransport); 63 | client = 64 | make_unique(clientProtocol); 65 | server = make_unique( 66 | processor, serverTransport, transportFactory, protocolFactory); 67 | std::thread serve_thread([this]() { 68 | server_running = true; 69 | server->serve(); 70 | server_running = false; 71 | }); 72 | std::this_thread::sleep_for(std::chrono::milliseconds(50)); 73 | clientTransport->open(); 74 | serve_thread.detach(); 75 | } 76 | 77 | void TearDown(benchmark::State&) override { 78 | clientTransport->close(); 79 | server->stop(); 80 | while (server_running) 81 | ; 82 | } 83 | 84 | void get_answer(int param) { 85 | (void)param; 86 | int a; 87 | benchmark::DoNotOptimize(a = client->get_answer(23)); 88 | } 89 | 90 | void get_blob(int param) { 91 | handler->blob_size = param; 92 | std::string s; 93 | client->get_blob(s); 94 | } 95 | 96 | void get_structs(int param) { 97 | (void)param; 98 | std::vector students; 99 | client->get_structs(students); 100 | std::size_t count; 101 | benchmark::DoNotOptimize(count = students.size()); 102 | } 103 | 104 | boost::shared_ptr handler; 105 | boost::shared_ptr processor; 106 | boost::shared_ptr serverTransport; 107 | boost::shared_ptr transportFactory; 108 | boost::shared_ptr protocolFactory; 109 | boost::shared_ptr clientSocket; 110 | boost::shared_ptr clientTransport; 111 | boost::shared_ptr clientProtocol; 112 | std::unique_ptr client; 113 | std::unique_ptr server; 114 | std::atomic_bool server_running; 115 | }; 116 | 117 | #endif /* end of include guard: FIXTURE_H_ALZERDCI */ 118 | -------------------------------------------------------------------------------- /include/thrift/struct_helpers.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "thrift/thrift_service_types.h" 5 | 6 | #ifndef STRUCT_HELPERS_H_QOFGY4Y7 7 | #define STRUCT_HELPERS_H_QOFGY4Y7 8 | 9 | namespace thrift_code { 10 | 11 | std::vector& get_structs(); 12 | void fill_struct_cache(); 13 | 14 | } 15 | 16 | 17 | #endif /* end of include guard: STRUCT_HELPERS_H_QOFGY4Y7 */ 18 | -------------------------------------------------------------------------------- /include/thrift/thrift_service_constants.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.3) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #ifndef thrift_service_CONSTANTS_H 8 | #define thrift_service_CONSTANTS_H 9 | 10 | #include "thrift_service_types.h" 11 | 12 | namespace thrift_code { 13 | 14 | class thrift_serviceConstants { 15 | public: 16 | thrift_serviceConstants(); 17 | 18 | }; 19 | 20 | extern const thrift_serviceConstants g_thrift_service_constants; 21 | 22 | } // namespace 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /include/thrift/thrift_service_types.h: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.3) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #ifndef thrift_service_TYPES_H 8 | #define thrift_service_TYPES_H 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include 18 | 19 | 20 | namespace thrift_code { 21 | 22 | class Date; 23 | 24 | class Address; 25 | 26 | class School; 27 | 28 | class Subject; 29 | 30 | class Student; 31 | 32 | typedef struct _Date__isset { 33 | _Date__isset() : year(false), month(false), day(false) {} 34 | bool year :1; 35 | bool month :1; 36 | bool day :1; 37 | } _Date__isset; 38 | 39 | class Date { 40 | public: 41 | 42 | Date(const Date&); 43 | Date& operator=(const Date&); 44 | Date() : year(0), month(0), day(0) { 45 | } 46 | 47 | virtual ~Date() throw(); 48 | int32_t year; 49 | int8_t month; 50 | int8_t day; 51 | 52 | _Date__isset __isset; 53 | 54 | void __set_year(const int32_t val); 55 | 56 | void __set_month(const int8_t val); 57 | 58 | void __set_day(const int8_t val); 59 | 60 | bool operator == (const Date & rhs) const 61 | { 62 | if (!(year == rhs.year)) 63 | return false; 64 | if (!(month == rhs.month)) 65 | return false; 66 | if (!(day == rhs.day)) 67 | return false; 68 | return true; 69 | } 70 | bool operator != (const Date &rhs) const { 71 | return !(*this == rhs); 72 | } 73 | 74 | bool operator < (const Date & ) const; 75 | 76 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 77 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 78 | 79 | virtual void printTo(std::ostream& out) const; 80 | }; 81 | 82 | void swap(Date &a, Date &b); 83 | 84 | inline std::ostream& operator<<(std::ostream& out, const Date& obj) 85 | { 86 | obj.printTo(out); 87 | return out; 88 | } 89 | 90 | typedef struct _Address__isset { 91 | _Address__isset() : city(false), zipcode(false), street(false), number(false) {} 92 | bool city :1; 93 | bool zipcode :1; 94 | bool street :1; 95 | bool number :1; 96 | } _Address__isset; 97 | 98 | class Address { 99 | public: 100 | 101 | Address(const Address&); 102 | Address& operator=(const Address&); 103 | Address() : city(), zipcode(0), street(), number(0) { 104 | } 105 | 106 | virtual ~Address() throw(); 107 | std::string city; 108 | int32_t zipcode; 109 | std::string street; 110 | int16_t number; 111 | 112 | _Address__isset __isset; 113 | 114 | void __set_city(const std::string& val); 115 | 116 | void __set_zipcode(const int32_t val); 117 | 118 | void __set_street(const std::string& val); 119 | 120 | void __set_number(const int16_t val); 121 | 122 | bool operator == (const Address & rhs) const 123 | { 124 | if (!(city == rhs.city)) 125 | return false; 126 | if (!(zipcode == rhs.zipcode)) 127 | return false; 128 | if (!(street == rhs.street)) 129 | return false; 130 | if (!(number == rhs.number)) 131 | return false; 132 | return true; 133 | } 134 | bool operator != (const Address &rhs) const { 135 | return !(*this == rhs); 136 | } 137 | 138 | bool operator < (const Address & ) const; 139 | 140 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 141 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 142 | 143 | virtual void printTo(std::ostream& out) const; 144 | }; 145 | 146 | void swap(Address &a, Address &b); 147 | 148 | inline std::ostream& operator<<(std::ostream& out, const Address& obj) 149 | { 150 | obj.printTo(out); 151 | return out; 152 | } 153 | 154 | typedef struct _School__isset { 155 | _School__isset() : name(false), address(false), foundation(false), email_addresses(false) {} 156 | bool name :1; 157 | bool address :1; 158 | bool foundation :1; 159 | bool email_addresses :1; 160 | } _School__isset; 161 | 162 | class School { 163 | public: 164 | 165 | School(const School&); 166 | School& operator=(const School&); 167 | School() : name() { 168 | } 169 | 170 | virtual ~School() throw(); 171 | std::string name; 172 | Address address; 173 | Date foundation; 174 | std::vector email_addresses; 175 | 176 | _School__isset __isset; 177 | 178 | void __set_name(const std::string& val); 179 | 180 | void __set_address(const Address& val); 181 | 182 | void __set_foundation(const Date& val); 183 | 184 | void __set_email_addresses(const std::vector & val); 185 | 186 | bool operator == (const School & rhs) const 187 | { 188 | if (!(name == rhs.name)) 189 | return false; 190 | if (!(address == rhs.address)) 191 | return false; 192 | if (!(foundation == rhs.foundation)) 193 | return false; 194 | if (!(email_addresses == rhs.email_addresses)) 195 | return false; 196 | return true; 197 | } 198 | bool operator != (const School &rhs) const { 199 | return !(*this == rhs); 200 | } 201 | 202 | bool operator < (const School & ) const; 203 | 204 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 205 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 206 | 207 | virtual void printTo(std::ostream& out) const; 208 | }; 209 | 210 | void swap(School &a, School &b); 211 | 212 | inline std::ostream& operator<<(std::ostream& out, const School& obj) 213 | { 214 | obj.printTo(out); 215 | return out; 216 | } 217 | 218 | typedef struct _Subject__isset { 219 | _Subject__isset() : id(false), title(false), code(false) {} 220 | bool id :1; 221 | bool title :1; 222 | bool code :1; 223 | } _Subject__isset; 224 | 225 | class Subject { 226 | public: 227 | 228 | Subject(const Subject&); 229 | Subject& operator=(const Subject&); 230 | Subject() : id(0), title(), code() { 231 | } 232 | 233 | virtual ~Subject() throw(); 234 | int32_t id; 235 | std::string title; 236 | std::string code; 237 | 238 | _Subject__isset __isset; 239 | 240 | void __set_id(const int32_t val); 241 | 242 | void __set_title(const std::string& val); 243 | 244 | void __set_code(const std::string& val); 245 | 246 | bool operator == (const Subject & rhs) const 247 | { 248 | if (!(id == rhs.id)) 249 | return false; 250 | if (!(title == rhs.title)) 251 | return false; 252 | if (!(code == rhs.code)) 253 | return false; 254 | return true; 255 | } 256 | bool operator != (const Subject &rhs) const { 257 | return !(*this == rhs); 258 | } 259 | 260 | bool operator < (const Subject & ) const; 261 | 262 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 263 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 264 | 265 | virtual void printTo(std::ostream& out) const; 266 | }; 267 | 268 | void swap(Subject &a, Subject &b); 269 | 270 | inline std::ostream& operator<<(std::ostream& out, const Subject& obj) 271 | { 272 | obj.printTo(out); 273 | return out; 274 | } 275 | 276 | typedef struct _Student__isset { 277 | _Student__isset() : name(false), friends(false), home_address(false), birth_place(false), birth(false), favorite_subjects(false), email_addresses(false), schools(false) {} 278 | bool name :1; 279 | bool friends :1; 280 | bool home_address :1; 281 | bool birth_place :1; 282 | bool birth :1; 283 | bool favorite_subjects :1; 284 | bool email_addresses :1; 285 | bool schools :1; 286 | } _Student__isset; 287 | 288 | class Student { 289 | public: 290 | 291 | Student(const Student&); 292 | Student& operator=(const Student&); 293 | Student() : name(), friends(0) { 294 | } 295 | 296 | virtual ~Student() throw(); 297 | std::string name; 298 | int32_t friends; 299 | Address home_address; 300 | Address birth_place; 301 | Date birth; 302 | std::vector favorite_subjects; 303 | std::vector email_addresses; 304 | std::vector schools; 305 | 306 | _Student__isset __isset; 307 | 308 | void __set_name(const std::string& val); 309 | 310 | void __set_friends(const int32_t val); 311 | 312 | void __set_home_address(const Address& val); 313 | 314 | void __set_birth_place(const Address& val); 315 | 316 | void __set_birth(const Date& val); 317 | 318 | void __set_favorite_subjects(const std::vector & val); 319 | 320 | void __set_email_addresses(const std::vector & val); 321 | 322 | void __set_schools(const std::vector & val); 323 | 324 | bool operator == (const Student & rhs) const 325 | { 326 | if (!(name == rhs.name)) 327 | return false; 328 | if (!(friends == rhs.friends)) 329 | return false; 330 | if (!(home_address == rhs.home_address)) 331 | return false; 332 | if (!(birth_place == rhs.birth_place)) 333 | return false; 334 | if (!(birth == rhs.birth)) 335 | return false; 336 | if (!(favorite_subjects == rhs.favorite_subjects)) 337 | return false; 338 | if (!(email_addresses == rhs.email_addresses)) 339 | return false; 340 | if (!(schools == rhs.schools)) 341 | return false; 342 | return true; 343 | } 344 | bool operator != (const Student &rhs) const { 345 | return !(*this == rhs); 346 | } 347 | 348 | bool operator < (const Student & ) const; 349 | 350 | uint32_t read(::apache::thrift::protocol::TProtocol* iprot); 351 | uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const; 352 | 353 | virtual void printTo(std::ostream& out) const; 354 | }; 355 | 356 | void swap(Student &a, Student &b); 357 | 358 | inline std::ostream& operator<<(std::ostream& out, const Student& obj) 359 | { 360 | obj.printTo(out); 361 | return out; 362 | } 363 | 364 | } // namespace 365 | 366 | #endif 367 | -------------------------------------------------------------------------------- /plots/get_structs_cpu_linear.svg: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 10 | 11 | 12 | 13 | 19 | 20 | 21 | 22 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 56 | 96 | 122 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 182 | 193 | 208 | 231 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 275 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 334 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 423 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 461 | 462 | 463 | 464 | 465 | 466 | 489 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 508 | 509 | 510 | 511 | 512 | 513 | 537 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 590 | 591 | 592 | 593 | 594 | 595 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 621 | 622 | 623 | 624 | 625 | 626 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 723 | 743 | 744 | 774 | 786 | 821 | 833 | 834 | 835 | 836 | 837 | 838 | 839 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | 852 | 853 | 854 | 855 | 856 | 857 | 858 | 864 | 865 | 866 | 872 | 873 | 874 | 880 | 881 | 882 | 888 | 889 | 890 | 896 | 897 | 898 | 900 | 901 | 902 | 904 | 905 | 906 | 908 | 909 | 910 | 912 | 913 | 914 | 916 | 917 | 918 | 921 | 922 | 923 | 926 | 927 | 928 | 931 | 932 | 933 | 936 | 937 | 938 | 939 | 940 | 977 | 1009 | 1026 | 1059 | 1060 | 1061 | 1062 | 1063 | 1064 | 1065 | 1066 | 1067 | 1068 | 1069 | 1070 | 1071 | 1072 | 1073 | 1074 | 1075 | 1076 | 1077 | 1078 | 1079 | 1080 | 1081 | 1082 | 1083 | 1084 | 1085 | 1086 | 1087 | 1088 | 1089 | 1090 | 1091 | 1092 | 1093 | 1094 | 1095 | 1096 | 1097 | 1098 | 1099 | 1100 | 1101 | 1102 | 1103 | 1104 | 1105 | 1106 | 1107 | 1108 | 1109 | 1110 | 1111 | 1112 | 1113 | 1114 | 1115 | 1116 | 1117 | 1118 | 1119 | 1120 | 1121 | 1122 | 1123 | 1124 | 1125 | 1126 | 1127 | 1133 | 1154 | 1165 | 1166 | 1167 | 1168 | 1169 | 1170 | 1171 | 1172 | 1173 | 1174 | 1175 | 1176 | 1177 | 1178 | 1179 | 1180 | 1181 | 1182 | 1183 | 1184 | 1185 | 1186 | 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 1193 | 1194 | 1195 | 1196 | 1197 | 1198 | 1199 | 1200 | 1201 | 1202 | 1203 | 1204 | 1205 | 1206 | 1207 | 1208 | 1209 | 1210 | 1211 | 1212 | 1213 | 1214 | 1215 | 1216 | 1217 | 1218 | 1219 | 1220 | 1221 | 1222 | 1223 | 1224 | 1225 | 1226 | 1227 | 1228 | 1229 | 1230 | 1231 | 1232 | 1233 | 1234 | 1235 | 1236 | 1237 | 1238 | 1239 | 1240 | 1241 | 1242 | 1243 | 1244 | 1245 | 1246 | 1247 | 1248 | 1249 | 1250 | 1251 | -------------------------------------------------------------------------------- /run_benchmarks.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # This script assumes that the executable is stored in ./build/bin/rpclib_benchmark, 4 | # relative to the script itself. 5 | 6 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 7 | 8 | $SCRIPT_DIR/build/bin/rpclib_benchmark --benchmark_min_time=3.0 --benchmark_repetitions=5 --benchmark_out=benchmark.json --benchmark_out_format=json 9 | -------------------------------------------------------------------------------- /scripts/run_codegens.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | set -e 4 | 5 | SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" 6 | BENCHMARKS_ROOT="$SCRIPT_DIR/.." 7 | 8 | pushd $SCRIPT_DIR 9 | 10 | # 1. grpc 11 | echo "> Generating grpc code" 12 | protoc --grpc_out=. -I$BENCHMARKS_ROOT/idl --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` $BENCHMARKS_ROOT/idl/grpc_service.proto 13 | protoc --cpp_out=. -I$BENCHMARKS_ROOT/idl --plugin=protoc-gen-grpc=`which grpc_cpp_plugin` $BENCHMARKS_ROOT/idl/grpc_service.proto 14 | mv $SCRIPT_DIR/*.h $BENCHMARKS_ROOT/include/grpc 15 | mv $SCRIPT_DIR/*.cc $BENCHMARKS_ROOT/src/grpc 16 | 17 | # 2. thrift 18 | echo "> Generating thrift code" 19 | thrift -r --gen cpp $BENCHMARKS_ROOT/idl/thrift_service.thrift 20 | mv $SCRIPT_DIR/gen-cpp/*.h $BENCHMARKS_ROOT/include/thrift 21 | mv $SCRIPT_DIR/gen-cpp/*.cpp $BENCHMARKS_ROOT/src/thrift 22 | rm -r $SCRIPT_DIR/gen-cpp 23 | 24 | # 3. cap'n'proto 25 | echo "> Generating cap'n'proto code" 26 | pushd $BENCHMARKS_ROOT/idl 27 | capnpc -oc++ capnp_service.capnp 28 | mv ./*.h $BENCHMARKS_ROOT/include/capnp 29 | mv ./*.c++ $BENCHMARKS_ROOT/src/capnp 30 | popd 31 | 32 | popd 33 | -------------------------------------------------------------------------------- /src/benchmark.cc: -------------------------------------------------------------------------------- 1 | #include "benchmark/benchmark.h" 2 | 3 | #include "target_code.h" 4 | 5 | #include "capnp/fixture.h" 6 | #include "direct/fixture.h" 7 | #include "grpc/fixture.h" 8 | #include "rpclib/fixture.h" 9 | #include "thrift/fixture.h" 10 | 11 | #include "grpc/struct_helpers.h" 12 | #include "rpclib/struct_helpers.h" 13 | #include "thrift/struct_helpers.h" 14 | #include "capnp/struct_helpers.h" 15 | 16 | #include 17 | 18 | int capnp_bench::blob_size_ = 0; 19 | 20 | #define MAKE_BENCHMARK(FixtureName, Benchmark) \ 21 | BENCHMARK_DEFINE_F(FixtureName, Benchmark)(benchmark::State & st) { \ 22 | auto num = st.range(0); \ 23 | while (st.KeepRunning()) { \ 24 | Benchmark(num); \ 25 | } \ 26 | } \ 27 | BENCHMARK_REGISTER_F(FixtureName, Benchmark) 28 | 29 | #define MAKE_BENCHMARK0(FixtureName, Benchmark) \ 30 | BENCHMARK_DEFINE_F(FixtureName, Benchmark)(benchmark::State & st) { \ 31 | while (st.KeepRunning()) { \ 32 | Benchmark(0); \ 33 | } \ 34 | } \ 35 | BENCHMARK_REGISTER_F(FixtureName, Benchmark) 36 | 37 | constexpr std::size_t min_size = 1 << 10; 38 | constexpr std::size_t max_size = 16 << 10 << 10; 39 | // constexpr std::size_t grpc_max_size = 1 << 10 << 10; // https://github.com/grpc/grpc/issues/9510 40 | constexpr std::size_t multiplier = 2; 41 | 42 | MAKE_BENCHMARK(direct_bench, get_blob)->RangeMultiplier(multiplier)->Range(min_size, max_size); 43 | MAKE_BENCHMARK(rpclib_bench, get_blob)->RangeMultiplier(multiplier)->Range(min_size, max_size); 44 | MAKE_BENCHMARK(capnp_bench, get_blob)->RangeMultiplier(multiplier)->Range(min_size, max_size); 45 | MAKE_BENCHMARK(thrift_bench, get_blob)->RangeMultiplier(multiplier)->Range(min_size, max_size); 46 | // MAKE_BENCHMARK(grpc_bench, get_blob)->RangeMultiplier(multiplier)->Range(min_size, grpc_max_size); 47 | 48 | MAKE_BENCHMARK0(direct_bench, get_structs); 49 | MAKE_BENCHMARK0(rpclib_bench, get_structs); 50 | MAKE_BENCHMARK0(thrift_bench, get_structs); 51 | MAKE_BENCHMARK0(grpc_bench, get_structs); 52 | MAKE_BENCHMARK0(capnp_bench, get_structs); 53 | 54 | MAKE_BENCHMARK0(direct_bench, get_answer); 55 | MAKE_BENCHMARK0(rpclib_bench, get_answer); 56 | MAKE_BENCHMARK0(capnp_bench, get_answer); 57 | MAKE_BENCHMARK0(thrift_bench, get_answer); 58 | MAKE_BENCHMARK0(grpc_bench, get_answer); 59 | 60 | int main(int argc, char *argv[]) { 61 | printf("Initalizing blob cache...\n"); 62 | for (std::size_t s = min_size; s <= max_size; s *= multiplier) { 63 | get_blob(s); 64 | } 65 | 66 | printf("Initalizing struct cache...\n"); 67 | rpclib_code::fill_struct_cache(); 68 | thrift_code::fill_struct_cache(); 69 | grpc_code::fill_struct_cache(); 70 | capnp_code::fill_struct_cache(); 71 | 72 | printf("Starting benchmarks...\n"); 73 | benchmark::Initialize(&argc, argv); 74 | return benchmark::RunSpecifiedBenchmarks(); 75 | } 76 | 77 | -------------------------------------------------------------------------------- /src/capnp/struct_helpers.cc: -------------------------------------------------------------------------------- 1 | #include "capnp/struct_helpers.h" 2 | #include "target_code.h" 3 | #include 4 | #include 5 | 6 | namespace capnp_code { 7 | 8 | capnp::MallocMessageBuilder msg; 9 | StudentDataResponse::Builder struct_cache = msg.initRoot(); 10 | 11 | void fill_struct_cache() { 12 | auto random_Date = []() { 13 | Date::Builder date = msg.initRoot(); 14 | date.setYear(rand() % 30 + 1900); 15 | date.setMonth(static_cast(rand() % 12 + 1)); 16 | date.setDay(static_cast(rand() % 30 + 1)); 17 | return date; 18 | }; 19 | 20 | auto random_Address = 21 | [&]() { 22 | Address::Builder addr = msg.initRoot
(); 23 | addr.setCity(rand_str(12)); 24 | addr.setZipcode(rand() % 3000 + 5000); 25 | addr.setStreet(rand_str(16)); 26 | addr.setNumber(static_cast(rand() % 125 + 1)); 27 | return addr; 28 | }; 29 | 30 | auto random_School = 31 | [&]() { 32 | School::Builder result = msg.initRoot(); 33 | result.setName(rand_str(36)); 34 | result.setAddress(random_Address()); 35 | result.setFoundation(random_Date()); 36 | result.initEmailAddresses(item_count); 37 | for (size_t i = 0; i < item_count; ++i) { 38 | result.getEmailAddresses().set(i, rand_str(37)); 39 | } 40 | return result; 41 | }; 42 | 43 | auto random_Subject = []() { 44 | Subject::Builder s = msg.initRoot(); 45 | s.setId(rand() % 28345); 46 | s.setTitle(rand_str(22)); 47 | s.setCode(rand_str(16)); 48 | return s; 49 | }; 50 | 51 | auto random_Student = [&]() { 52 | Student::Builder s = msg.initRoot(); 53 | s.setName(rand_str(43)); 54 | s.setFriends(rand() % 600); 55 | s.setHomeAddress(random_Address()); 56 | s.setBirthPlace(random_Address()); 57 | s.setBirth(random_Date()); 58 | 59 | s.initSchools(item_count); 60 | s.initFavoriteSubjects(item_count); 61 | s.initEmailAddresses(item_count); 62 | for (size_t i = 0; i < item_count; ++i) { 63 | s.getFavoriteSubjects().setWithCaveats(i, random_Subject()); 64 | s.getEmailAddresses().set(i, rand_str(37)); 65 | } 66 | return s; 67 | }; 68 | 69 | auto builder = struct_cache.initStudents(item_count); 70 | for (std::size_t i = 0; i < item_count; ++i) { 71 | builder.setWithCaveats(i, random_Student()); 72 | } 73 | struct_cache.setStudents(builder); 74 | } 75 | 76 | StudentDataResponse::Builder& get_structs() { return struct_cache; } 77 | 78 | } 79 | -------------------------------------------------------------------------------- /src/grpc/grpc_service.grpc.pb.cc: -------------------------------------------------------------------------------- 1 | // Generated by the gRPC protobuf plugin. 2 | // If you make any local change, they will be lost. 3 | // source: grpc_service.proto 4 | 5 | #include "grpc_service.pb.h" 6 | #include "grpc_service.grpc.pb.h" 7 | 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | namespace grpc_code { 17 | 18 | static const char* GrpcServiceBenchmark_method_names[] = { 19 | "/grpc_code.GrpcServiceBenchmark/get_answer", 20 | "/grpc_code.GrpcServiceBenchmark/get_blob", 21 | "/grpc_code.GrpcServiceBenchmark/get_structs", 22 | }; 23 | 24 | std::unique_ptr< GrpcServiceBenchmark::Stub> GrpcServiceBenchmark::NewStub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, const ::grpc::StubOptions& options) { 25 | std::unique_ptr< GrpcServiceBenchmark::Stub> stub(new GrpcServiceBenchmark::Stub(channel)); 26 | return stub; 27 | } 28 | 29 | GrpcServiceBenchmark::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel) 30 | : channel_(channel), rpcmethod_get_answer_(GrpcServiceBenchmark_method_names[0], ::grpc::RpcMethod::NORMAL_RPC, channel) 31 | , rpcmethod_get_blob_(GrpcServiceBenchmark_method_names[1], ::grpc::RpcMethod::NORMAL_RPC, channel) 32 | , rpcmethod_get_structs_(GrpcServiceBenchmark_method_names[2], ::grpc::RpcMethod::NORMAL_RPC, channel) 33 | {} 34 | 35 | ::grpc::Status GrpcServiceBenchmark::Stub::get_answer(::grpc::ClientContext* context, const ::grpc_code::AnswerRequest& request, ::grpc_code::AnswerReply* response) { 36 | return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_get_answer_, context, request, response); 37 | } 38 | 39 | ::grpc::ClientAsyncResponseReader< ::grpc_code::AnswerReply>* GrpcServiceBenchmark::Stub::Asyncget_answerRaw(::grpc::ClientContext* context, const ::grpc_code::AnswerRequest& request, ::grpc::CompletionQueue* cq) { 40 | return new ::grpc::ClientAsyncResponseReader< ::grpc_code::AnswerReply>(channel_.get(), cq, rpcmethod_get_answer_, context, request); 41 | } 42 | 43 | ::grpc::Status GrpcServiceBenchmark::Stub::get_blob(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc_code::BlobResponse* response) { 44 | return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_get_blob_, context, request, response); 45 | } 46 | 47 | ::grpc::ClientAsyncResponseReader< ::grpc_code::BlobResponse>* GrpcServiceBenchmark::Stub::Asyncget_blobRaw(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) { 48 | return new ::grpc::ClientAsyncResponseReader< ::grpc_code::BlobResponse>(channel_.get(), cq, rpcmethod_get_blob_, context, request); 49 | } 50 | 51 | ::grpc::Status GrpcServiceBenchmark::Stub::get_structs(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc_code::StudentDataResponse* response) { 52 | return ::grpc::BlockingUnaryCall(channel_.get(), rpcmethod_get_structs_, context, request, response); 53 | } 54 | 55 | ::grpc::ClientAsyncResponseReader< ::grpc_code::StudentDataResponse>* GrpcServiceBenchmark::Stub::Asyncget_structsRaw(::grpc::ClientContext* context, const ::grpc_code::EmptyRequest& request, ::grpc::CompletionQueue* cq) { 56 | return new ::grpc::ClientAsyncResponseReader< ::grpc_code::StudentDataResponse>(channel_.get(), cq, rpcmethod_get_structs_, context, request); 57 | } 58 | 59 | GrpcServiceBenchmark::Service::Service() { 60 | AddMethod(new ::grpc::RpcServiceMethod( 61 | GrpcServiceBenchmark_method_names[0], 62 | ::grpc::RpcMethod::NORMAL_RPC, 63 | new ::grpc::RpcMethodHandler< GrpcServiceBenchmark::Service, ::grpc_code::AnswerRequest, ::grpc_code::AnswerReply>( 64 | std::mem_fn(&GrpcServiceBenchmark::Service::get_answer), this))); 65 | AddMethod(new ::grpc::RpcServiceMethod( 66 | GrpcServiceBenchmark_method_names[1], 67 | ::grpc::RpcMethod::NORMAL_RPC, 68 | new ::grpc::RpcMethodHandler< GrpcServiceBenchmark::Service, ::grpc_code::EmptyRequest, ::grpc_code::BlobResponse>( 69 | std::mem_fn(&GrpcServiceBenchmark::Service::get_blob), this))); 70 | AddMethod(new ::grpc::RpcServiceMethod( 71 | GrpcServiceBenchmark_method_names[2], 72 | ::grpc::RpcMethod::NORMAL_RPC, 73 | new ::grpc::RpcMethodHandler< GrpcServiceBenchmark::Service, ::grpc_code::EmptyRequest, ::grpc_code::StudentDataResponse>( 74 | std::mem_fn(&GrpcServiceBenchmark::Service::get_structs), this))); 75 | } 76 | 77 | GrpcServiceBenchmark::Service::~Service() { 78 | } 79 | 80 | ::grpc::Status GrpcServiceBenchmark::Service::get_answer(::grpc::ServerContext* context, const ::grpc_code::AnswerRequest* request, ::grpc_code::AnswerReply* response) { 81 | (void) context; 82 | (void) request; 83 | (void) response; 84 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 85 | } 86 | 87 | ::grpc::Status GrpcServiceBenchmark::Service::get_blob(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::BlobResponse* response) { 88 | (void) context; 89 | (void) request; 90 | (void) response; 91 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 92 | } 93 | 94 | ::grpc::Status GrpcServiceBenchmark::Service::get_structs(::grpc::ServerContext* context, const ::grpc_code::EmptyRequest* request, ::grpc_code::StudentDataResponse* response) { 95 | (void) context; 96 | (void) request; 97 | (void) response; 98 | return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); 99 | } 100 | 101 | 102 | } // namespace grpc_code 103 | 104 | -------------------------------------------------------------------------------- /src/grpc/struct_helpers.cc: -------------------------------------------------------------------------------- 1 | #include "grpc/struct_helpers.h" 2 | #include "target_code.h" 3 | #include 4 | 5 | namespace grpc_code { 6 | 7 | static Date random_Date() { 8 | Date date; 9 | date.set_year(rand() % 30 + 1900); 10 | date.set_month(static_cast(rand() % 12 + 1)); 11 | date.set_day(static_cast(rand() % 30 + 1)); 12 | return date; 13 | } 14 | 15 | static Address random_Address() { 16 | Address addr; 17 | addr.set_city(rand_str(12)); 18 | addr.set_zipcode(rand() % 3000 + 5000); 19 | addr.set_street(rand_str(16)); 20 | addr.set_number(static_cast(rand() % 125 + 1)); 21 | return addr; 22 | } 23 | 24 | static School random_School() { 25 | School result; 26 | result.set_name(rand_str(36)); 27 | result.mutable_address()->CopyFrom(random_Address()); 28 | result.mutable_foundation()->CopyFrom(random_Date()); 29 | for (size_t i = 0; i < item_count; ++i) { 30 | result.add_email_addresses(rand_str(37)); 31 | } 32 | return result; 33 | } 34 | 35 | static Subject random_Subject() { 36 | Subject s; 37 | s.set_id(rand() % 28345); 38 | s.set_title(rand_str(22)); 39 | s.set_code(rand_str(16)); 40 | return s; 41 | } 42 | 43 | static Student random_Student() { 44 | Student s; 45 | s.set_name(rand_str(43)); 46 | s.set_friends(rand() % 600); 47 | s.mutable_home_address()->CopyFrom(random_Address()); 48 | s.mutable_birth_place()->CopyFrom(random_Address()); 49 | s.mutable_birth()->CopyFrom(random_Date()); 50 | 51 | for (size_t i = 0; i < item_count; ++i) { 52 | auto subject = s.add_favorite_subjects(); 53 | subject->CopyFrom(random_Subject()); 54 | s.add_email_addresses(rand_str(37)); 55 | auto school = s.add_schools(); 56 | school->CopyFrom(random_School()); 57 | } 58 | return s; 59 | } 60 | 61 | static StudentDataResponse struct_cache; 62 | 63 | void fill_struct_cache() { 64 | for (std::size_t i = 0; i < item_count; ++i) { 65 | auto new_s = struct_cache.add_students(); 66 | new_s->CopyFrom(random_Student()); 67 | } 68 | } 69 | 70 | StudentDataResponse& get_structs() { return struct_cache; } 71 | 72 | 73 | 74 | } /* grpc_code */ 75 | -------------------------------------------------------------------------------- /src/rpclib/struct_helpers.cc: -------------------------------------------------------------------------------- 1 | #include "rpclib/struct_helpers.h" 2 | 3 | namespace rpclib_code { 4 | 5 | static std::vector struct_cache; 6 | 7 | void fill_struct_cache() { 8 | for (std::size_t i = 0; i < item_count; ++i) { 9 | struct_cache.push_back(Student::random()); 10 | } 11 | } 12 | 13 | std::vector &get_structs() { return struct_cache; } 14 | 15 | } /* rpclib_bench */ 16 | -------------------------------------------------------------------------------- /src/target_code.cc: -------------------------------------------------------------------------------- 1 | #include "target_code.h" 2 | #include 3 | #include 4 | 5 | int get_answer(int num) { 6 | return 41 + num; 7 | } 8 | 9 | static std::map blob_cache; 10 | 11 | const std::string& get_blob(int size) { 12 | if (blob_cache.find(size) != end(blob_cache)) { 13 | return blob_cache[size]; 14 | } 15 | 16 | std::string s; 17 | s.resize(size); 18 | for (auto &c : s) { 19 | c = static_cast(rand() % 256); 20 | } 21 | 22 | blob_cache[size] = std::move(s); 23 | return blob_cache[size]; 24 | } 25 | 26 | std::string rand_str(std::size_t size) { 27 | static const char alphanum[] = "0123456789" 28 | "AB CDEFGHIJKLMNOPQRSTUV WXYZ" 29 | "abcdefghij klmnopqrstuvwxyz "; 30 | std::string s; 31 | s.resize(size); 32 | for (std::size_t i = 0; i < size; ++i) { 33 | s[i] = alphanum[rand() % (sizeof(alphanum) - 1)]; 34 | } 35 | return s; 36 | } 37 | 38 | -------------------------------------------------------------------------------- /src/thrift/ThriftServiceBenchmark.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.3) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #include "ThriftServiceBenchmark.h" 8 | 9 | namespace thrift_code { 10 | 11 | 12 | ThriftServiceBenchmark_get_answer_args::~ThriftServiceBenchmark_get_answer_args() throw() { 13 | } 14 | 15 | 16 | uint32_t ThriftServiceBenchmark_get_answer_args::read(::apache::thrift::protocol::TProtocol* iprot) { 17 | 18 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 19 | uint32_t xfer = 0; 20 | std::string fname; 21 | ::apache::thrift::protocol::TType ftype; 22 | int16_t fid; 23 | 24 | xfer += iprot->readStructBegin(fname); 25 | 26 | using ::apache::thrift::protocol::TProtocolException; 27 | 28 | 29 | while (true) 30 | { 31 | xfer += iprot->readFieldBegin(fname, ftype, fid); 32 | if (ftype == ::apache::thrift::protocol::T_STOP) { 33 | break; 34 | } 35 | switch (fid) 36 | { 37 | case 1: 38 | if (ftype == ::apache::thrift::protocol::T_I32) { 39 | xfer += iprot->readI32(this->number); 40 | this->__isset.number = true; 41 | } else { 42 | xfer += iprot->skip(ftype); 43 | } 44 | break; 45 | default: 46 | xfer += iprot->skip(ftype); 47 | break; 48 | } 49 | xfer += iprot->readFieldEnd(); 50 | } 51 | 52 | xfer += iprot->readStructEnd(); 53 | 54 | return xfer; 55 | } 56 | 57 | uint32_t ThriftServiceBenchmark_get_answer_args::write(::apache::thrift::protocol::TProtocol* oprot) const { 58 | uint32_t xfer = 0; 59 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 60 | xfer += oprot->writeStructBegin("ThriftServiceBenchmark_get_answer_args"); 61 | 62 | xfer += oprot->writeFieldBegin("number", ::apache::thrift::protocol::T_I32, 1); 63 | xfer += oprot->writeI32(this->number); 64 | xfer += oprot->writeFieldEnd(); 65 | 66 | xfer += oprot->writeFieldStop(); 67 | xfer += oprot->writeStructEnd(); 68 | return xfer; 69 | } 70 | 71 | 72 | ThriftServiceBenchmark_get_answer_pargs::~ThriftServiceBenchmark_get_answer_pargs() throw() { 73 | } 74 | 75 | 76 | uint32_t ThriftServiceBenchmark_get_answer_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { 77 | uint32_t xfer = 0; 78 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 79 | xfer += oprot->writeStructBegin("ThriftServiceBenchmark_get_answer_pargs"); 80 | 81 | xfer += oprot->writeFieldBegin("number", ::apache::thrift::protocol::T_I32, 1); 82 | xfer += oprot->writeI32((*(this->number))); 83 | xfer += oprot->writeFieldEnd(); 84 | 85 | xfer += oprot->writeFieldStop(); 86 | xfer += oprot->writeStructEnd(); 87 | return xfer; 88 | } 89 | 90 | 91 | ThriftServiceBenchmark_get_answer_result::~ThriftServiceBenchmark_get_answer_result() throw() { 92 | } 93 | 94 | 95 | uint32_t ThriftServiceBenchmark_get_answer_result::read(::apache::thrift::protocol::TProtocol* iprot) { 96 | 97 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 98 | uint32_t xfer = 0; 99 | std::string fname; 100 | ::apache::thrift::protocol::TType ftype; 101 | int16_t fid; 102 | 103 | xfer += iprot->readStructBegin(fname); 104 | 105 | using ::apache::thrift::protocol::TProtocolException; 106 | 107 | 108 | while (true) 109 | { 110 | xfer += iprot->readFieldBegin(fname, ftype, fid); 111 | if (ftype == ::apache::thrift::protocol::T_STOP) { 112 | break; 113 | } 114 | switch (fid) 115 | { 116 | case 0: 117 | if (ftype == ::apache::thrift::protocol::T_I32) { 118 | xfer += iprot->readI32(this->success); 119 | this->__isset.success = true; 120 | } else { 121 | xfer += iprot->skip(ftype); 122 | } 123 | break; 124 | default: 125 | xfer += iprot->skip(ftype); 126 | break; 127 | } 128 | xfer += iprot->readFieldEnd(); 129 | } 130 | 131 | xfer += iprot->readStructEnd(); 132 | 133 | return xfer; 134 | } 135 | 136 | uint32_t ThriftServiceBenchmark_get_answer_result::write(::apache::thrift::protocol::TProtocol* oprot) const { 137 | 138 | uint32_t xfer = 0; 139 | 140 | xfer += oprot->writeStructBegin("ThriftServiceBenchmark_get_answer_result"); 141 | 142 | if (this->__isset.success) { 143 | xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_I32, 0); 144 | xfer += oprot->writeI32(this->success); 145 | xfer += oprot->writeFieldEnd(); 146 | } 147 | xfer += oprot->writeFieldStop(); 148 | xfer += oprot->writeStructEnd(); 149 | return xfer; 150 | } 151 | 152 | 153 | ThriftServiceBenchmark_get_answer_presult::~ThriftServiceBenchmark_get_answer_presult() throw() { 154 | } 155 | 156 | 157 | uint32_t ThriftServiceBenchmark_get_answer_presult::read(::apache::thrift::protocol::TProtocol* iprot) { 158 | 159 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 160 | uint32_t xfer = 0; 161 | std::string fname; 162 | ::apache::thrift::protocol::TType ftype; 163 | int16_t fid; 164 | 165 | xfer += iprot->readStructBegin(fname); 166 | 167 | using ::apache::thrift::protocol::TProtocolException; 168 | 169 | 170 | while (true) 171 | { 172 | xfer += iprot->readFieldBegin(fname, ftype, fid); 173 | if (ftype == ::apache::thrift::protocol::T_STOP) { 174 | break; 175 | } 176 | switch (fid) 177 | { 178 | case 0: 179 | if (ftype == ::apache::thrift::protocol::T_I32) { 180 | xfer += iprot->readI32((*(this->success))); 181 | this->__isset.success = true; 182 | } else { 183 | xfer += iprot->skip(ftype); 184 | } 185 | break; 186 | default: 187 | xfer += iprot->skip(ftype); 188 | break; 189 | } 190 | xfer += iprot->readFieldEnd(); 191 | } 192 | 193 | xfer += iprot->readStructEnd(); 194 | 195 | return xfer; 196 | } 197 | 198 | 199 | ThriftServiceBenchmark_get_blob_args::~ThriftServiceBenchmark_get_blob_args() throw() { 200 | } 201 | 202 | 203 | uint32_t ThriftServiceBenchmark_get_blob_args::read(::apache::thrift::protocol::TProtocol* iprot) { 204 | 205 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 206 | uint32_t xfer = 0; 207 | std::string fname; 208 | ::apache::thrift::protocol::TType ftype; 209 | int16_t fid; 210 | 211 | xfer += iprot->readStructBegin(fname); 212 | 213 | using ::apache::thrift::protocol::TProtocolException; 214 | 215 | 216 | while (true) 217 | { 218 | xfer += iprot->readFieldBegin(fname, ftype, fid); 219 | if (ftype == ::apache::thrift::protocol::T_STOP) { 220 | break; 221 | } 222 | xfer += iprot->skip(ftype); 223 | xfer += iprot->readFieldEnd(); 224 | } 225 | 226 | xfer += iprot->readStructEnd(); 227 | 228 | return xfer; 229 | } 230 | 231 | uint32_t ThriftServiceBenchmark_get_blob_args::write(::apache::thrift::protocol::TProtocol* oprot) const { 232 | uint32_t xfer = 0; 233 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 234 | xfer += oprot->writeStructBegin("ThriftServiceBenchmark_get_blob_args"); 235 | 236 | xfer += oprot->writeFieldStop(); 237 | xfer += oprot->writeStructEnd(); 238 | return xfer; 239 | } 240 | 241 | 242 | ThriftServiceBenchmark_get_blob_pargs::~ThriftServiceBenchmark_get_blob_pargs() throw() { 243 | } 244 | 245 | 246 | uint32_t ThriftServiceBenchmark_get_blob_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { 247 | uint32_t xfer = 0; 248 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 249 | xfer += oprot->writeStructBegin("ThriftServiceBenchmark_get_blob_pargs"); 250 | 251 | xfer += oprot->writeFieldStop(); 252 | xfer += oprot->writeStructEnd(); 253 | return xfer; 254 | } 255 | 256 | 257 | ThriftServiceBenchmark_get_blob_result::~ThriftServiceBenchmark_get_blob_result() throw() { 258 | } 259 | 260 | 261 | uint32_t ThriftServiceBenchmark_get_blob_result::read(::apache::thrift::protocol::TProtocol* iprot) { 262 | 263 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 264 | uint32_t xfer = 0; 265 | std::string fname; 266 | ::apache::thrift::protocol::TType ftype; 267 | int16_t fid; 268 | 269 | xfer += iprot->readStructBegin(fname); 270 | 271 | using ::apache::thrift::protocol::TProtocolException; 272 | 273 | 274 | while (true) 275 | { 276 | xfer += iprot->readFieldBegin(fname, ftype, fid); 277 | if (ftype == ::apache::thrift::protocol::T_STOP) { 278 | break; 279 | } 280 | switch (fid) 281 | { 282 | case 0: 283 | if (ftype == ::apache::thrift::protocol::T_STRING) { 284 | xfer += iprot->readBinary(this->success); 285 | this->__isset.success = true; 286 | } else { 287 | xfer += iprot->skip(ftype); 288 | } 289 | break; 290 | default: 291 | xfer += iprot->skip(ftype); 292 | break; 293 | } 294 | xfer += iprot->readFieldEnd(); 295 | } 296 | 297 | xfer += iprot->readStructEnd(); 298 | 299 | return xfer; 300 | } 301 | 302 | uint32_t ThriftServiceBenchmark_get_blob_result::write(::apache::thrift::protocol::TProtocol* oprot) const { 303 | 304 | uint32_t xfer = 0; 305 | 306 | xfer += oprot->writeStructBegin("ThriftServiceBenchmark_get_blob_result"); 307 | 308 | if (this->__isset.success) { 309 | xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_STRING, 0); 310 | xfer += oprot->writeBinary(this->success); 311 | xfer += oprot->writeFieldEnd(); 312 | } 313 | xfer += oprot->writeFieldStop(); 314 | xfer += oprot->writeStructEnd(); 315 | return xfer; 316 | } 317 | 318 | 319 | ThriftServiceBenchmark_get_blob_presult::~ThriftServiceBenchmark_get_blob_presult() throw() { 320 | } 321 | 322 | 323 | uint32_t ThriftServiceBenchmark_get_blob_presult::read(::apache::thrift::protocol::TProtocol* iprot) { 324 | 325 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 326 | uint32_t xfer = 0; 327 | std::string fname; 328 | ::apache::thrift::protocol::TType ftype; 329 | int16_t fid; 330 | 331 | xfer += iprot->readStructBegin(fname); 332 | 333 | using ::apache::thrift::protocol::TProtocolException; 334 | 335 | 336 | while (true) 337 | { 338 | xfer += iprot->readFieldBegin(fname, ftype, fid); 339 | if (ftype == ::apache::thrift::protocol::T_STOP) { 340 | break; 341 | } 342 | switch (fid) 343 | { 344 | case 0: 345 | if (ftype == ::apache::thrift::protocol::T_STRING) { 346 | xfer += iprot->readBinary((*(this->success))); 347 | this->__isset.success = true; 348 | } else { 349 | xfer += iprot->skip(ftype); 350 | } 351 | break; 352 | default: 353 | xfer += iprot->skip(ftype); 354 | break; 355 | } 356 | xfer += iprot->readFieldEnd(); 357 | } 358 | 359 | xfer += iprot->readStructEnd(); 360 | 361 | return xfer; 362 | } 363 | 364 | 365 | ThriftServiceBenchmark_get_structs_args::~ThriftServiceBenchmark_get_structs_args() throw() { 366 | } 367 | 368 | 369 | uint32_t ThriftServiceBenchmark_get_structs_args::read(::apache::thrift::protocol::TProtocol* iprot) { 370 | 371 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 372 | uint32_t xfer = 0; 373 | std::string fname; 374 | ::apache::thrift::protocol::TType ftype; 375 | int16_t fid; 376 | 377 | xfer += iprot->readStructBegin(fname); 378 | 379 | using ::apache::thrift::protocol::TProtocolException; 380 | 381 | 382 | while (true) 383 | { 384 | xfer += iprot->readFieldBegin(fname, ftype, fid); 385 | if (ftype == ::apache::thrift::protocol::T_STOP) { 386 | break; 387 | } 388 | xfer += iprot->skip(ftype); 389 | xfer += iprot->readFieldEnd(); 390 | } 391 | 392 | xfer += iprot->readStructEnd(); 393 | 394 | return xfer; 395 | } 396 | 397 | uint32_t ThriftServiceBenchmark_get_structs_args::write(::apache::thrift::protocol::TProtocol* oprot) const { 398 | uint32_t xfer = 0; 399 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 400 | xfer += oprot->writeStructBegin("ThriftServiceBenchmark_get_structs_args"); 401 | 402 | xfer += oprot->writeFieldStop(); 403 | xfer += oprot->writeStructEnd(); 404 | return xfer; 405 | } 406 | 407 | 408 | ThriftServiceBenchmark_get_structs_pargs::~ThriftServiceBenchmark_get_structs_pargs() throw() { 409 | } 410 | 411 | 412 | uint32_t ThriftServiceBenchmark_get_structs_pargs::write(::apache::thrift::protocol::TProtocol* oprot) const { 413 | uint32_t xfer = 0; 414 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 415 | xfer += oprot->writeStructBegin("ThriftServiceBenchmark_get_structs_pargs"); 416 | 417 | xfer += oprot->writeFieldStop(); 418 | xfer += oprot->writeStructEnd(); 419 | return xfer; 420 | } 421 | 422 | 423 | ThriftServiceBenchmark_get_structs_result::~ThriftServiceBenchmark_get_structs_result() throw() { 424 | } 425 | 426 | 427 | uint32_t ThriftServiceBenchmark_get_structs_result::read(::apache::thrift::protocol::TProtocol* iprot) { 428 | 429 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 430 | uint32_t xfer = 0; 431 | std::string fname; 432 | ::apache::thrift::protocol::TType ftype; 433 | int16_t fid; 434 | 435 | xfer += iprot->readStructBegin(fname); 436 | 437 | using ::apache::thrift::protocol::TProtocolException; 438 | 439 | 440 | while (true) 441 | { 442 | xfer += iprot->readFieldBegin(fname, ftype, fid); 443 | if (ftype == ::apache::thrift::protocol::T_STOP) { 444 | break; 445 | } 446 | switch (fid) 447 | { 448 | case 0: 449 | if (ftype == ::apache::thrift::protocol::T_LIST) { 450 | { 451 | this->success.clear(); 452 | uint32_t _size34; 453 | ::apache::thrift::protocol::TType _etype37; 454 | xfer += iprot->readListBegin(_etype37, _size34); 455 | this->success.resize(_size34); 456 | uint32_t _i38; 457 | for (_i38 = 0; _i38 < _size34; ++_i38) 458 | { 459 | xfer += this->success[_i38].read(iprot); 460 | } 461 | xfer += iprot->readListEnd(); 462 | } 463 | this->__isset.success = true; 464 | } else { 465 | xfer += iprot->skip(ftype); 466 | } 467 | break; 468 | default: 469 | xfer += iprot->skip(ftype); 470 | break; 471 | } 472 | xfer += iprot->readFieldEnd(); 473 | } 474 | 475 | xfer += iprot->readStructEnd(); 476 | 477 | return xfer; 478 | } 479 | 480 | uint32_t ThriftServiceBenchmark_get_structs_result::write(::apache::thrift::protocol::TProtocol* oprot) const { 481 | 482 | uint32_t xfer = 0; 483 | 484 | xfer += oprot->writeStructBegin("ThriftServiceBenchmark_get_structs_result"); 485 | 486 | if (this->__isset.success) { 487 | xfer += oprot->writeFieldBegin("success", ::apache::thrift::protocol::T_LIST, 0); 488 | { 489 | xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->success.size())); 490 | std::vector ::const_iterator _iter39; 491 | for (_iter39 = this->success.begin(); _iter39 != this->success.end(); ++_iter39) 492 | { 493 | xfer += (*_iter39).write(oprot); 494 | } 495 | xfer += oprot->writeListEnd(); 496 | } 497 | xfer += oprot->writeFieldEnd(); 498 | } 499 | xfer += oprot->writeFieldStop(); 500 | xfer += oprot->writeStructEnd(); 501 | return xfer; 502 | } 503 | 504 | 505 | ThriftServiceBenchmark_get_structs_presult::~ThriftServiceBenchmark_get_structs_presult() throw() { 506 | } 507 | 508 | 509 | uint32_t ThriftServiceBenchmark_get_structs_presult::read(::apache::thrift::protocol::TProtocol* iprot) { 510 | 511 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 512 | uint32_t xfer = 0; 513 | std::string fname; 514 | ::apache::thrift::protocol::TType ftype; 515 | int16_t fid; 516 | 517 | xfer += iprot->readStructBegin(fname); 518 | 519 | using ::apache::thrift::protocol::TProtocolException; 520 | 521 | 522 | while (true) 523 | { 524 | xfer += iprot->readFieldBegin(fname, ftype, fid); 525 | if (ftype == ::apache::thrift::protocol::T_STOP) { 526 | break; 527 | } 528 | switch (fid) 529 | { 530 | case 0: 531 | if (ftype == ::apache::thrift::protocol::T_LIST) { 532 | { 533 | (*(this->success)).clear(); 534 | uint32_t _size40; 535 | ::apache::thrift::protocol::TType _etype43; 536 | xfer += iprot->readListBegin(_etype43, _size40); 537 | (*(this->success)).resize(_size40); 538 | uint32_t _i44; 539 | for (_i44 = 0; _i44 < _size40; ++_i44) 540 | { 541 | xfer += (*(this->success))[_i44].read(iprot); 542 | } 543 | xfer += iprot->readListEnd(); 544 | } 545 | this->__isset.success = true; 546 | } else { 547 | xfer += iprot->skip(ftype); 548 | } 549 | break; 550 | default: 551 | xfer += iprot->skip(ftype); 552 | break; 553 | } 554 | xfer += iprot->readFieldEnd(); 555 | } 556 | 557 | xfer += iprot->readStructEnd(); 558 | 559 | return xfer; 560 | } 561 | 562 | int32_t ThriftServiceBenchmarkClient::get_answer(const int32_t number) 563 | { 564 | send_get_answer(number); 565 | return recv_get_answer(); 566 | } 567 | 568 | void ThriftServiceBenchmarkClient::send_get_answer(const int32_t number) 569 | { 570 | int32_t cseqid = 0; 571 | oprot_->writeMessageBegin("get_answer", ::apache::thrift::protocol::T_CALL, cseqid); 572 | 573 | ThriftServiceBenchmark_get_answer_pargs args; 574 | args.number = &number; 575 | args.write(oprot_); 576 | 577 | oprot_->writeMessageEnd(); 578 | oprot_->getTransport()->writeEnd(); 579 | oprot_->getTransport()->flush(); 580 | } 581 | 582 | int32_t ThriftServiceBenchmarkClient::recv_get_answer() 583 | { 584 | 585 | int32_t rseqid = 0; 586 | std::string fname; 587 | ::apache::thrift::protocol::TMessageType mtype; 588 | 589 | iprot_->readMessageBegin(fname, mtype, rseqid); 590 | if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { 591 | ::apache::thrift::TApplicationException x; 592 | x.read(iprot_); 593 | iprot_->readMessageEnd(); 594 | iprot_->getTransport()->readEnd(); 595 | throw x; 596 | } 597 | if (mtype != ::apache::thrift::protocol::T_REPLY) { 598 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 599 | iprot_->readMessageEnd(); 600 | iprot_->getTransport()->readEnd(); 601 | } 602 | if (fname.compare("get_answer") != 0) { 603 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 604 | iprot_->readMessageEnd(); 605 | iprot_->getTransport()->readEnd(); 606 | } 607 | int32_t _return; 608 | ThriftServiceBenchmark_get_answer_presult result; 609 | result.success = &_return; 610 | result.read(iprot_); 611 | iprot_->readMessageEnd(); 612 | iprot_->getTransport()->readEnd(); 613 | 614 | if (result.__isset.success) { 615 | return _return; 616 | } 617 | throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "get_answer failed: unknown result"); 618 | } 619 | 620 | void ThriftServiceBenchmarkClient::get_blob(std::string& _return) 621 | { 622 | send_get_blob(); 623 | recv_get_blob(_return); 624 | } 625 | 626 | void ThriftServiceBenchmarkClient::send_get_blob() 627 | { 628 | int32_t cseqid = 0; 629 | oprot_->writeMessageBegin("get_blob", ::apache::thrift::protocol::T_CALL, cseqid); 630 | 631 | ThriftServiceBenchmark_get_blob_pargs args; 632 | args.write(oprot_); 633 | 634 | oprot_->writeMessageEnd(); 635 | oprot_->getTransport()->writeEnd(); 636 | oprot_->getTransport()->flush(); 637 | } 638 | 639 | void ThriftServiceBenchmarkClient::recv_get_blob(std::string& _return) 640 | { 641 | 642 | int32_t rseqid = 0; 643 | std::string fname; 644 | ::apache::thrift::protocol::TMessageType mtype; 645 | 646 | iprot_->readMessageBegin(fname, mtype, rseqid); 647 | if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { 648 | ::apache::thrift::TApplicationException x; 649 | x.read(iprot_); 650 | iprot_->readMessageEnd(); 651 | iprot_->getTransport()->readEnd(); 652 | throw x; 653 | } 654 | if (mtype != ::apache::thrift::protocol::T_REPLY) { 655 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 656 | iprot_->readMessageEnd(); 657 | iprot_->getTransport()->readEnd(); 658 | } 659 | if (fname.compare("get_blob") != 0) { 660 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 661 | iprot_->readMessageEnd(); 662 | iprot_->getTransport()->readEnd(); 663 | } 664 | ThriftServiceBenchmark_get_blob_presult result; 665 | result.success = &_return; 666 | result.read(iprot_); 667 | iprot_->readMessageEnd(); 668 | iprot_->getTransport()->readEnd(); 669 | 670 | if (result.__isset.success) { 671 | // _return pointer has now been filled 672 | return; 673 | } 674 | throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "get_blob failed: unknown result"); 675 | } 676 | 677 | void ThriftServiceBenchmarkClient::get_structs(std::vector & _return) 678 | { 679 | send_get_structs(); 680 | recv_get_structs(_return); 681 | } 682 | 683 | void ThriftServiceBenchmarkClient::send_get_structs() 684 | { 685 | int32_t cseqid = 0; 686 | oprot_->writeMessageBegin("get_structs", ::apache::thrift::protocol::T_CALL, cseqid); 687 | 688 | ThriftServiceBenchmark_get_structs_pargs args; 689 | args.write(oprot_); 690 | 691 | oprot_->writeMessageEnd(); 692 | oprot_->getTransport()->writeEnd(); 693 | oprot_->getTransport()->flush(); 694 | } 695 | 696 | void ThriftServiceBenchmarkClient::recv_get_structs(std::vector & _return) 697 | { 698 | 699 | int32_t rseqid = 0; 700 | std::string fname; 701 | ::apache::thrift::protocol::TMessageType mtype; 702 | 703 | iprot_->readMessageBegin(fname, mtype, rseqid); 704 | if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { 705 | ::apache::thrift::TApplicationException x; 706 | x.read(iprot_); 707 | iprot_->readMessageEnd(); 708 | iprot_->getTransport()->readEnd(); 709 | throw x; 710 | } 711 | if (mtype != ::apache::thrift::protocol::T_REPLY) { 712 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 713 | iprot_->readMessageEnd(); 714 | iprot_->getTransport()->readEnd(); 715 | } 716 | if (fname.compare("get_structs") != 0) { 717 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 718 | iprot_->readMessageEnd(); 719 | iprot_->getTransport()->readEnd(); 720 | } 721 | ThriftServiceBenchmark_get_structs_presult result; 722 | result.success = &_return; 723 | result.read(iprot_); 724 | iprot_->readMessageEnd(); 725 | iprot_->getTransport()->readEnd(); 726 | 727 | if (result.__isset.success) { 728 | // _return pointer has now been filled 729 | return; 730 | } 731 | throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "get_structs failed: unknown result"); 732 | } 733 | 734 | bool ThriftServiceBenchmarkProcessor::dispatchCall(::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, const std::string& fname, int32_t seqid, void* callContext) { 735 | ProcessMap::iterator pfn; 736 | pfn = processMap_.find(fname); 737 | if (pfn == processMap_.end()) { 738 | iprot->skip(::apache::thrift::protocol::T_STRUCT); 739 | iprot->readMessageEnd(); 740 | iprot->getTransport()->readEnd(); 741 | ::apache::thrift::TApplicationException x(::apache::thrift::TApplicationException::UNKNOWN_METHOD, "Invalid method name: '"+fname+"'"); 742 | oprot->writeMessageBegin(fname, ::apache::thrift::protocol::T_EXCEPTION, seqid); 743 | x.write(oprot); 744 | oprot->writeMessageEnd(); 745 | oprot->getTransport()->writeEnd(); 746 | oprot->getTransport()->flush(); 747 | return true; 748 | } 749 | (this->*(pfn->second))(seqid, iprot, oprot, callContext); 750 | return true; 751 | } 752 | 753 | void ThriftServiceBenchmarkProcessor::process_get_answer(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) 754 | { 755 | void* ctx = NULL; 756 | if (this->eventHandler_.get() != NULL) { 757 | ctx = this->eventHandler_->getContext("ThriftServiceBenchmark.get_answer", callContext); 758 | } 759 | ::apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "ThriftServiceBenchmark.get_answer"); 760 | 761 | if (this->eventHandler_.get() != NULL) { 762 | this->eventHandler_->preRead(ctx, "ThriftServiceBenchmark.get_answer"); 763 | } 764 | 765 | ThriftServiceBenchmark_get_answer_args args; 766 | args.read(iprot); 767 | iprot->readMessageEnd(); 768 | uint32_t bytes = iprot->getTransport()->readEnd(); 769 | 770 | if (this->eventHandler_.get() != NULL) { 771 | this->eventHandler_->postRead(ctx, "ThriftServiceBenchmark.get_answer", bytes); 772 | } 773 | 774 | ThriftServiceBenchmark_get_answer_result result; 775 | try { 776 | result.success = iface_->get_answer(args.number); 777 | result.__isset.success = true; 778 | } catch (const std::exception& e) { 779 | if (this->eventHandler_.get() != NULL) { 780 | this->eventHandler_->handlerError(ctx, "ThriftServiceBenchmark.get_answer"); 781 | } 782 | 783 | ::apache::thrift::TApplicationException x(e.what()); 784 | oprot->writeMessageBegin("get_answer", ::apache::thrift::protocol::T_EXCEPTION, seqid); 785 | x.write(oprot); 786 | oprot->writeMessageEnd(); 787 | oprot->getTransport()->writeEnd(); 788 | oprot->getTransport()->flush(); 789 | return; 790 | } 791 | 792 | if (this->eventHandler_.get() != NULL) { 793 | this->eventHandler_->preWrite(ctx, "ThriftServiceBenchmark.get_answer"); 794 | } 795 | 796 | oprot->writeMessageBegin("get_answer", ::apache::thrift::protocol::T_REPLY, seqid); 797 | result.write(oprot); 798 | oprot->writeMessageEnd(); 799 | bytes = oprot->getTransport()->writeEnd(); 800 | oprot->getTransport()->flush(); 801 | 802 | if (this->eventHandler_.get() != NULL) { 803 | this->eventHandler_->postWrite(ctx, "ThriftServiceBenchmark.get_answer", bytes); 804 | } 805 | } 806 | 807 | void ThriftServiceBenchmarkProcessor::process_get_blob(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) 808 | { 809 | void* ctx = NULL; 810 | if (this->eventHandler_.get() != NULL) { 811 | ctx = this->eventHandler_->getContext("ThriftServiceBenchmark.get_blob", callContext); 812 | } 813 | ::apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "ThriftServiceBenchmark.get_blob"); 814 | 815 | if (this->eventHandler_.get() != NULL) { 816 | this->eventHandler_->preRead(ctx, "ThriftServiceBenchmark.get_blob"); 817 | } 818 | 819 | ThriftServiceBenchmark_get_blob_args args; 820 | args.read(iprot); 821 | iprot->readMessageEnd(); 822 | uint32_t bytes = iprot->getTransport()->readEnd(); 823 | 824 | if (this->eventHandler_.get() != NULL) { 825 | this->eventHandler_->postRead(ctx, "ThriftServiceBenchmark.get_blob", bytes); 826 | } 827 | 828 | ThriftServiceBenchmark_get_blob_result result; 829 | try { 830 | iface_->get_blob(result.success); 831 | result.__isset.success = true; 832 | } catch (const std::exception& e) { 833 | if (this->eventHandler_.get() != NULL) { 834 | this->eventHandler_->handlerError(ctx, "ThriftServiceBenchmark.get_blob"); 835 | } 836 | 837 | ::apache::thrift::TApplicationException x(e.what()); 838 | oprot->writeMessageBegin("get_blob", ::apache::thrift::protocol::T_EXCEPTION, seqid); 839 | x.write(oprot); 840 | oprot->writeMessageEnd(); 841 | oprot->getTransport()->writeEnd(); 842 | oprot->getTransport()->flush(); 843 | return; 844 | } 845 | 846 | if (this->eventHandler_.get() != NULL) { 847 | this->eventHandler_->preWrite(ctx, "ThriftServiceBenchmark.get_blob"); 848 | } 849 | 850 | oprot->writeMessageBegin("get_blob", ::apache::thrift::protocol::T_REPLY, seqid); 851 | result.write(oprot); 852 | oprot->writeMessageEnd(); 853 | bytes = oprot->getTransport()->writeEnd(); 854 | oprot->getTransport()->flush(); 855 | 856 | if (this->eventHandler_.get() != NULL) { 857 | this->eventHandler_->postWrite(ctx, "ThriftServiceBenchmark.get_blob", bytes); 858 | } 859 | } 860 | 861 | void ThriftServiceBenchmarkProcessor::process_get_structs(int32_t seqid, ::apache::thrift::protocol::TProtocol* iprot, ::apache::thrift::protocol::TProtocol* oprot, void* callContext) 862 | { 863 | void* ctx = NULL; 864 | if (this->eventHandler_.get() != NULL) { 865 | ctx = this->eventHandler_->getContext("ThriftServiceBenchmark.get_structs", callContext); 866 | } 867 | ::apache::thrift::TProcessorContextFreer freer(this->eventHandler_.get(), ctx, "ThriftServiceBenchmark.get_structs"); 868 | 869 | if (this->eventHandler_.get() != NULL) { 870 | this->eventHandler_->preRead(ctx, "ThriftServiceBenchmark.get_structs"); 871 | } 872 | 873 | ThriftServiceBenchmark_get_structs_args args; 874 | args.read(iprot); 875 | iprot->readMessageEnd(); 876 | uint32_t bytes = iprot->getTransport()->readEnd(); 877 | 878 | if (this->eventHandler_.get() != NULL) { 879 | this->eventHandler_->postRead(ctx, "ThriftServiceBenchmark.get_structs", bytes); 880 | } 881 | 882 | ThriftServiceBenchmark_get_structs_result result; 883 | try { 884 | iface_->get_structs(result.success); 885 | result.__isset.success = true; 886 | } catch (const std::exception& e) { 887 | if (this->eventHandler_.get() != NULL) { 888 | this->eventHandler_->handlerError(ctx, "ThriftServiceBenchmark.get_structs"); 889 | } 890 | 891 | ::apache::thrift::TApplicationException x(e.what()); 892 | oprot->writeMessageBegin("get_structs", ::apache::thrift::protocol::T_EXCEPTION, seqid); 893 | x.write(oprot); 894 | oprot->writeMessageEnd(); 895 | oprot->getTransport()->writeEnd(); 896 | oprot->getTransport()->flush(); 897 | return; 898 | } 899 | 900 | if (this->eventHandler_.get() != NULL) { 901 | this->eventHandler_->preWrite(ctx, "ThriftServiceBenchmark.get_structs"); 902 | } 903 | 904 | oprot->writeMessageBegin("get_structs", ::apache::thrift::protocol::T_REPLY, seqid); 905 | result.write(oprot); 906 | oprot->writeMessageEnd(); 907 | bytes = oprot->getTransport()->writeEnd(); 908 | oprot->getTransport()->flush(); 909 | 910 | if (this->eventHandler_.get() != NULL) { 911 | this->eventHandler_->postWrite(ctx, "ThriftServiceBenchmark.get_structs", bytes); 912 | } 913 | } 914 | 915 | ::boost::shared_ptr< ::apache::thrift::TProcessor > ThriftServiceBenchmarkProcessorFactory::getProcessor(const ::apache::thrift::TConnectionInfo& connInfo) { 916 | ::apache::thrift::ReleaseHandler< ThriftServiceBenchmarkIfFactory > cleanup(handlerFactory_); 917 | ::boost::shared_ptr< ThriftServiceBenchmarkIf > handler(handlerFactory_->getHandler(connInfo), cleanup); 918 | ::boost::shared_ptr< ::apache::thrift::TProcessor > processor(new ThriftServiceBenchmarkProcessor(handler)); 919 | return processor; 920 | } 921 | 922 | int32_t ThriftServiceBenchmarkConcurrentClient::get_answer(const int32_t number) 923 | { 924 | int32_t seqid = send_get_answer(number); 925 | return recv_get_answer(seqid); 926 | } 927 | 928 | int32_t ThriftServiceBenchmarkConcurrentClient::send_get_answer(const int32_t number) 929 | { 930 | int32_t cseqid = this->sync_.generateSeqId(); 931 | ::apache::thrift::async::TConcurrentSendSentry sentry(&this->sync_); 932 | oprot_->writeMessageBegin("get_answer", ::apache::thrift::protocol::T_CALL, cseqid); 933 | 934 | ThriftServiceBenchmark_get_answer_pargs args; 935 | args.number = &number; 936 | args.write(oprot_); 937 | 938 | oprot_->writeMessageEnd(); 939 | oprot_->getTransport()->writeEnd(); 940 | oprot_->getTransport()->flush(); 941 | 942 | sentry.commit(); 943 | return cseqid; 944 | } 945 | 946 | int32_t ThriftServiceBenchmarkConcurrentClient::recv_get_answer(const int32_t seqid) 947 | { 948 | 949 | int32_t rseqid = 0; 950 | std::string fname; 951 | ::apache::thrift::protocol::TMessageType mtype; 952 | 953 | // the read mutex gets dropped and reacquired as part of waitForWork() 954 | // The destructor of this sentry wakes up other clients 955 | ::apache::thrift::async::TConcurrentRecvSentry sentry(&this->sync_, seqid); 956 | 957 | while(true) { 958 | if(!this->sync_.getPending(fname, mtype, rseqid)) { 959 | iprot_->readMessageBegin(fname, mtype, rseqid); 960 | } 961 | if(seqid == rseqid) { 962 | if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { 963 | ::apache::thrift::TApplicationException x; 964 | x.read(iprot_); 965 | iprot_->readMessageEnd(); 966 | iprot_->getTransport()->readEnd(); 967 | sentry.commit(); 968 | throw x; 969 | } 970 | if (mtype != ::apache::thrift::protocol::T_REPLY) { 971 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 972 | iprot_->readMessageEnd(); 973 | iprot_->getTransport()->readEnd(); 974 | } 975 | if (fname.compare("get_answer") != 0) { 976 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 977 | iprot_->readMessageEnd(); 978 | iprot_->getTransport()->readEnd(); 979 | 980 | // in a bad state, don't commit 981 | using ::apache::thrift::protocol::TProtocolException; 982 | throw TProtocolException(TProtocolException::INVALID_DATA); 983 | } 984 | int32_t _return; 985 | ThriftServiceBenchmark_get_answer_presult result; 986 | result.success = &_return; 987 | result.read(iprot_); 988 | iprot_->readMessageEnd(); 989 | iprot_->getTransport()->readEnd(); 990 | 991 | if (result.__isset.success) { 992 | sentry.commit(); 993 | return _return; 994 | } 995 | // in a bad state, don't commit 996 | throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "get_answer failed: unknown result"); 997 | } 998 | // seqid != rseqid 999 | this->sync_.updatePending(fname, mtype, rseqid); 1000 | 1001 | // this will temporarily unlock the readMutex, and let other clients get work done 1002 | this->sync_.waitForWork(seqid); 1003 | } // end while(true) 1004 | } 1005 | 1006 | void ThriftServiceBenchmarkConcurrentClient::get_blob(std::string& _return) 1007 | { 1008 | int32_t seqid = send_get_blob(); 1009 | recv_get_blob(_return, seqid); 1010 | } 1011 | 1012 | int32_t ThriftServiceBenchmarkConcurrentClient::send_get_blob() 1013 | { 1014 | int32_t cseqid = this->sync_.generateSeqId(); 1015 | ::apache::thrift::async::TConcurrentSendSentry sentry(&this->sync_); 1016 | oprot_->writeMessageBegin("get_blob", ::apache::thrift::protocol::T_CALL, cseqid); 1017 | 1018 | ThriftServiceBenchmark_get_blob_pargs args; 1019 | args.write(oprot_); 1020 | 1021 | oprot_->writeMessageEnd(); 1022 | oprot_->getTransport()->writeEnd(); 1023 | oprot_->getTransport()->flush(); 1024 | 1025 | sentry.commit(); 1026 | return cseqid; 1027 | } 1028 | 1029 | void ThriftServiceBenchmarkConcurrentClient::recv_get_blob(std::string& _return, const int32_t seqid) 1030 | { 1031 | 1032 | int32_t rseqid = 0; 1033 | std::string fname; 1034 | ::apache::thrift::protocol::TMessageType mtype; 1035 | 1036 | // the read mutex gets dropped and reacquired as part of waitForWork() 1037 | // The destructor of this sentry wakes up other clients 1038 | ::apache::thrift::async::TConcurrentRecvSentry sentry(&this->sync_, seqid); 1039 | 1040 | while(true) { 1041 | if(!this->sync_.getPending(fname, mtype, rseqid)) { 1042 | iprot_->readMessageBegin(fname, mtype, rseqid); 1043 | } 1044 | if(seqid == rseqid) { 1045 | if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { 1046 | ::apache::thrift::TApplicationException x; 1047 | x.read(iprot_); 1048 | iprot_->readMessageEnd(); 1049 | iprot_->getTransport()->readEnd(); 1050 | sentry.commit(); 1051 | throw x; 1052 | } 1053 | if (mtype != ::apache::thrift::protocol::T_REPLY) { 1054 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 1055 | iprot_->readMessageEnd(); 1056 | iprot_->getTransport()->readEnd(); 1057 | } 1058 | if (fname.compare("get_blob") != 0) { 1059 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 1060 | iprot_->readMessageEnd(); 1061 | iprot_->getTransport()->readEnd(); 1062 | 1063 | // in a bad state, don't commit 1064 | using ::apache::thrift::protocol::TProtocolException; 1065 | throw TProtocolException(TProtocolException::INVALID_DATA); 1066 | } 1067 | ThriftServiceBenchmark_get_blob_presult result; 1068 | result.success = &_return; 1069 | result.read(iprot_); 1070 | iprot_->readMessageEnd(); 1071 | iprot_->getTransport()->readEnd(); 1072 | 1073 | if (result.__isset.success) { 1074 | // _return pointer has now been filled 1075 | sentry.commit(); 1076 | return; 1077 | } 1078 | // in a bad state, don't commit 1079 | throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "get_blob failed: unknown result"); 1080 | } 1081 | // seqid != rseqid 1082 | this->sync_.updatePending(fname, mtype, rseqid); 1083 | 1084 | // this will temporarily unlock the readMutex, and let other clients get work done 1085 | this->sync_.waitForWork(seqid); 1086 | } // end while(true) 1087 | } 1088 | 1089 | void ThriftServiceBenchmarkConcurrentClient::get_structs(std::vector & _return) 1090 | { 1091 | int32_t seqid = send_get_structs(); 1092 | recv_get_structs(_return, seqid); 1093 | } 1094 | 1095 | int32_t ThriftServiceBenchmarkConcurrentClient::send_get_structs() 1096 | { 1097 | int32_t cseqid = this->sync_.generateSeqId(); 1098 | ::apache::thrift::async::TConcurrentSendSentry sentry(&this->sync_); 1099 | oprot_->writeMessageBegin("get_structs", ::apache::thrift::protocol::T_CALL, cseqid); 1100 | 1101 | ThriftServiceBenchmark_get_structs_pargs args; 1102 | args.write(oprot_); 1103 | 1104 | oprot_->writeMessageEnd(); 1105 | oprot_->getTransport()->writeEnd(); 1106 | oprot_->getTransport()->flush(); 1107 | 1108 | sentry.commit(); 1109 | return cseqid; 1110 | } 1111 | 1112 | void ThriftServiceBenchmarkConcurrentClient::recv_get_structs(std::vector & _return, const int32_t seqid) 1113 | { 1114 | 1115 | int32_t rseqid = 0; 1116 | std::string fname; 1117 | ::apache::thrift::protocol::TMessageType mtype; 1118 | 1119 | // the read mutex gets dropped and reacquired as part of waitForWork() 1120 | // The destructor of this sentry wakes up other clients 1121 | ::apache::thrift::async::TConcurrentRecvSentry sentry(&this->sync_, seqid); 1122 | 1123 | while(true) { 1124 | if(!this->sync_.getPending(fname, mtype, rseqid)) { 1125 | iprot_->readMessageBegin(fname, mtype, rseqid); 1126 | } 1127 | if(seqid == rseqid) { 1128 | if (mtype == ::apache::thrift::protocol::T_EXCEPTION) { 1129 | ::apache::thrift::TApplicationException x; 1130 | x.read(iprot_); 1131 | iprot_->readMessageEnd(); 1132 | iprot_->getTransport()->readEnd(); 1133 | sentry.commit(); 1134 | throw x; 1135 | } 1136 | if (mtype != ::apache::thrift::protocol::T_REPLY) { 1137 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 1138 | iprot_->readMessageEnd(); 1139 | iprot_->getTransport()->readEnd(); 1140 | } 1141 | if (fname.compare("get_structs") != 0) { 1142 | iprot_->skip(::apache::thrift::protocol::T_STRUCT); 1143 | iprot_->readMessageEnd(); 1144 | iprot_->getTransport()->readEnd(); 1145 | 1146 | // in a bad state, don't commit 1147 | using ::apache::thrift::protocol::TProtocolException; 1148 | throw TProtocolException(TProtocolException::INVALID_DATA); 1149 | } 1150 | ThriftServiceBenchmark_get_structs_presult result; 1151 | result.success = &_return; 1152 | result.read(iprot_); 1153 | iprot_->readMessageEnd(); 1154 | iprot_->getTransport()->readEnd(); 1155 | 1156 | if (result.__isset.success) { 1157 | // _return pointer has now been filled 1158 | sentry.commit(); 1159 | return; 1160 | } 1161 | // in a bad state, don't commit 1162 | throw ::apache::thrift::TApplicationException(::apache::thrift::TApplicationException::MISSING_RESULT, "get_structs failed: unknown result"); 1163 | } 1164 | // seqid != rseqid 1165 | this->sync_.updatePending(fname, mtype, rseqid); 1166 | 1167 | // this will temporarily unlock the readMutex, and let other clients get work done 1168 | this->sync_.waitForWork(seqid); 1169 | } // end while(true) 1170 | } 1171 | 1172 | } // namespace 1173 | 1174 | -------------------------------------------------------------------------------- /src/thrift/ThriftServiceBenchmark_server.skeleton.cpp: -------------------------------------------------------------------------------- 1 | // This autogenerated skeleton file illustrates how to build a server. 2 | // You should copy it to another filename to avoid overwriting it. 3 | 4 | #include "ThriftServiceBenchmark.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | using namespace ::apache::thrift; 11 | using namespace ::apache::thrift::protocol; 12 | using namespace ::apache::thrift::transport; 13 | using namespace ::apache::thrift::server; 14 | 15 | using boost::shared_ptr; 16 | 17 | using namespace ::thrift_code; 18 | 19 | class ThriftServiceBenchmarkHandler : virtual public ThriftServiceBenchmarkIf { 20 | public: 21 | ThriftServiceBenchmarkHandler() { 22 | // Your initialization goes here 23 | } 24 | 25 | int32_t get_answer(const int32_t number) { 26 | // Your implementation goes here 27 | printf("get_answer\n"); 28 | } 29 | 30 | void get_blob(std::string& _return) { 31 | // Your implementation goes here 32 | printf("get_blob\n"); 33 | } 34 | 35 | void get_structs(std::vector & _return) { 36 | // Your implementation goes here 37 | printf("get_structs\n"); 38 | } 39 | 40 | }; 41 | 42 | int main(int argc, char **argv) { 43 | int port = 9090; 44 | shared_ptr handler(new ThriftServiceBenchmarkHandler()); 45 | shared_ptr processor(new ThriftServiceBenchmarkProcessor(handler)); 46 | shared_ptr serverTransport(new TServerSocket(port)); 47 | shared_ptr transportFactory(new TBufferedTransportFactory()); 48 | shared_ptr protocolFactory(new TBinaryProtocolFactory()); 49 | 50 | TSimpleServer server(processor, serverTransport, transportFactory, protocolFactory); 51 | server.serve(); 52 | return 0; 53 | } 54 | 55 | -------------------------------------------------------------------------------- /src/thrift/struct_helpers.cc: -------------------------------------------------------------------------------- 1 | #include "thrift/struct_helpers.h" 2 | #include "target_code.h" 3 | #include 4 | 5 | namespace thrift_code { 6 | 7 | static Date random_Date() { 8 | Date date; 9 | date.year = rand() % 30 + 1900; 10 | date.month = static_cast(rand() % 12 + 1); 11 | date.day = static_cast(rand() % 30 + 1); 12 | return date; 13 | } 14 | 15 | static Address random_Address() { 16 | Address addr; 17 | addr.city = rand_str(12); 18 | addr.zipcode = rand() % 3000 + 5000; 19 | addr.street = rand_str(16); 20 | addr.number = static_cast(rand() % 125 + 1); 21 | return addr; 22 | } 23 | 24 | static School random_School() { 25 | School result; 26 | result.name = rand_str(36); 27 | result.address = random_Address(); 28 | result.foundation = random_Date(); 29 | for (size_t i = 0; i < item_count; ++i) { 30 | result.email_addresses.push_back(rand_str(37)); 31 | } 32 | return result; 33 | } 34 | 35 | static Subject random_Subject() { 36 | Subject s; 37 | s.id = rand() % 28345; 38 | s.title = rand_str(22); 39 | s.code = rand_str(16); 40 | return s; 41 | } 42 | 43 | static Student random_Student() { 44 | Student s; 45 | s.name = rand_str(43); 46 | s.friends = rand() % 600; 47 | s.home_address = random_Address(); 48 | s.birth_place = random_Address(); 49 | s.birth = random_Date(); 50 | 51 | for (size_t i = 0; i < item_count; ++i) { 52 | s.favorite_subjects.push_back(random_Subject()); 53 | s.email_addresses.push_back(rand_str(37)); 54 | s.schools.push_back(random_School()); 55 | } 56 | return s; 57 | } 58 | 59 | static std::vector struct_cache; 60 | 61 | void fill_struct_cache() { 62 | for (std::size_t i = 0; i < item_count; ++i) { 63 | struct_cache.push_back(random_Student()); 64 | } 65 | } 66 | 67 | std::vector &get_structs() { return struct_cache; } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/thrift/thrift_service_constants.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.3) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #include "thrift_service_constants.h" 8 | 9 | namespace thrift_code { 10 | 11 | const thrift_serviceConstants g_thrift_service_constants; 12 | 13 | thrift_serviceConstants::thrift_serviceConstants() { 14 | } 15 | 16 | } // namespace 17 | 18 | -------------------------------------------------------------------------------- /src/thrift/thrift_service_types.cpp: -------------------------------------------------------------------------------- 1 | /** 2 | * Autogenerated by Thrift Compiler (0.9.3) 3 | * 4 | * DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | * @generated 6 | */ 7 | #include "thrift_service_types.h" 8 | 9 | #include 10 | #include 11 | 12 | #include 13 | 14 | namespace thrift_code { 15 | 16 | 17 | Date::~Date() throw() { 18 | } 19 | 20 | 21 | void Date::__set_year(const int32_t val) { 22 | this->year = val; 23 | } 24 | 25 | void Date::__set_month(const int8_t val) { 26 | this->month = val; 27 | } 28 | 29 | void Date::__set_day(const int8_t val) { 30 | this->day = val; 31 | } 32 | 33 | uint32_t Date::read(::apache::thrift::protocol::TProtocol* iprot) { 34 | 35 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 36 | uint32_t xfer = 0; 37 | std::string fname; 38 | ::apache::thrift::protocol::TType ftype; 39 | int16_t fid; 40 | 41 | xfer += iprot->readStructBegin(fname); 42 | 43 | using ::apache::thrift::protocol::TProtocolException; 44 | 45 | 46 | while (true) 47 | { 48 | xfer += iprot->readFieldBegin(fname, ftype, fid); 49 | if (ftype == ::apache::thrift::protocol::T_STOP) { 50 | break; 51 | } 52 | switch (fid) 53 | { 54 | case 1: 55 | if (ftype == ::apache::thrift::protocol::T_I32) { 56 | xfer += iprot->readI32(this->year); 57 | this->__isset.year = true; 58 | } else { 59 | xfer += iprot->skip(ftype); 60 | } 61 | break; 62 | case 2: 63 | if (ftype == ::apache::thrift::protocol::T_BYTE) { 64 | xfer += iprot->readByte(this->month); 65 | this->__isset.month = true; 66 | } else { 67 | xfer += iprot->skip(ftype); 68 | } 69 | break; 70 | case 3: 71 | if (ftype == ::apache::thrift::protocol::T_BYTE) { 72 | xfer += iprot->readByte(this->day); 73 | this->__isset.day = true; 74 | } else { 75 | xfer += iprot->skip(ftype); 76 | } 77 | break; 78 | default: 79 | xfer += iprot->skip(ftype); 80 | break; 81 | } 82 | xfer += iprot->readFieldEnd(); 83 | } 84 | 85 | xfer += iprot->readStructEnd(); 86 | 87 | return xfer; 88 | } 89 | 90 | uint32_t Date::write(::apache::thrift::protocol::TProtocol* oprot) const { 91 | uint32_t xfer = 0; 92 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 93 | xfer += oprot->writeStructBegin("Date"); 94 | 95 | xfer += oprot->writeFieldBegin("year", ::apache::thrift::protocol::T_I32, 1); 96 | xfer += oprot->writeI32(this->year); 97 | xfer += oprot->writeFieldEnd(); 98 | 99 | xfer += oprot->writeFieldBegin("month", ::apache::thrift::protocol::T_BYTE, 2); 100 | xfer += oprot->writeByte(this->month); 101 | xfer += oprot->writeFieldEnd(); 102 | 103 | xfer += oprot->writeFieldBegin("day", ::apache::thrift::protocol::T_BYTE, 3); 104 | xfer += oprot->writeByte(this->day); 105 | xfer += oprot->writeFieldEnd(); 106 | 107 | xfer += oprot->writeFieldStop(); 108 | xfer += oprot->writeStructEnd(); 109 | return xfer; 110 | } 111 | 112 | void swap(Date &a, Date &b) { 113 | using ::std::swap; 114 | swap(a.year, b.year); 115 | swap(a.month, b.month); 116 | swap(a.day, b.day); 117 | swap(a.__isset, b.__isset); 118 | } 119 | 120 | Date::Date(const Date& other0) { 121 | year = other0.year; 122 | month = other0.month; 123 | day = other0.day; 124 | __isset = other0.__isset; 125 | } 126 | Date& Date::operator=(const Date& other1) { 127 | year = other1.year; 128 | month = other1.month; 129 | day = other1.day; 130 | __isset = other1.__isset; 131 | return *this; 132 | } 133 | void Date::printTo(std::ostream& out) const { 134 | using ::apache::thrift::to_string; 135 | out << "Date("; 136 | out << "year=" << to_string(year); 137 | out << ", " << "month=" << to_string(month); 138 | out << ", " << "day=" << to_string(day); 139 | out << ")"; 140 | } 141 | 142 | 143 | Address::~Address() throw() { 144 | } 145 | 146 | 147 | void Address::__set_city(const std::string& val) { 148 | this->city = val; 149 | } 150 | 151 | void Address::__set_zipcode(const int32_t val) { 152 | this->zipcode = val; 153 | } 154 | 155 | void Address::__set_street(const std::string& val) { 156 | this->street = val; 157 | } 158 | 159 | void Address::__set_number(const int16_t val) { 160 | this->number = val; 161 | } 162 | 163 | uint32_t Address::read(::apache::thrift::protocol::TProtocol* iprot) { 164 | 165 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 166 | uint32_t xfer = 0; 167 | std::string fname; 168 | ::apache::thrift::protocol::TType ftype; 169 | int16_t fid; 170 | 171 | xfer += iprot->readStructBegin(fname); 172 | 173 | using ::apache::thrift::protocol::TProtocolException; 174 | 175 | 176 | while (true) 177 | { 178 | xfer += iprot->readFieldBegin(fname, ftype, fid); 179 | if (ftype == ::apache::thrift::protocol::T_STOP) { 180 | break; 181 | } 182 | switch (fid) 183 | { 184 | case 1: 185 | if (ftype == ::apache::thrift::protocol::T_STRING) { 186 | xfer += iprot->readString(this->city); 187 | this->__isset.city = true; 188 | } else { 189 | xfer += iprot->skip(ftype); 190 | } 191 | break; 192 | case 2: 193 | if (ftype == ::apache::thrift::protocol::T_I32) { 194 | xfer += iprot->readI32(this->zipcode); 195 | this->__isset.zipcode = true; 196 | } else { 197 | xfer += iprot->skip(ftype); 198 | } 199 | break; 200 | case 3: 201 | if (ftype == ::apache::thrift::protocol::T_STRING) { 202 | xfer += iprot->readString(this->street); 203 | this->__isset.street = true; 204 | } else { 205 | xfer += iprot->skip(ftype); 206 | } 207 | break; 208 | case 4: 209 | if (ftype == ::apache::thrift::protocol::T_I16) { 210 | xfer += iprot->readI16(this->number); 211 | this->__isset.number = true; 212 | } else { 213 | xfer += iprot->skip(ftype); 214 | } 215 | break; 216 | default: 217 | xfer += iprot->skip(ftype); 218 | break; 219 | } 220 | xfer += iprot->readFieldEnd(); 221 | } 222 | 223 | xfer += iprot->readStructEnd(); 224 | 225 | return xfer; 226 | } 227 | 228 | uint32_t Address::write(::apache::thrift::protocol::TProtocol* oprot) const { 229 | uint32_t xfer = 0; 230 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 231 | xfer += oprot->writeStructBegin("Address"); 232 | 233 | xfer += oprot->writeFieldBegin("city", ::apache::thrift::protocol::T_STRING, 1); 234 | xfer += oprot->writeString(this->city); 235 | xfer += oprot->writeFieldEnd(); 236 | 237 | xfer += oprot->writeFieldBegin("zipcode", ::apache::thrift::protocol::T_I32, 2); 238 | xfer += oprot->writeI32(this->zipcode); 239 | xfer += oprot->writeFieldEnd(); 240 | 241 | xfer += oprot->writeFieldBegin("street", ::apache::thrift::protocol::T_STRING, 3); 242 | xfer += oprot->writeString(this->street); 243 | xfer += oprot->writeFieldEnd(); 244 | 245 | xfer += oprot->writeFieldBegin("number", ::apache::thrift::protocol::T_I16, 4); 246 | xfer += oprot->writeI16(this->number); 247 | xfer += oprot->writeFieldEnd(); 248 | 249 | xfer += oprot->writeFieldStop(); 250 | xfer += oprot->writeStructEnd(); 251 | return xfer; 252 | } 253 | 254 | void swap(Address &a, Address &b) { 255 | using ::std::swap; 256 | swap(a.city, b.city); 257 | swap(a.zipcode, b.zipcode); 258 | swap(a.street, b.street); 259 | swap(a.number, b.number); 260 | swap(a.__isset, b.__isset); 261 | } 262 | 263 | Address::Address(const Address& other2) { 264 | city = other2.city; 265 | zipcode = other2.zipcode; 266 | street = other2.street; 267 | number = other2.number; 268 | __isset = other2.__isset; 269 | } 270 | Address& Address::operator=(const Address& other3) { 271 | city = other3.city; 272 | zipcode = other3.zipcode; 273 | street = other3.street; 274 | number = other3.number; 275 | __isset = other3.__isset; 276 | return *this; 277 | } 278 | void Address::printTo(std::ostream& out) const { 279 | using ::apache::thrift::to_string; 280 | out << "Address("; 281 | out << "city=" << to_string(city); 282 | out << ", " << "zipcode=" << to_string(zipcode); 283 | out << ", " << "street=" << to_string(street); 284 | out << ", " << "number=" << to_string(number); 285 | out << ")"; 286 | } 287 | 288 | 289 | School::~School() throw() { 290 | } 291 | 292 | 293 | void School::__set_name(const std::string& val) { 294 | this->name = val; 295 | } 296 | 297 | void School::__set_address(const Address& val) { 298 | this->address = val; 299 | } 300 | 301 | void School::__set_foundation(const Date& val) { 302 | this->foundation = val; 303 | } 304 | 305 | void School::__set_email_addresses(const std::vector & val) { 306 | this->email_addresses = val; 307 | } 308 | 309 | uint32_t School::read(::apache::thrift::protocol::TProtocol* iprot) { 310 | 311 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 312 | uint32_t xfer = 0; 313 | std::string fname; 314 | ::apache::thrift::protocol::TType ftype; 315 | int16_t fid; 316 | 317 | xfer += iprot->readStructBegin(fname); 318 | 319 | using ::apache::thrift::protocol::TProtocolException; 320 | 321 | 322 | while (true) 323 | { 324 | xfer += iprot->readFieldBegin(fname, ftype, fid); 325 | if (ftype == ::apache::thrift::protocol::T_STOP) { 326 | break; 327 | } 328 | switch (fid) 329 | { 330 | case 1: 331 | if (ftype == ::apache::thrift::protocol::T_STRING) { 332 | xfer += iprot->readString(this->name); 333 | this->__isset.name = true; 334 | } else { 335 | xfer += iprot->skip(ftype); 336 | } 337 | break; 338 | case 2: 339 | if (ftype == ::apache::thrift::protocol::T_STRUCT) { 340 | xfer += this->address.read(iprot); 341 | this->__isset.address = true; 342 | } else { 343 | xfer += iprot->skip(ftype); 344 | } 345 | break; 346 | case 3: 347 | if (ftype == ::apache::thrift::protocol::T_STRUCT) { 348 | xfer += this->foundation.read(iprot); 349 | this->__isset.foundation = true; 350 | } else { 351 | xfer += iprot->skip(ftype); 352 | } 353 | break; 354 | case 4: 355 | if (ftype == ::apache::thrift::protocol::T_LIST) { 356 | { 357 | this->email_addresses.clear(); 358 | uint32_t _size4; 359 | ::apache::thrift::protocol::TType _etype7; 360 | xfer += iprot->readListBegin(_etype7, _size4); 361 | this->email_addresses.resize(_size4); 362 | uint32_t _i8; 363 | for (_i8 = 0; _i8 < _size4; ++_i8) 364 | { 365 | xfer += iprot->readString(this->email_addresses[_i8]); 366 | } 367 | xfer += iprot->readListEnd(); 368 | } 369 | this->__isset.email_addresses = true; 370 | } else { 371 | xfer += iprot->skip(ftype); 372 | } 373 | break; 374 | default: 375 | xfer += iprot->skip(ftype); 376 | break; 377 | } 378 | xfer += iprot->readFieldEnd(); 379 | } 380 | 381 | xfer += iprot->readStructEnd(); 382 | 383 | return xfer; 384 | } 385 | 386 | uint32_t School::write(::apache::thrift::protocol::TProtocol* oprot) const { 387 | uint32_t xfer = 0; 388 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 389 | xfer += oprot->writeStructBegin("School"); 390 | 391 | xfer += oprot->writeFieldBegin("name", ::apache::thrift::protocol::T_STRING, 1); 392 | xfer += oprot->writeString(this->name); 393 | xfer += oprot->writeFieldEnd(); 394 | 395 | xfer += oprot->writeFieldBegin("address", ::apache::thrift::protocol::T_STRUCT, 2); 396 | xfer += this->address.write(oprot); 397 | xfer += oprot->writeFieldEnd(); 398 | 399 | xfer += oprot->writeFieldBegin("foundation", ::apache::thrift::protocol::T_STRUCT, 3); 400 | xfer += this->foundation.write(oprot); 401 | xfer += oprot->writeFieldEnd(); 402 | 403 | xfer += oprot->writeFieldBegin("email_addresses", ::apache::thrift::protocol::T_LIST, 4); 404 | { 405 | xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->email_addresses.size())); 406 | std::vector ::const_iterator _iter9; 407 | for (_iter9 = this->email_addresses.begin(); _iter9 != this->email_addresses.end(); ++_iter9) 408 | { 409 | xfer += oprot->writeString((*_iter9)); 410 | } 411 | xfer += oprot->writeListEnd(); 412 | } 413 | xfer += oprot->writeFieldEnd(); 414 | 415 | xfer += oprot->writeFieldStop(); 416 | xfer += oprot->writeStructEnd(); 417 | return xfer; 418 | } 419 | 420 | void swap(School &a, School &b) { 421 | using ::std::swap; 422 | swap(a.name, b.name); 423 | swap(a.address, b.address); 424 | swap(a.foundation, b.foundation); 425 | swap(a.email_addresses, b.email_addresses); 426 | swap(a.__isset, b.__isset); 427 | } 428 | 429 | School::School(const School& other10) { 430 | name = other10.name; 431 | address = other10.address; 432 | foundation = other10.foundation; 433 | email_addresses = other10.email_addresses; 434 | __isset = other10.__isset; 435 | } 436 | School& School::operator=(const School& other11) { 437 | name = other11.name; 438 | address = other11.address; 439 | foundation = other11.foundation; 440 | email_addresses = other11.email_addresses; 441 | __isset = other11.__isset; 442 | return *this; 443 | } 444 | void School::printTo(std::ostream& out) const { 445 | using ::apache::thrift::to_string; 446 | out << "School("; 447 | out << "name=" << to_string(name); 448 | out << ", " << "address=" << to_string(address); 449 | out << ", " << "foundation=" << to_string(foundation); 450 | out << ", " << "email_addresses=" << to_string(email_addresses); 451 | out << ")"; 452 | } 453 | 454 | 455 | Subject::~Subject() throw() { 456 | } 457 | 458 | 459 | void Subject::__set_id(const int32_t val) { 460 | this->id = val; 461 | } 462 | 463 | void Subject::__set_title(const std::string& val) { 464 | this->title = val; 465 | } 466 | 467 | void Subject::__set_code(const std::string& val) { 468 | this->code = val; 469 | } 470 | 471 | uint32_t Subject::read(::apache::thrift::protocol::TProtocol* iprot) { 472 | 473 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 474 | uint32_t xfer = 0; 475 | std::string fname; 476 | ::apache::thrift::protocol::TType ftype; 477 | int16_t fid; 478 | 479 | xfer += iprot->readStructBegin(fname); 480 | 481 | using ::apache::thrift::protocol::TProtocolException; 482 | 483 | 484 | while (true) 485 | { 486 | xfer += iprot->readFieldBegin(fname, ftype, fid); 487 | if (ftype == ::apache::thrift::protocol::T_STOP) { 488 | break; 489 | } 490 | switch (fid) 491 | { 492 | case 1: 493 | if (ftype == ::apache::thrift::protocol::T_I32) { 494 | xfer += iprot->readI32(this->id); 495 | this->__isset.id = true; 496 | } else { 497 | xfer += iprot->skip(ftype); 498 | } 499 | break; 500 | case 2: 501 | if (ftype == ::apache::thrift::protocol::T_STRING) { 502 | xfer += iprot->readString(this->title); 503 | this->__isset.title = true; 504 | } else { 505 | xfer += iprot->skip(ftype); 506 | } 507 | break; 508 | case 3: 509 | if (ftype == ::apache::thrift::protocol::T_STRING) { 510 | xfer += iprot->readString(this->code); 511 | this->__isset.code = true; 512 | } else { 513 | xfer += iprot->skip(ftype); 514 | } 515 | break; 516 | default: 517 | xfer += iprot->skip(ftype); 518 | break; 519 | } 520 | xfer += iprot->readFieldEnd(); 521 | } 522 | 523 | xfer += iprot->readStructEnd(); 524 | 525 | return xfer; 526 | } 527 | 528 | uint32_t Subject::write(::apache::thrift::protocol::TProtocol* oprot) const { 529 | uint32_t xfer = 0; 530 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 531 | xfer += oprot->writeStructBegin("Subject"); 532 | 533 | xfer += oprot->writeFieldBegin("id", ::apache::thrift::protocol::T_I32, 1); 534 | xfer += oprot->writeI32(this->id); 535 | xfer += oprot->writeFieldEnd(); 536 | 537 | xfer += oprot->writeFieldBegin("title", ::apache::thrift::protocol::T_STRING, 2); 538 | xfer += oprot->writeString(this->title); 539 | xfer += oprot->writeFieldEnd(); 540 | 541 | xfer += oprot->writeFieldBegin("code", ::apache::thrift::protocol::T_STRING, 3); 542 | xfer += oprot->writeString(this->code); 543 | xfer += oprot->writeFieldEnd(); 544 | 545 | xfer += oprot->writeFieldStop(); 546 | xfer += oprot->writeStructEnd(); 547 | return xfer; 548 | } 549 | 550 | void swap(Subject &a, Subject &b) { 551 | using ::std::swap; 552 | swap(a.id, b.id); 553 | swap(a.title, b.title); 554 | swap(a.code, b.code); 555 | swap(a.__isset, b.__isset); 556 | } 557 | 558 | Subject::Subject(const Subject& other12) { 559 | id = other12.id; 560 | title = other12.title; 561 | code = other12.code; 562 | __isset = other12.__isset; 563 | } 564 | Subject& Subject::operator=(const Subject& other13) { 565 | id = other13.id; 566 | title = other13.title; 567 | code = other13.code; 568 | __isset = other13.__isset; 569 | return *this; 570 | } 571 | void Subject::printTo(std::ostream& out) const { 572 | using ::apache::thrift::to_string; 573 | out << "Subject("; 574 | out << "id=" << to_string(id); 575 | out << ", " << "title=" << to_string(title); 576 | out << ", " << "code=" << to_string(code); 577 | out << ")"; 578 | } 579 | 580 | 581 | Student::~Student() throw() { 582 | } 583 | 584 | 585 | void Student::__set_name(const std::string& val) { 586 | this->name = val; 587 | } 588 | 589 | void Student::__set_friends(const int32_t val) { 590 | this->friends = val; 591 | } 592 | 593 | void Student::__set_home_address(const Address& val) { 594 | this->home_address = val; 595 | } 596 | 597 | void Student::__set_birth_place(const Address& val) { 598 | this->birth_place = val; 599 | } 600 | 601 | void Student::__set_birth(const Date& val) { 602 | this->birth = val; 603 | } 604 | 605 | void Student::__set_favorite_subjects(const std::vector & val) { 606 | this->favorite_subjects = val; 607 | } 608 | 609 | void Student::__set_email_addresses(const std::vector & val) { 610 | this->email_addresses = val; 611 | } 612 | 613 | void Student::__set_schools(const std::vector & val) { 614 | this->schools = val; 615 | } 616 | 617 | uint32_t Student::read(::apache::thrift::protocol::TProtocol* iprot) { 618 | 619 | apache::thrift::protocol::TInputRecursionTracker tracker(*iprot); 620 | uint32_t xfer = 0; 621 | std::string fname; 622 | ::apache::thrift::protocol::TType ftype; 623 | int16_t fid; 624 | 625 | xfer += iprot->readStructBegin(fname); 626 | 627 | using ::apache::thrift::protocol::TProtocolException; 628 | 629 | 630 | while (true) 631 | { 632 | xfer += iprot->readFieldBegin(fname, ftype, fid); 633 | if (ftype == ::apache::thrift::protocol::T_STOP) { 634 | break; 635 | } 636 | switch (fid) 637 | { 638 | case 1: 639 | if (ftype == ::apache::thrift::protocol::T_STRING) { 640 | xfer += iprot->readString(this->name); 641 | this->__isset.name = true; 642 | } else { 643 | xfer += iprot->skip(ftype); 644 | } 645 | break; 646 | case 2: 647 | if (ftype == ::apache::thrift::protocol::T_I32) { 648 | xfer += iprot->readI32(this->friends); 649 | this->__isset.friends = true; 650 | } else { 651 | xfer += iprot->skip(ftype); 652 | } 653 | break; 654 | case 3: 655 | if (ftype == ::apache::thrift::protocol::T_STRUCT) { 656 | xfer += this->home_address.read(iprot); 657 | this->__isset.home_address = true; 658 | } else { 659 | xfer += iprot->skip(ftype); 660 | } 661 | break; 662 | case 4: 663 | if (ftype == ::apache::thrift::protocol::T_STRUCT) { 664 | xfer += this->birth_place.read(iprot); 665 | this->__isset.birth_place = true; 666 | } else { 667 | xfer += iprot->skip(ftype); 668 | } 669 | break; 670 | case 5: 671 | if (ftype == ::apache::thrift::protocol::T_STRUCT) { 672 | xfer += this->birth.read(iprot); 673 | this->__isset.birth = true; 674 | } else { 675 | xfer += iprot->skip(ftype); 676 | } 677 | break; 678 | case 6: 679 | if (ftype == ::apache::thrift::protocol::T_LIST) { 680 | { 681 | this->favorite_subjects.clear(); 682 | uint32_t _size14; 683 | ::apache::thrift::protocol::TType _etype17; 684 | xfer += iprot->readListBegin(_etype17, _size14); 685 | this->favorite_subjects.resize(_size14); 686 | uint32_t _i18; 687 | for (_i18 = 0; _i18 < _size14; ++_i18) 688 | { 689 | xfer += this->favorite_subjects[_i18].read(iprot); 690 | } 691 | xfer += iprot->readListEnd(); 692 | } 693 | this->__isset.favorite_subjects = true; 694 | } else { 695 | xfer += iprot->skip(ftype); 696 | } 697 | break; 698 | case 7: 699 | if (ftype == ::apache::thrift::protocol::T_LIST) { 700 | { 701 | this->email_addresses.clear(); 702 | uint32_t _size19; 703 | ::apache::thrift::protocol::TType _etype22; 704 | xfer += iprot->readListBegin(_etype22, _size19); 705 | this->email_addresses.resize(_size19); 706 | uint32_t _i23; 707 | for (_i23 = 0; _i23 < _size19; ++_i23) 708 | { 709 | xfer += iprot->readString(this->email_addresses[_i23]); 710 | } 711 | xfer += iprot->readListEnd(); 712 | } 713 | this->__isset.email_addresses = true; 714 | } else { 715 | xfer += iprot->skip(ftype); 716 | } 717 | break; 718 | case 8: 719 | if (ftype == ::apache::thrift::protocol::T_LIST) { 720 | { 721 | this->schools.clear(); 722 | uint32_t _size24; 723 | ::apache::thrift::protocol::TType _etype27; 724 | xfer += iprot->readListBegin(_etype27, _size24); 725 | this->schools.resize(_size24); 726 | uint32_t _i28; 727 | for (_i28 = 0; _i28 < _size24; ++_i28) 728 | { 729 | xfer += this->schools[_i28].read(iprot); 730 | } 731 | xfer += iprot->readListEnd(); 732 | } 733 | this->__isset.schools = true; 734 | } else { 735 | xfer += iprot->skip(ftype); 736 | } 737 | break; 738 | default: 739 | xfer += iprot->skip(ftype); 740 | break; 741 | } 742 | xfer += iprot->readFieldEnd(); 743 | } 744 | 745 | xfer += iprot->readStructEnd(); 746 | 747 | return xfer; 748 | } 749 | 750 | uint32_t Student::write(::apache::thrift::protocol::TProtocol* oprot) const { 751 | uint32_t xfer = 0; 752 | apache::thrift::protocol::TOutputRecursionTracker tracker(*oprot); 753 | xfer += oprot->writeStructBegin("Student"); 754 | 755 | xfer += oprot->writeFieldBegin("name", ::apache::thrift::protocol::T_STRING, 1); 756 | xfer += oprot->writeString(this->name); 757 | xfer += oprot->writeFieldEnd(); 758 | 759 | xfer += oprot->writeFieldBegin("friends", ::apache::thrift::protocol::T_I32, 2); 760 | xfer += oprot->writeI32(this->friends); 761 | xfer += oprot->writeFieldEnd(); 762 | 763 | xfer += oprot->writeFieldBegin("home_address", ::apache::thrift::protocol::T_STRUCT, 3); 764 | xfer += this->home_address.write(oprot); 765 | xfer += oprot->writeFieldEnd(); 766 | 767 | xfer += oprot->writeFieldBegin("birth_place", ::apache::thrift::protocol::T_STRUCT, 4); 768 | xfer += this->birth_place.write(oprot); 769 | xfer += oprot->writeFieldEnd(); 770 | 771 | xfer += oprot->writeFieldBegin("birth", ::apache::thrift::protocol::T_STRUCT, 5); 772 | xfer += this->birth.write(oprot); 773 | xfer += oprot->writeFieldEnd(); 774 | 775 | xfer += oprot->writeFieldBegin("favorite_subjects", ::apache::thrift::protocol::T_LIST, 6); 776 | { 777 | xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->favorite_subjects.size())); 778 | std::vector ::const_iterator _iter29; 779 | for (_iter29 = this->favorite_subjects.begin(); _iter29 != this->favorite_subjects.end(); ++_iter29) 780 | { 781 | xfer += (*_iter29).write(oprot); 782 | } 783 | xfer += oprot->writeListEnd(); 784 | } 785 | xfer += oprot->writeFieldEnd(); 786 | 787 | xfer += oprot->writeFieldBegin("email_addresses", ::apache::thrift::protocol::T_LIST, 7); 788 | { 789 | xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRING, static_cast(this->email_addresses.size())); 790 | std::vector ::const_iterator _iter30; 791 | for (_iter30 = this->email_addresses.begin(); _iter30 != this->email_addresses.end(); ++_iter30) 792 | { 793 | xfer += oprot->writeString((*_iter30)); 794 | } 795 | xfer += oprot->writeListEnd(); 796 | } 797 | xfer += oprot->writeFieldEnd(); 798 | 799 | xfer += oprot->writeFieldBegin("schools", ::apache::thrift::protocol::T_LIST, 8); 800 | { 801 | xfer += oprot->writeListBegin(::apache::thrift::protocol::T_STRUCT, static_cast(this->schools.size())); 802 | std::vector ::const_iterator _iter31; 803 | for (_iter31 = this->schools.begin(); _iter31 != this->schools.end(); ++_iter31) 804 | { 805 | xfer += (*_iter31).write(oprot); 806 | } 807 | xfer += oprot->writeListEnd(); 808 | } 809 | xfer += oprot->writeFieldEnd(); 810 | 811 | xfer += oprot->writeFieldStop(); 812 | xfer += oprot->writeStructEnd(); 813 | return xfer; 814 | } 815 | 816 | void swap(Student &a, Student &b) { 817 | using ::std::swap; 818 | swap(a.name, b.name); 819 | swap(a.friends, b.friends); 820 | swap(a.home_address, b.home_address); 821 | swap(a.birth_place, b.birth_place); 822 | swap(a.birth, b.birth); 823 | swap(a.favorite_subjects, b.favorite_subjects); 824 | swap(a.email_addresses, b.email_addresses); 825 | swap(a.schools, b.schools); 826 | swap(a.__isset, b.__isset); 827 | } 828 | 829 | Student::Student(const Student& other32) { 830 | name = other32.name; 831 | friends = other32.friends; 832 | home_address = other32.home_address; 833 | birth_place = other32.birth_place; 834 | birth = other32.birth; 835 | favorite_subjects = other32.favorite_subjects; 836 | email_addresses = other32.email_addresses; 837 | schools = other32.schools; 838 | __isset = other32.__isset; 839 | } 840 | Student& Student::operator=(const Student& other33) { 841 | name = other33.name; 842 | friends = other33.friends; 843 | home_address = other33.home_address; 844 | birth_place = other33.birth_place; 845 | birth = other33.birth; 846 | favorite_subjects = other33.favorite_subjects; 847 | email_addresses = other33.email_addresses; 848 | schools = other33.schools; 849 | __isset = other33.__isset; 850 | return *this; 851 | } 852 | void Student::printTo(std::ostream& out) const { 853 | using ::apache::thrift::to_string; 854 | out << "Student("; 855 | out << "name=" << to_string(name); 856 | out << ", " << "friends=" << to_string(friends); 857 | out << ", " << "home_address=" << to_string(home_address); 858 | out << ", " << "birth_place=" << to_string(birth_place); 859 | out << ", " << "birth=" << to_string(birth); 860 | out << ", " << "favorite_subjects=" << to_string(favorite_subjects); 861 | out << ", " << "email_addresses=" << to_string(email_addresses); 862 | out << ", " << "schools=" << to_string(schools); 863 | out << ")"; 864 | } 865 | 866 | } // namespace 867 | --------------------------------------------------------------------------------