-
Notifications
You must be signed in to change notification settings - Fork 15.6k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #4478 from BSBandme/proto2_to_proto3_tools
Add gogo benchmark
- Loading branch information
Showing
6 changed files
with
584 additions
and
53 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
Empty file.
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,105 @@ | ||
#include "benchmarks.pb.h" | ||
#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h" | ||
#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h" | ||
#include "datasets/google_message2/benchmark_message2.pb.h" | ||
#include "datasets/google_message3/benchmark_message3.pb.h" | ||
#include "datasets/google_message4/benchmark_message4.pb.h" | ||
|
||
#include "google/protobuf/message.h" | ||
#include "google/protobuf/descriptor.h" | ||
|
||
#include <fstream> | ||
|
||
using google::protobuf::FieldDescriptor; | ||
using google::protobuf::Message; | ||
using google::protobuf::Reflection; | ||
|
||
|
||
class DataGroupStripper { | ||
public: | ||
static void StripMessage(Message *message) { | ||
std::vector<const FieldDescriptor*> set_fields; | ||
const Reflection* reflection = message->GetReflection(); | ||
reflection->ListFields(*message, &set_fields); | ||
|
||
for (size_t i = 0; i < set_fields.size(); i++) { | ||
const FieldDescriptor* field = set_fields[i]; | ||
if (field->type() == FieldDescriptor::TYPE_GROUP) { | ||
reflection->ClearField(message, field); | ||
} | ||
if (field->type() == FieldDescriptor::TYPE_MESSAGE) { | ||
if (field->is_repeated()) { | ||
for (int j = 0; j < reflection->FieldSize(*message, field); j++) { | ||
StripMessage(reflection->MutableRepeatedMessage(message, field, j)); | ||
} | ||
} else { | ||
StripMessage(reflection->MutableMessage(message, field)); | ||
} | ||
} | ||
} | ||
|
||
reflection->MutableUnknownFields(message)->Clear(); | ||
} | ||
}; | ||
|
||
std::string ReadFile(const std::string& name) { | ||
std::ifstream file(name.c_str()); | ||
GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" | ||
<< name | ||
<< "', please make sure you are running this command from the benchmarks" | ||
<< " directory.\n"; | ||
return std::string((std::istreambuf_iterator<char>(file)), | ||
std::istreambuf_iterator<char>()); | ||
} | ||
|
||
int main(int argc, char *argv[]) { | ||
if (argc % 2 == 0 || argc == 1) { | ||
std::cerr << "Usage: [input_files] [output_file_names] where " << | ||
"input_files are one to one mapping to output_file_names." << | ||
std::endl; | ||
return 1; | ||
} | ||
|
||
for (int i = argc / 2; i > 0; i--) { | ||
const std::string &input_file = argv[i]; | ||
const std::string &output_file = argv[i + argc / 2]; | ||
|
||
std::cerr << "Generating " << input_file | ||
<< " to " << output_file << std::endl; | ||
benchmarks::BenchmarkDataset dataset; | ||
Message* message; | ||
std::string dataset_payload = ReadFile(input_file); | ||
GOOGLE_CHECK(dataset.ParseFromString(dataset_payload)) | ||
<< "Can' t parse data file " << input_file; | ||
|
||
if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") { | ||
message = new benchmarks::proto3::GoogleMessage1; | ||
} else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") { | ||
message = new benchmarks::proto2::GoogleMessage1; | ||
} else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") { | ||
message = new benchmarks::proto2::GoogleMessage2; | ||
} else if (dataset.message_name() == | ||
"benchmarks.google_message3.GoogleMessage3") { | ||
message = new benchmarks::google_message3::GoogleMessage3; | ||
} else if (dataset.message_name() == | ||
"benchmarks.google_message4.GoogleMessage4") { | ||
message = new benchmarks::google_message4::GoogleMessage4; | ||
} else { | ||
std::cerr << "Unknown message type: " << dataset.message_name(); | ||
exit(1); | ||
} | ||
|
||
for (int i = 0; i < dataset.payload_size(); i++) { | ||
message->ParseFromString(dataset.payload(i)); | ||
DataGroupStripper::StripMessage(message); | ||
dataset.set_payload(i, message->SerializeAsString()); | ||
} | ||
|
||
std::ofstream ofs(output_file); | ||
ofs << dataset.SerializeAsString(); | ||
ofs.close(); | ||
} | ||
|
||
|
||
return 0; | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,103 @@ | ||
#include "google/protobuf/compiler/code_generator.h" | ||
#include "google/protobuf/io/zero_copy_stream.h" | ||
#include "google/protobuf/io/printer.h" | ||
#include "google/protobuf/descriptor.h" | ||
#include "google/protobuf/descriptor.pb.h" | ||
#include "schema_proto2_to_proto3_util.h" | ||
|
||
#include "google/protobuf/compiler/plugin.h" | ||
|
||
using google::protobuf::FileDescriptorProto; | ||
using google::protobuf::FileDescriptor; | ||
using google::protobuf::DescriptorPool; | ||
using google::protobuf::io::Printer; | ||
using google::protobuf::util::SchemaGroupStripper; | ||
using google::protobuf::util::SchemaAddZeroEnumValue; | ||
|
||
namespace google { | ||
namespace protobuf { | ||
namespace compiler { | ||
|
||
namespace { | ||
|
||
string StripProto(string filename) { | ||
if (filename.substr(filename.size() - 11) == ".protodevel") { | ||
// .protodevel | ||
return filename.substr(0, filename.size() - 11); | ||
} else { | ||
// .proto | ||
return filename.substr(0, filename.size() - 6); | ||
} | ||
} | ||
|
||
DescriptorPool new_pool_; | ||
|
||
} // namespace | ||
|
||
class GoGoProtoGenerator : public CodeGenerator { | ||
public: | ||
virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files, | ||
const string& parameter, | ||
GeneratorContext* context, | ||
string* error) const { | ||
for (int i = 0; i < files.size(); i++) { | ||
for (auto file : files) { | ||
bool can_generate = | ||
(new_pool_.FindFileByName(file->name()) == nullptr); | ||
for (int j = 0; j < file->dependency_count(); j++) { | ||
can_generate &= (new_pool_.FindFileByName( | ||
file->dependency(j)->name()) != nullptr); | ||
} | ||
for (int j = 0; j < file->public_dependency_count(); j++) { | ||
can_generate &= (new_pool_.FindFileByName( | ||
file->public_dependency(j)->name()) != nullptr); | ||
} | ||
for (int j = 0; j < file->weak_dependency_count(); j++) { | ||
can_generate &= (new_pool_.FindFileByName( | ||
file->weak_dependency(j)->name()) != nullptr); | ||
} | ||
if (can_generate) { | ||
Generate(file, parameter, context, error); | ||
break; | ||
} | ||
} | ||
} | ||
|
||
return true; | ||
} | ||
|
||
virtual bool Generate(const FileDescriptor* file, | ||
const string& parameter, | ||
GeneratorContext* context, | ||
string* error) const { | ||
FileDescriptorProto new_file; | ||
file->CopyTo(&new_file); | ||
SchemaGroupStripper::StripFile(file, &new_file); | ||
|
||
SchemaAddZeroEnumValue enum_scrubber; | ||
enum_scrubber.ScrubFile(&new_file); | ||
|
||
string filename = file->name(); | ||
string basename = StripProto(filename); | ||
|
||
std::vector<std::pair<string,string>> option_pairs; | ||
ParseGeneratorParameter(parameter, &option_pairs); | ||
|
||
std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output( | ||
context->Open(basename + ".proto")); | ||
string content = new_pool_.BuildFile(new_file)->DebugString(); | ||
Printer printer(output.get(), '$'); | ||
printer.WriteRaw(content.c_str(), content.size()); | ||
|
||
return true; | ||
} | ||
}; | ||
|
||
} // namespace compiler | ||
} // namespace protobuf | ||
} // namespace google | ||
|
||
int main(int argc, char* argv[]) { | ||
google::protobuf::compiler::GoGoProtoGenerator generator; | ||
return google::protobuf::compiler::PluginMain(argc, argv, &generator); | ||
} |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,137 @@ | ||
#ifndef PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ | ||
#define PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ | ||
|
||
#include "google/protobuf/message.h" | ||
#include "google/protobuf/descriptor.h" | ||
#include "google/protobuf/descriptor.pb.h" | ||
|
||
#include <sstream> | ||
#include <algorithm> | ||
|
||
using google::protobuf::Descriptor; | ||
using google::protobuf::DescriptorProto; | ||
using google::protobuf::FileDescriptorProto; | ||
using google::protobuf::FieldDescriptorProto; | ||
using google::protobuf::Message; | ||
using google::protobuf::EnumValueDescriptorProto; | ||
|
||
namespace google { | ||
namespace protobuf { | ||
namespace util { | ||
|
||
class SchemaGroupStripper { | ||
|
||
public: | ||
static void StripFile(const FileDescriptor* old_file, | ||
FileDescriptorProto *file) { | ||
for (int i = file->mutable_message_type()->size() - 1; i >= 0; i--) { | ||
if (IsMessageSet(old_file->message_type(i))) { | ||
file->mutable_message_type()->DeleteSubrange(i, 1); | ||
continue; | ||
} | ||
StripMessage(old_file->message_type(i), file->mutable_message_type(i)); | ||
} | ||
for (int i = file->mutable_extension()->size() - 1; i >= 0; i--) { | ||
auto field = old_file->extension(i); | ||
if (field->type() == FieldDescriptor::TYPE_GROUP || | ||
IsMessageSet(field->message_type()) || | ||
IsMessageSet(field->containing_type())) { | ||
file->mutable_extension()->DeleteSubrange(i, 1); | ||
} | ||
} | ||
} | ||
|
||
private: | ||
static bool IsMessageSet(const Descriptor *descriptor) { | ||
if (descriptor != nullptr | ||
&& descriptor->options().message_set_wire_format()) { | ||
return true; | ||
} | ||
return false; | ||
} | ||
|
||
static void StripMessage(const Descriptor *old_message, | ||
DescriptorProto *new_message) { | ||
for (int i = new_message->mutable_field()->size() - 1; i >= 0; i--) { | ||
if (old_message->field(i)->type() == FieldDescriptor::TYPE_GROUP || | ||
IsMessageSet(old_message->field(i)->message_type())) { | ||
new_message->mutable_field()->DeleteSubrange(i, 1); | ||
} | ||
} | ||
for (int i = new_message->mutable_extension()->size() - 1; i >= 0; i--) { | ||
auto field_type_name = new_message->mutable_extension(i)->type_name(); | ||
if (old_message->extension(i)->type() == FieldDescriptor::TYPE_GROUP || | ||
IsMessageSet(old_message->extension(i)->containing_type()) || | ||
IsMessageSet(old_message->extension(i)->message_type())) { | ||
new_message->mutable_extension()->DeleteSubrange(i, 1); | ||
} | ||
} | ||
for (int i = 0; i < new_message->mutable_nested_type()->size(); i++) { | ||
StripMessage(old_message->nested_type(i), | ||
new_message->mutable_nested_type(i)); | ||
} | ||
} | ||
|
||
}; | ||
|
||
class SchemaAddZeroEnumValue { | ||
|
||
public: | ||
SchemaAddZeroEnumValue() | ||
: total_added_(0) { | ||
} | ||
|
||
void ScrubFile(FileDescriptorProto *file) { | ||
for (int i = 0; i < file->enum_type_size(); i++) { | ||
ScrubEnum(file->mutable_enum_type(i)); | ||
} | ||
for (int i = 0; i < file->mutable_message_type()->size(); i++) { | ||
ScrubMessage(file->mutable_message_type(i)); | ||
} | ||
} | ||
|
||
private: | ||
void ScrubEnum(EnumDescriptorProto *enum_type) { | ||
if (enum_type->value(0).number() != 0) { | ||
bool has_zero = false; | ||
for (int j = 0; j < enum_type->value().size(); j++) { | ||
if (enum_type->value(j).number() == 0) { | ||
EnumValueDescriptorProto temp_enum_value; | ||
temp_enum_value.CopyFrom(enum_type->value(j)); | ||
enum_type->mutable_value(j)->CopyFrom(enum_type->value(0)); | ||
enum_type->mutable_value(0)->CopyFrom(temp_enum_value); | ||
has_zero = true; | ||
break; | ||
} | ||
} | ||
if (!has_zero) { | ||
enum_type->mutable_value()->Add(); | ||
for (int i = enum_type->mutable_value()->size() - 1; i > 0; i--) { | ||
enum_type->mutable_value(i)->CopyFrom( | ||
*enum_type->mutable_value(i - 1)); | ||
} | ||
enum_type->mutable_value(0)->set_number(0); | ||
enum_type->mutable_value(0)->set_name("ADDED_ZERO_VALUE_" + | ||
std::to_string(total_added_++)); | ||
} | ||
} | ||
|
||
} | ||
|
||
void ScrubMessage(DescriptorProto *message_type) { | ||
for (int i = 0; i < message_type->mutable_enum_type()->size(); i++) { | ||
ScrubEnum(message_type->mutable_enum_type(i)); | ||
} | ||
for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) { | ||
ScrubMessage(message_type->mutable_nested_type(i)); | ||
} | ||
} | ||
|
||
int total_added_; | ||
}; | ||
|
||
} // namespace util | ||
} // namespace protobuf | ||
} // namespace google | ||
|
||
#endif // PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_ |