blob: ca44a46d69f1ee1674a89c9a0ff21cccf7bee7c4 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <fbl/ref_ptr.h>
#include <fbl/string_printf.h>
#include <perftest/perftest.h>
#include <src/lib/fxl/strings/string_printf.h>
#include <zircon/syscalls.h>
#include <iostream>
#include <random>
#include <sstream>
#include <vector>
#include "lib/inspect/deprecated/exposed_object.h"
namespace {
using ByteVector = component::Property::ByteVector;
using component::CallbackMetric;
using component::DoubleMetric;
using component::IntMetric;
using component::Metric;
using component::Object;
using component::ObjectPath;
using component::Property;
using component::UIntMetric;
const char kValue[] = "value";
const int kSmallPropertySize = 8;
const int kLargePropertySize = 10000;
const ObjectPath kPath0 = {};
const ObjectPath kPath1 = {"a"};
const ObjectPath kPath2 = {"a", "b"};
const ObjectPath kPath10 = {"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"};
class NumericItem : public component::ExposedObject {
public:
NumericItem(ObjectPath path)
: ExposedObject(UniqueName("itemN-")), path_{std::move(path)} {
object_dir().set_metric(path_, kValue, component::IntMetric(0));
}
NumericItem() : NumericItem(ObjectPath()) {}
void increment() { object_dir().add_metric(path_, kValue, 1); }
private:
ObjectPath path_;
};
class PropertyItem : public component::ExposedObject {
public:
PropertyItem() : ExposedObject(UniqueName("itemS-")) {
object_dir().set_prop(kValue, component::Property());
}
void set(std::string str_value) {
object_dir().set_prop(kValue, std::move(str_value));
}
void set(ByteVector vector_value) {
object_dir().set_prop(kValue, std::move(vector_value));
}
};
// Measure the time taken to create and destroy metrics and properties.
bool TestExposedObjectLifecycle(perftest::RepeatState* state) {
state->DeclareStep("MetricCreate");
state->DeclareStep("MetricDestroy");
state->DeclareStep("PropertyCreate");
state->DeclareStep("PropertyDestroy");
while (state->KeepRunning()) {
{
NumericItem item;
state->NextStep();
}
state->NextStep();
{
PropertyItem item;
state->NextStep();
}
}
return true;
}
// Measure the time taken to increment an IntMetric.
bool TestExposedObjectIncrement(perftest::RepeatState* state) {
NumericItem item;
while (state->KeepRunning()) {
item.increment();
}
return true;
}
// Measure the time taken to increment an IntMetric, given a path.
bool TestIncrementPath(perftest::RepeatState* state, ObjectPath path) {
NumericItem item(path);
while (state->KeepRunning()) {
item.increment();
}
return true;
}
// Measure the time taken to change a String property.
bool TestExposedObjectSetString(perftest::RepeatState* state, int size) {
PropertyItem item;
std::string string;
string.resize(size, 'a');
while (state->KeepRunning()) {
item.set(string);
}
return true;
}
// Measure the time taken to change a ByteVector property.
bool TestExposedObjectSetVector(perftest::RepeatState* state, int size) {
PropertyItem item;
ByteVector vector;
vector.resize(size, 'a');
while (state->KeepRunning()) {
item.set(vector);
}
return true;
}
bool TestExposedObjectParenting(perftest::RepeatState* state) {
NumericItem parent;
NumericItem child1;
NumericItem child2;
NumericItem child3;
state->DeclareStep("AddFirst");
state->DeclareStep("AddSecond");
state->DeclareStep("AddFirstAgain");
state->DeclareStep("AddThird");
state->DeclareStep("RemoveFirst");
state->DeclareStep("RemoveSecond");
state->DeclareStep("RemoveFirstAgain");
state->DeclareStep("RemoveThird");
while (state->KeepRunning()) {
child1.set_parent(parent.object_dir());
state->NextStep();
child2.set_parent(parent.object_dir());
state->NextStep();
child1.set_parent(parent.object_dir());
state->NextStep();
child3.set_parent(parent.object_dir());
state->NextStep();
child1.remove_from_parent();
state->NextStep();
child2.remove_from_parent();
state->NextStep();
child1.remove_from_parent();
state->NextStep();
child3.remove_from_parent();
}
return true;
}
bool TestIntMetricLifecycle(perftest::RepeatState* state) {
state->DeclareStep("Create");
state->DeclareStep("Destroy");
while (state->KeepRunning()) {
Metric item = IntMetric(5);
state->NextStep();
}
return true;
}
bool TestIntMetricSet(perftest::RepeatState* state) {
Metric item = IntMetric(5);
while (state->KeepRunning()) {
item.SetInt(5);
}
return true;
}
bool TestIntMetricAdd(perftest::RepeatState* state) {
Metric item = IntMetric(5);
while (state->KeepRunning()) {
item.Add(5);
}
return true;
}
bool TestIntMetricSub(perftest::RepeatState* state) {
Metric item = IntMetric(5);
while (state->KeepRunning()) {
item.Sub(5);
}
return true;
}
bool TestIntMetricToString(perftest::RepeatState* state) {
Metric item = IntMetric(5);
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToString());
}
return true;
}
bool TestIntMetricToFidl(perftest::RepeatState* state) {
Metric item = IntMetric(5);
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToFidl("a_name"));
}
return true;
}
bool TestUIntMetricLifecycle(perftest::RepeatState* state) {
state->DeclareStep("Create");
state->DeclareStep("Destroy");
while (state->KeepRunning()) {
Metric item = UIntMetric(5);
state->NextStep();
}
return true;
}
bool TestUIntMetricSet(perftest::RepeatState* state) {
Metric item = UIntMetric(5);
while (state->KeepRunning()) {
item.SetInt(5);
}
return true;
}
bool TestUIntMetricAdd(perftest::RepeatState* state) {
Metric item = UIntMetric(5);
while (state->KeepRunning()) {
item.Add(5);
}
return true;
}
bool TestUIntMetricSub(perftest::RepeatState* state) {
Metric item = UIntMetric(5);
while (state->KeepRunning()) {
item.Sub(5);
}
return true;
}
bool TestUIntMetricToString(perftest::RepeatState* state) {
Metric item = UIntMetric(5);
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToString());
}
return true;
}
bool TestUIntMetricToFidl(perftest::RepeatState* state) {
Metric item = UIntMetric(5);
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToFidl("a_name"));
}
return true;
}
bool TestDoubleMetricLifecycle(perftest::RepeatState* state) {
state->DeclareStep("Create");
state->DeclareStep("Destroy");
while (state->KeepRunning()) {
Metric item = DoubleMetric(5);
state->NextStep();
}
return true;
}
bool TestDoubleMetricSet(perftest::RepeatState* state) {
Metric item = DoubleMetric(5);
while (state->KeepRunning()) {
item.SetDouble(5);
}
return true;
}
bool TestDoubleMetricAdd(perftest::RepeatState* state) {
Metric item = DoubleMetric(5);
while (state->KeepRunning()) {
item.Add(5);
}
return true;
}
bool TestDoubleMetricSub(perftest::RepeatState* state) {
Metric item = DoubleMetric(5);
while (state->KeepRunning()) {
item.Sub(5);
}
return true;
}
bool TestDoubleMetricToString(perftest::RepeatState* state) {
Metric item = DoubleMetric(5);
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToString());
}
return true;
}
bool TestDoubleMetricToFidl(perftest::RepeatState* state) {
Metric item = DoubleMetric(5);
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToFidl("a_name"));
}
return true;
}
bool TestCallbackMetricLifecycle(perftest::RepeatState* state) {
state->DeclareStep("Create");
state->DeclareStep("Destroy");
while (state->KeepRunning()) {
Metric item =
CallbackMetric([](Metric* out_metric) { out_metric->SetInt(10); });
state->NextStep();
}
return true;
}
bool TestCallbackMetricSet(perftest::RepeatState* state) {
Metric item =
CallbackMetric([](Metric* out_metric) { out_metric->SetInt(10); });
while (state->KeepRunning()) {
item.SetCallback([](Metric* out_metric) { out_metric->SetInt(10); });
}
return true;
}
bool TestCallbackMetricToString(perftest::RepeatState* state) {
Metric item =
CallbackMetric([](Metric* out_metric) { out_metric->SetInt(10); });
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToString());
}
return true;
}
bool TestCallbackMetricToFidl(perftest::RepeatState* state) {
Metric item =
CallbackMetric([](Metric* out_metric) { out_metric->SetInt(10); });
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToFidl("a_name"));
}
return true;
}
bool TestStringPropertyLifecycle(perftest::RepeatState* state, int size) {
std::string data;
data.resize(size, 'a');
state->DeclareStep("Create");
state->DeclareStep("Destroy");
while (state->KeepRunning()) {
Property item(data);
state->NextStep();
}
return true;
}
bool TestStringPropertySet(perftest::RepeatState* state, int size) {
std::string data;
data.resize(size, 'a');
Property item(data);
while (state->KeepRunning()) {
item.Set(data);
}
return true;
}
bool TestStringPropertyToFidl(perftest::RepeatState* state, int size) {
std::string data;
data.resize(size, 'a');
Property item(data);
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToFidl("a_name"));
}
return true;
}
bool TestVectorPropertyLifecycle(perftest::RepeatState* state, int size) {
ByteVector data;
data.resize(size, 'a');
state->DeclareStep("Create");
state->DeclareStep("Destroy");
while (state->KeepRunning()) {
Property item(data);
state->NextStep();
}
return true;
}
bool TestVectorPropertySet(perftest::RepeatState* state, int size) {
ByteVector data;
data.resize(size, 'a');
Property item(data);
while (state->KeepRunning()) {
item.Set(data);
}
return true;
}
bool TestVectorPropertyToFidl(perftest::RepeatState* state, int size) {
ByteVector data;
data.resize(size, 'a');
Property item(data);
while (state->KeepRunning()) {
perftest::DoNotOptimize(item.ToFidl("a_name"));
}
return true;
}
bool TestCallbackPropertyLifecycle(perftest::RepeatState* state) {
state->DeclareStep("Create");
state->DeclareStep("Destroy");
while (state->KeepRunning()) {
Property item = Property([]() { return "a"; });
state->NextStep();
}
return true;
}
bool TestCallbackPropertySet(perftest::RepeatState* state) {
Property item = Property([]() { return "a"; });
while (state->KeepRunning()) {
item.Set([]() { return "a"; });
}
return true;
}
bool TestObjectLifecycle(perftest::RepeatState* state) {
state->DeclareStep("Create");
state->DeclareStep("Destroy");
while (state->KeepRunning()) {
auto item = Object::Make("a_name");
state->NextStep();
}
return true;
}
bool TestObjectParenting(perftest::RepeatState* state) {
auto parent = Object::Make("parent");
auto first_child = Object::Make("first");
auto second_child = Object::Make("second");
state->DeclareStep("AllocateChildren");
state->DeclareStep("AddFirstChild");
state->DeclareStep("AddSecondChild");
state->DeclareStep("GetFirstChild");
state->DeclareStep("GetInvalidChild");
state->DeclareStep("RemoveSecondChild");
state->DeclareStep("RemoveFirstChild");
state->DeclareStep("RemoveInvalidChild");
while (state->KeepRunning()) {
state->NextStep();
parent->SetChild(first_child);
state->NextStep();
parent->SetChild(second_child);
state->NextStep();
perftest::DoNotOptimize(parent->GetChild("first"));
state->NextStep();
perftest::DoNotOptimize(parent->GetChild("invalid"));
state->NextStep();
parent->TakeChild("second");
state->NextStep();
parent->TakeChild("first");
state->NextStep();
parent->TakeChild("invalid");
}
return true;
}
bool TestObjectMetricOperations(perftest::RepeatState* state) {
auto parent = Object::Make("parent");
state->DeclareStep("CreateMetric");
state->DeclareStep("Set");
state->DeclareStep("Add");
state->DeclareStep("Sub");
state->DeclareStep("Remove");
state->DeclareStep("RemoveMissing");
while (state->KeepRunning()) {
Metric metric = IntMetric(10);
state->NextStep();
parent->SetMetric("metric", std::move(metric));
state->NextStep();
parent->AddMetric("metric", 1);
state->NextStep();
parent->SubMetric("metric", 1);
state->NextStep();
parent->RemoveMetric("metric");
state->NextStep();
parent->RemoveMetric("not_there");
}
return true;
}
bool TestObjectPropertyOperations(perftest::RepeatState* state) {
auto parent = Object::Make("parent");
state->DeclareStep("CreateProperty");
state->DeclareStep("Set");
state->DeclareStep("Remove");
state->DeclareStep("RemoveMissing");
while (state->KeepRunning()) {
Property property = Property("data");
state->NextStep();
parent->SetProperty("property", std::move(property));
state->NextStep();
parent->RemoveMetric("property");
state->NextStep();
parent->RemoveMetric("not_there");
}
return true;
}
bool TestObjectChildrenCallback(perftest::RepeatState* state) {
auto parent = Object::Make("parent");
state->DeclareStep("SetCallback");
state->DeclareStep("RemoveCallback");
while (state->KeepRunning()) {
parent->SetChildrenCallback([](auto vector) {});
state->NextStep();
parent->ClearChildrenCallback();
}
// TODO(maybe): Test non-empty objects?
return true;
}
bool TestObjectToFidl(perftest::RepeatState* state) {
auto parent = Object::Make("parent");
while (state->KeepRunning()) {
perftest::DoNotOptimize(parent->ToFidl());
}
// TODO(maybe): Test non-empty objects?
return true;
}
void RegisterTests() {
perftest::RegisterTest("Expose/ExposedObject/Lifecycle",
TestExposedObjectLifecycle);
perftest::RegisterTest("Expose/ExposedObject/Increment",
TestExposedObjectIncrement);
perftest::RegisterTest("Expose/ExposedObject/Parenting",
TestExposedObjectParenting);
perftest::RegisterTest("Expose/ExposedObject/Path/0", TestIncrementPath,
kPath0);
perftest::RegisterTest("Expose/ExposedObject/Path/1", TestIncrementPath,
kPath1);
perftest::RegisterTest("Expose/ExposedObject/Path/2", TestIncrementPath,
kPath2);
perftest::RegisterTest("Expose/ExposedObject/Path/10", TestIncrementPath,
kPath10);
perftest::RegisterTest(
fxl::StringPrintf("Expose/ExposedObject/SetString/%d", kSmallPropertySize)
.c_str(),
TestExposedObjectSetString, kSmallPropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/ExposedObject/SetString/%d", kLargePropertySize)
.c_str(),
TestExposedObjectSetString, kLargePropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/ExposedObject/SetVector/%d", kSmallPropertySize)
.c_str(),
TestExposedObjectSetVector, kSmallPropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/ExposedObject/SetVector/%d", kLargePropertySize)
.c_str(),
TestExposedObjectSetVector, kLargePropertySize);
perftest::RegisterTest("Expose/IntMetric/Lifecycle", TestIntMetricLifecycle);
perftest::RegisterTest("Expose/IntMetric/Set", TestIntMetricSet);
perftest::RegisterTest("Expose/IntMetric/Add", TestIntMetricAdd);
perftest::RegisterTest("Expose/IntMetric/Sub", TestIntMetricSub);
perftest::RegisterTest("Expose/IntMetric/ToString", TestIntMetricToString);
perftest::RegisterTest("Expose/IntMetric/ToFidl", TestIntMetricToFidl);
perftest::RegisterTest("Expose/UIntMetric/Lifecycle",
TestUIntMetricLifecycle);
perftest::RegisterTest("Expose/UIntMetric/Set", TestUIntMetricSet);
perftest::RegisterTest("Expose/UIntMetric/Add", TestUIntMetricAdd);
perftest::RegisterTest("Expose/UIntMetric/Sub", TestUIntMetricSub);
perftest::RegisterTest("Expose/UIntMetric/ToString", TestUIntMetricToString);
perftest::RegisterTest("Expose/UIntMetric/ToFidl", TestUIntMetricToFidl);
perftest::RegisterTest("Expose/DoubleMetric/Lifecycle",
TestDoubleMetricLifecycle);
perftest::RegisterTest("Expose/DoubleMetric/Set", TestDoubleMetricSet);
perftest::RegisterTest("Expose/DoubleMetric/Add", TestDoubleMetricAdd);
perftest::RegisterTest("Expose/DoubleMetric/Sub", TestDoubleMetricSub);
perftest::RegisterTest("Expose/DoubleMetric/ToString",
TestDoubleMetricToString);
perftest::RegisterTest("Expose/DoubleMetric/ToFidl", TestDoubleMetricToFidl);
perftest::RegisterTest("Expose/CallbackMetric/Lifecycle",
TestCallbackMetricLifecycle);
perftest::RegisterTest("Expose/CallbackMetric/Set", TestCallbackMetricSet);
perftest::RegisterTest("Expose/CallbackMetric/ToString",
TestCallbackMetricToString);
perftest::RegisterTest("Expose/CallbackMetric/ToFidl",
TestCallbackMetricToFidl);
perftest::RegisterTest(fxl::StringPrintf("Expose/StringProperty/Lifecycle/%d",
kSmallPropertySize)
.c_str(),
TestStringPropertyLifecycle, kSmallPropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/StringProperty/Set/%d", kSmallPropertySize)
.c_str(),
TestStringPropertySet, kSmallPropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/StringProperty/ToFidl/%d", kSmallPropertySize)
.c_str(),
TestStringPropertyToFidl, kSmallPropertySize);
perftest::RegisterTest(fxl::StringPrintf("Expose/StringProperty/Lifecycle/%d",
kLargePropertySize)
.c_str(),
TestStringPropertyLifecycle, kLargePropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/StringProperty/Set/%d", kLargePropertySize)
.c_str(),
TestStringPropertySet, kLargePropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/StringProperty/ToFidl/%d", kLargePropertySize)
.c_str(),
TestStringPropertyToFidl, kLargePropertySize);
perftest::RegisterTest(fxl::StringPrintf("Expose/VectorProperty/Lifecycle/%d",
kSmallPropertySize)
.c_str(),
TestVectorPropertyLifecycle, kSmallPropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/VectorProperty/Set/%d", kSmallPropertySize)
.c_str(),
TestVectorPropertySet, kSmallPropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/VectorProperty/ToFidl/%d", kSmallPropertySize)
.c_str(),
TestVectorPropertyToFidl, kSmallPropertySize);
perftest::RegisterTest(fxl::StringPrintf("Expose/VectorProperty/Lifecycle/%d",
kLargePropertySize)
.c_str(),
TestVectorPropertyLifecycle, kLargePropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/VectorProperty/Set/%d", kLargePropertySize)
.c_str(),
TestVectorPropertySet, kLargePropertySize);
perftest::RegisterTest(
fxl::StringPrintf("Expose/VectorProperty/ToFidl/%d", kLargePropertySize)
.c_str(),
TestVectorPropertyToFidl, kLargePropertySize);
perftest::RegisterTest("Expose/CallbackProperty/Lifecycle",
TestCallbackPropertyLifecycle);
perftest::RegisterTest("Expose/CallbackProperty/Set",
TestCallbackPropertySet);
perftest::RegisterTest("Expose/Object/Lifecycle", TestObjectLifecycle);
perftest::RegisterTest("Expose/Object/Parenting", TestObjectParenting);
perftest::RegisterTest("Expose/Object/MetricOperations",
TestObjectMetricOperations);
perftest::RegisterTest("Expose/Object/PropertyOperations",
TestObjectPropertyOperations);
perftest::RegisterTest("Expose/Object/ToFidl", TestObjectToFidl);
perftest::RegisterTest("Expose/Object/ChildrenCallback",
TestObjectChildrenCallback);
}
PERFTEST_CTOR(RegisterTests);
} // namespace