Last active
August 29, 2015 14:00
-
-
Save stepancheg/11333310 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
extern crate protobuf; | #include <iostream> | |
extern crate rand; | #include <fstream> | |
extern crate time; | #include <random> | |
| #include <sstream> | |
use std::io::File; | #include <chrono> | |
use std::io::MemWriter; | | |
use std::io::BufReader; | #include <google/protobuf/message.h> | |
use std::default::Default; | #include <google/protobuf/io/zero_copy_stream_impl.h> | |
| | |
use rand::Rng; | #include <stdio.h> | |
use rand::StdRng; | | |
use rand::SeedableRng; | #include "perftest_data.pb.h" | |
| | |
use protobuf::Message; | | |
use perftest_data::PerftestData; | using namespace google::protobuf; | |
| using namespace google::protobuf::io; | |
mod perftest_data; | | |
| | |
| #define FAIL(msg) do { \ | |
| fprintf(stderr, "FAIL: %s\n", msg); exit(1); \ | |
| } while (0) | |
| #define VERIFY(param) do { \ | |
| if (!(param)) FAIL(#param); \ | |
| } while(0) | |
| | |
| | |
| template <typename TFunc> | |
fn measure_ns<R>(f: || -> R) -> (u64, R) { | uint64_t measure_ns(TFunc func) { | |
let start = time::precise_time_ns(); | auto start = std::chrono::system_clock::now(); | |
let r = f(); | func(); | |
(time::precise_time_ns() - start, r) | auto end = std::chrono::system_clock::now(); | |
| return std::chrono::duration_cast< | |
| std::chrono::nanoseconds>(end - start).count(); | |
} | } | |
| | |
| template <typename TFunc> | |
fn measure_print<R>(title: &str, iter: u64, f: || -> R) -> R { | void measure_print(const std::string& name, unsigned iter, TFunc fun | |
let (ns, r) = measure_ns(f); | auto ns = measure_ns(func); | |
let ns_per_iter = ns / iter; | auto ns_per_iter = ns / iter; | |
println!("{}: {} ns per iter", title, ns_per_iter); | printf("%s: %u ns per iter\n", | |
r | name.c_str(), (unsigned) ns_per_iter); | |
} | } | |
| | |
| template <typename M> | |
fn test<M : Message>(name: &str, data: &[M]) { | void test(const char* name, const RepeatedPtrField<M>& data) { | |
let mut rng: StdRng = SeedableRng::from_seed(&[10, 20]); | std::mt19937 rng; | |
| std::uniform_int_distribution<std::mt19937::result_type> | |
| dist(0, data.size() - 1); | |
| | |
let mut random_data: Vec<M> = Vec::new(); | RepeatedPtrField<M> randomData; | |
| | |
let mut total_size = 0; | auto totalSize = 0; | |
while total_size < 1000000 { | while (totalSize < 1000000) { | |
let ref item = data[rng.gen_range(0, data.len())]; | const auto& item = data.Get(dist(rng)); | |
random_data.push(item.clone()); | *randomData.Add() = item; | |
total_size += item.serialized_size(); | totalSize += item.ByteSize(); | |
} | } | |
| | |
let mut writer = MemWriter::new(); | std::string s; | |
measure_print( | measure_print( | |
format!("{}: write", name), | std::string() + name + " write", | |
random_data.len() as u64, | randomData.size(), | |
|| { | [&] () { | |
| StringOutputStream ss(&s); | |
| CodedOutputStream os(&ss); | |
for m in random_data.iter() { | for (int i = 0; i < randomData.size(); ++i) { | |
m.write_length_delimited_to_writer(&mut writer); | auto size = randomData.Get(i).ByteSize(); | |
| os.WriteVarint32(size); | |
| randomData.Get(i).SerializeWithCachedSizes(&os); | |
} | } | |
}); | }); | |
| | |
let buf = writer.unwrap(); | RepeatedPtrField<M> readData; | |
| | |
let read_data = measure_print( | measure_print( | |
format!("{}: read", name), | std::string() + name + " read", | |
random_data.len() as u64, | randomData.size(), | |
|| { | [&] () { | |
let mut r = Vec::new(); | CodedInputStream is((const uint8*) s.data(), s.size()); | |
let mut reader = BufReader::new(buf.as_slice()); | while (is.BytesUntilLimit() > 0) { | |
let mut coded_input_stream = | uint32 length; | |
protobuf::CodedInputStream::new(&mut reader); | bool okLength = is.ReadVarint32(&length); | |
while !coded_input_stream.eof() { | while (is.BytesUntilLimit() > 0) { | |
r.push(protobuf::parse_length_delimited_from::<M>( | uint32 length; | |
&mut coded_input_stream)); | bool okLength = is.ReadVarint32(&length); | |
| VERIFY(okLength); | |
| auto oldLimit = is.PushLimit(length); | |
| bool okReadMsg = readData.Add() | |
| ->MergeFromCodedStream(&is); | |
| VERIFY(okReadMsg); | |
| is.PopLimit(oldLimit); | |
} | } | |
r | | |
}); | }); | |
| | |
| // TODO: compare content | |
assert_eq!(random_data, read_data); | VERIFY(randomData.size() == readData.size()); | |
| | |
| auto count = 0; | |
let merged = measure_print( | measure_print( | |
format!("{}: read reuse", name), | std::string() + name + " read reuse", | |
random_data.len() as u64, | randomData.size(), | |
|| { | [&] () { | |
let mut reader = BufReader::new(buf.as_slice()); | M msg; | |
let mut coded_input_stream = | CodedInputStream is((const uint8*) s.data(), s.size()); | |
protobuf::CodedInputStream::new(&mut reader); | | |
let mut msg: M = Default::default(); | | |
let mut count = 0; | | |
while !coded_input_stream.eof() { | while (is.BytesUntilLimit() > 0) { | |
msg.clear(); | msg.Clear(); | |
coded_input_stream.merge_message(&mut msg); | uint32 length; | |
| bool okLength = is.ReadVarint32(&length); | |
| VERIFY(okLength); | |
| auto oldLimit = is.PushLimit(length); | |
| bool okReadMsg = msg.MergeFromCodedStream(&is); | |
| VERIFY(okReadMsg); | |
| is.PopLimit(oldLimit); | |
count += 1; | count += 1; | |
} | } | |
count | | |
}); | }); | |
| | |
assert_eq!(random_data.len(), merged); | VERIFY(randomData.size() == count); | |
} | } | |
| | |
fn main() { | int main() { | |
let mut is = File::open(&Path::new("perftest_data.pbbin")); | std::ifstream is("perftest_data.pbbin"); | |
let perftest_data = | PerftestData perftestData; | |
protobuf::parse_from_reader::<PerftestData>(&mut is); | bool ok = perftestData.ParsePartialFromIstream(&is); | |
| VERIFY(ok); | |
test("test1", | test("test1", | |
perftest_data.get_test1()); | perftestData.test1()); | |
test("test_repeated_bool", | test("test_repeated_bool", | |
perftest_data.get_test_repeated_bool()); | perftestData.test_repeated_bool()); | |
test("test_messages_of_messages", | test("test_messages_of_messages", | |
perftest_data.get_test_messages_of_messages()); | perftestData.test_messages_of_messages()); | |
| return 0; | |
} | } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment