Repository: kudu
Updated Branches:
  refs/heads/master 2bff29b59 -> bf6c2c07b


jsonwriter: small optimization for PB fields

This avoids extra non-inlinable calls into the protobuf library:
- extra calls to GetReflection()
- calls to FieldSize() while looping through repeated fields

This has a small benefit on all PBs and a big benefit on those PBs with
a lot of repeated fields. The latter should be a nice boost particularly
when serializing metrics.

Before:
TestJsonWriter.BenchmarkAllTypes      Throughput: 157.609MB/sec
TestJsonWriter.BenchmarkNestedMessage Throughput: 124.048MB/sec
TestJsonWriter.BenchmarkRepeatedInt64 Throughput: 113.77MB/sec

After:
TestJsonWriter.BenchmarkAllTypes      Throughput: 163.327MB/sec  (+3.6%)
TestJsonWriter.BenchmarkNestedMessage Throughput: 127.633MB/sec  (+2.9%)
TestJsonWriter.BenchmarkRepeatedInt64 Throughput: 158.229MB/sec  (+39.1%)

Change-Id: Iceee0096a3af9300fca3dd18508a12e140e99b31
Reviewed-on: http://gerrit.cloudera.org:8080/9184
Reviewed-by: Sailesh Mukil <sail...@cloudera.com>
Tested-by: Kudu Jenkins
Reviewed-by: Todd Lipcon <t...@apache.org>


Project: http://git-wip-us.apache.org/repos/asf/kudu/repo
Commit: http://git-wip-us.apache.org/repos/asf/kudu/commit/f27f5ada
Tree: http://git-wip-us.apache.org/repos/asf/kudu/tree/f27f5ada
Diff: http://git-wip-us.apache.org/repos/asf/kudu/diff/f27f5ada

Branch: refs/heads/master
Commit: f27f5adaedabf5aac53583a2cd425c6a38484b78
Parents: 2bff29b
Author: Todd Lipcon <t...@apache.org>
Authored: Thu Feb 1 14:57:36 2018 -0800
Committer: Todd Lipcon <t...@apache.org>
Committed: Sat Feb 3 01:53:02 2018 +0000

----------------------------------------------------------------------
 src/kudu/util/jsonwriter-test.cc | 27 ++++++++++++++++++++++++---
 src/kudu/util/jsonwriter.cc      | 15 ++++++++-------
 src/kudu/util/jsonwriter.h       |  5 ++++-
 3 files changed, 36 insertions(+), 11 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/kudu/blob/f27f5ada/src/kudu/util/jsonwriter-test.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/jsonwriter-test.cc b/src/kudu/util/jsonwriter-test.cc
index 608d9c0..6f9b10d 100644
--- a/src/kudu/util/jsonwriter-test.cc
+++ b/src/kudu/util/jsonwriter-test.cc
@@ -29,12 +29,17 @@
 #include "kudu/util/stopwatch.h"
 #include "kudu/util/test_util.h"
 
+namespace google { namespace protobuf { class Message; } }
+
+using google::protobuf::Message;
 using jsonwriter_test::TestAllTypes;
 
 namespace kudu {
 
 class TestJsonWriter : public KuduTest {
  protected:
+  void DoBenchmark(const Message& pb);
+
   TestAllTypes MakeAllTypesPB() {
     TestAllTypes pb;
     pb.set_optional_int32(1);
@@ -170,9 +175,7 @@ TEST_F(TestJsonWriter, TestPBNestedMessage) {
             JsonWriter::ToJson(pb, JsonWriter::COMPACT));
 }
 
-TEST_F(TestJsonWriter, Benchmark) {
-  TestAllTypes pb = MakeAllTypesPB();
-
+void TestJsonWriter::DoBenchmark(const Message& pb) {
   int64_t total_len = 0;
   Stopwatch sw;
   sw.start();
@@ -191,5 +194,23 @@ TEST_F(TestJsonWriter, Benchmark) {
   LOG(INFO) << "Throughput: " << mbps << "MB/sec";
 }
 
+TEST_F(TestJsonWriter, BenchmarkAllTypes) {
+  DoBenchmark(MakeAllTypesPB());
+}
+
+TEST_F(TestJsonWriter, BenchmarkNestedMessage) {
+  TestAllTypes pb;
+  pb.add_repeated_nested_message()->set_int_field(12345);
+  pb.mutable_optional_nested_message()->set_int_field(54321);
+  DoBenchmark(pb);
+}
+
+TEST_F(TestJsonWriter, BenchmarkRepeatedInt64) {
+  TestAllTypes pb;
+  for (int i = 0; i < 10000; i++) {
+    pb.add_repeated_int64(i);
+  }
+  DoBenchmark(pb);
+}
 
 } // namespace kudu

http://git-wip-us.apache.org/repos/asf/kudu/blob/f27f5ada/src/kudu/util/jsonwriter.cc
----------------------------------------------------------------------
diff --git a/src/kudu/util/jsonwriter.cc b/src/kudu/util/jsonwriter.cc
index f194d5b..3a5580c 100644
--- a/src/kudu/util/jsonwriter.cc
+++ b/src/kudu/util/jsonwriter.cc
@@ -188,19 +188,20 @@ void JsonWriter::Protobuf(const Message& pb) {
     String(field->name());
     if (field->is_repeated()) {
       StartArray();
-      for (int i = 0; i < reflection->FieldSize(pb, field); i++) {
-        ProtobufRepeatedField(pb, field, i);
+      int size = reflection->FieldSize(pb, field);
+      for (int i = 0; i < size; i++) {
+        ProtobufRepeatedField(pb, reflection, field, i);
       }
       EndArray();
     } else {
-      ProtobufField(pb, field);
+      ProtobufField(pb, reflection, field);
     }
   }
   EndObject();
 }
 
-void JsonWriter::ProtobufField(const Message& pb, const FieldDescriptor* 
field) {
-  const Reflection* reflection = pb.GetReflection();
+void JsonWriter::ProtobufField(const Message& pb, const Reflection* reflection,
+                               const FieldDescriptor* field) {
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
       Int(reflection->GetInt32(pb, field));
@@ -238,8 +239,8 @@ void JsonWriter::ProtobufField(const Message& pb, const 
FieldDescriptor* field)
   }
 }
 
-void JsonWriter::ProtobufRepeatedField(const Message& pb, const 
FieldDescriptor* field, int index) {
-  const Reflection* reflection = pb.GetReflection();
+void JsonWriter::ProtobufRepeatedField(const Message& pb, const Reflection* 
reflection,
+                                       const FieldDescriptor* field, int 
index) {
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
       Int(reflection->GetRepeatedInt32(pb, field, index));

http://git-wip-us.apache.org/repos/asf/kudu/blob/f27f5ada/src/kudu/util/jsonwriter.h
----------------------------------------------------------------------
diff --git a/src/kudu/util/jsonwriter.h b/src/kudu/util/jsonwriter.h
index 860bfaa..24b4575 100644
--- a/src/kudu/util/jsonwriter.h
+++ b/src/kudu/util/jsonwriter.h
@@ -27,8 +27,9 @@
 
 namespace google {
 namespace protobuf {
-class Message;
 class FieldDescriptor;
+class Message;
+class Reflection;
 } // namespace protobuf
 } // namespace google
 
@@ -85,8 +86,10 @@ class JsonWriter {
 
  private:
   void ProtobufField(const google::protobuf::Message& pb,
+                     const google::protobuf::Reflection* reflection,
                      const google::protobuf::FieldDescriptor* field);
   void ProtobufRepeatedField(const google::protobuf::Message& pb,
+                             const google::protobuf::Reflection* reflection,
                              const google::protobuf::FieldDescriptor* field,
                              int index);
 

Reply via email to