/* * Copyright (c) Meta Platforms, Inc. and affiliates. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include #include #include #include using namespace folly; using namespace std; namespace apache::thrift::protocol { // Testcase 1 uses an object with a large bool list and patch doesn't contain // the field. Testcase 4 uses the same object and clears the field. Object getObject1And4(int n) { Object obj; std::vector boolList; while (n--) { boolList.push_back(asValueStruct(n % 2)); } obj[FieldId{1}].emplace_list(boolList); obj[FieldId{2}].emplace_i32(5); return obj; } Object getPatchObj1And4(bool clear) { Value intPatch; intPatch.ensure_object()[FieldId{static_cast(op::PatchOp::Assign)}] = asValueStruct(1); Value objPatch; objPatch.ensure_object()[FieldId{2}] = intPatch; if (clear) { Value listPatch; listPatch .ensure_object()[FieldId{static_cast(op::PatchOp::Clear)}] = asValueStruct(true); objPatch.objectValue_ref().ensure()[FieldId{1}] = listPatch; } Object patchObj; patchObj[FieldId{static_cast(op::PatchOp::PatchAfter)}] = objPatch; return patchObj; } // Testcase 2 uses an object with a large bool list and patch contains // the field. Object getObject2(int n) { Object obj; std::vector boolList; while (n--) { boolList.push_back(asValueStruct(n % 2)); } obj[FieldId{1}].emplace_list(boolList); obj[FieldId{2}].emplace_i32(5); return obj; } Object getPatchObj2() { Value intPatch; intPatch.ensure_object()[FieldId{static_cast(op::PatchOp::Assign)}] = asValueStruct(1); Value listPatch; listPatch.ensure_object()[FieldId{static_cast(op::PatchOp::Put)}] .emplace_list(std::vector{asValueStruct(true)}); Value objPatch; objPatch.ensure_object()[FieldId{1}] = listPatch; objPatch.ensure_object()[FieldId{2}] = intPatch; Object patchObj; patchObj[FieldId{static_cast(op::PatchOp::PatchAfter)}] = objPatch; return patchObj; } // Testcase 3 uses an object with many fields and patch contain all the fields. Object getObject3(int n) { Object obj; while (n--) { obj[static_cast(n)].emplace_i32(n); } return obj; } Object getPatchObj3(int n) { Value intPatch; intPatch.ensure_object()[FieldId{static_cast(op::PatchOp::Add)}] = asValueStruct(1); Value objPatch; while (n--) { objPatch.ensure_object()[static_cast(n)] = intPatch; } Object patchObj; patchObj[FieldId{static_cast(op::PatchOp::PatchAfter)}] = objPatch; return patchObj; } std::unique_ptr serialized1, serialized2, serialized3, serialized4; Object patchObj1, patchObj2, patchObj3, patchObj4; void init(int n) { serialized1 = serializeObject(getObject1And4(n)); patchObj1 = getPatchObj1And4(false); serialized2 = serializeObject(getObject2(n)); patchObj2 = getPatchObj2(); serialized3 = serializeObject(getObject3(n)); patchObj3 = getPatchObj3(n); serialized4 = serializeObject(getObject1And4(n)); patchObj4 = getPatchObj1And4(true); } void runOriginalApproach( std::unique_ptr& serialized, const Object& patchObj) { Value value; value.emplace_object(parseObject(*serialized)); protocol::applyPatch(patchObj, value); protocol::serializeObject(value.as_object()); } BENCHMARK(patch_few_small_fields_without_partial_deser) { runOriginalApproach(serialized1, patchObj1); } BENCHMARK(patch_few_small_fields_with_partial_deser) { applyPatchToSerializedData( patchObj1, *serialized1); } BENCHMARK(patch_large_fields_without_partial_deser) { runOriginalApproach(serialized2, patchObj2); } BENCHMARK(patch_large_fields_with_partial_deser) { applyPatchToSerializedData( patchObj2, *serialized2); } BENCHMARK(patch_all_small_fields_without_partial_deser) { runOriginalApproach(serialized3, patchObj3); } BENCHMARK(patch_all_small_fields_with_partial_deser) { applyPatchToSerializedData( patchObj3, *serialized3); } BENCHMARK(patch_clear_large_fields_without_partial_deser) { runOriginalApproach(serialized4, patchObj4); } BENCHMARK(patch_clear_large_fields_with_partial_deser) { applyPatchToSerializedData( patchObj4, *serialized4); } } // namespace apache::thrift::protocol int main(int argc, char** argv) { folly::init(&argc, &argv); apache::thrift::protocol::init(10000); runBenchmarks(); return 0; }