Loading cmds/statsd/Android.mk +2 −1 Original line number Diff line number Diff line Loading @@ -249,7 +249,8 @@ LOCAL_SRC_FILES := $(statsd_common_src) \ benchmark/main.cpp \ benchmark/hello_world_benchmark.cpp \ benchmark/log_event_benchmark.cpp \ benchmark/stats_write_benchmark.cpp benchmark/stats_write_benchmark.cpp \ benchmark/filter_value_benchmark.cpp LOCAL_C_INCLUDES := $(statsd_common_c_includes) Loading cmds/statsd/benchmark/filter_value_benchmark.cpp 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * 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 <vector> #include "benchmark/benchmark.h" #include "FieldValue.h" #include "HashableDimensionKey.h" #include "logd/LogEvent.h" namespace android { namespace os { namespace statsd { using std::vector; static void BM_FilterValue(benchmark::State& state) { LogEvent event(1, 100000); event.write(3.2f); event.write("LOCATION"); event.write((int64_t)990); event.init(); FieldMatcher field_matcher; field_matcher.set_field(1); field_matcher.add_child()->set_field(2); field_matcher.add_child()->set_field(3); std::vector<Matcher> matchers; translateFieldMatcher(field_matcher, &matchers); while (state.KeepRunning()) { vector<HashableDimensionKey> output; filterValues(matchers, event.getValues(), &output); } } BENCHMARK(BM_FilterValue); } // namespace statsd } // namespace os } // namespace android cmds/statsd/src/FieldValue.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,8 @@ Value::Value(const Value& from) { case STRING: str_value = from.str_value; break; default: break; } } Loading @@ -148,6 +150,8 @@ std::string Value::toString() const { return std::to_string(float_value) + "[F]"; case STRING: return str_value + "[S]"; default: return "[UNKNOWN]"; } } Loading @@ -163,6 +167,8 @@ bool Value::operator==(const Value& that) const { return float_value == that.float_value; case STRING: return str_value == that.str_value; default: return false; } } Loading @@ -177,6 +183,8 @@ bool Value::operator!=(const Value& that) const { return float_value != that.float_value; case STRING: return str_value != that.str_value; default: return false; } } Loading cmds/statsd/src/FieldValue.h +6 −4 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ const int32_t kMaxLogDepth = 2; const int32_t kLastBitMask = 0x80; const int32_t kClearLastBitDeco = 0x7f; enum Type { INT, LONG, FLOAT, STRING }; enum Type { UNKNOWN, INT, LONG, FLOAT, STRING }; int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth); Loading Loading @@ -82,6 +82,8 @@ private: int32_t mField; public: Field() {} Field(int32_t tag, int32_t pos[], int32_t depth) : mTag(tag) { mField = getEncodedField(pos, depth, true); } Loading Loading @@ -229,6 +231,8 @@ struct Matcher { * */ struct Value { Value() : type(UNKNOWN) {} Value(int32_t v) { int_value = v; type = INT; Loading Loading @@ -280,15 +284,13 @@ struct Value { bool operator!=(const Value& that) const; bool operator<(const Value& that) const; private: Value(){}; }; /** * Represents a log item, or a dimension item (They are essentially the same). */ struct FieldValue { FieldValue() {} FieldValue(const Field& field, const Value& value) : mField(field), mValue(value) { } bool operator==(const FieldValue& that) const { Loading cmds/statsd/src/HashableDimensionKey.cpp +20 −10 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #define DEBUG false // STOPSHIP if true #include "Log.h" #include <mutex> #include "HashableDimensionKey.h" #include "FieldValue.h" Loading Loading @@ -50,6 +52,8 @@ android::hash_t hashDimension(const HashableDimensionKey& value) { android::hash_type(fieldValue.mValue.float_value)); break; } default: break; } } return JenkinsHashWhiten(hash); Loading @@ -64,26 +68,32 @@ bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue> int prevAnyMatcherPrefix = 0; size_t prevPrevFanout = 0; size_t prevFanout = 0; // For each matcher get matched results. vector<FieldValue> matchedResults(2); for (const auto& matcher : matcherFields) { vector<FieldValue> matchedResults; size_t num_matches = 0; for (const auto& value : values) { // TODO: potential optimization here to break early because all fields are naturally // sorted. if (value.mField.matches(matcher)) { matchedResults.push_back(FieldValue( Field(value.mField.getTag(), (value.mField.getField() & matcher.mMask)), value.mValue)); if (num_matches >= matchedResults.size()) { matchedResults.resize(num_matches * 2); } matchedResults[num_matches].mField.setTag(value.mField.getTag()); matchedResults[num_matches].mField.setField(value.mField.getField() & matcher.mMask); matchedResults[num_matches].mValue = value.mValue; num_matches++; } } if (matchedResults.size() == 0) { if (num_matches == 0) { VLOG("We can't find a dimension value for matcher (%d)%#x.", matcher.mMatcher.getTag(), matcher.mMatcher.getField()); continue; } if (matchedResults.size() == 1) { if (num_matches == 1) { for (auto& dimension : *output) { dimension.addValue(matchedResults[0]); } Loading Loading @@ -119,23 +129,23 @@ bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue> // First create fanout (fanout size is matchedResults.Size which could be one, // which means we do nothing here) oldSize = output->size(); for (size_t i = 1; i < matchedResults.size(); i++) { for (size_t i = 1; i < num_matches; i++) { output->insert(output->end(), output->begin(), output->begin() + oldSize); } prevPrevFanout = oldSize; prevFanout = matchedResults.size(); prevFanout = num_matches; } else { // If we should not create fanout, e.g., uid tag from same position should be remain // together. oldSize = prevPrevFanout; if (prevFanout != matchedResults.size()) { if (prevFanout != num_matches) { // sanity check. ALOGE("2 Any matcher result in different output"); return false; } } // now add the matched field value to output for (size_t i = 0; i < matchedResults.size(); i++) { for (size_t i = 0; i < num_matches; i++) { for (int j = 0; j < oldSize; j++) { (*output)[i * oldSize + j].addValue(matchedResults[i]); } Loading Loading
cmds/statsd/Android.mk +2 −1 Original line number Diff line number Diff line Loading @@ -249,7 +249,8 @@ LOCAL_SRC_FILES := $(statsd_common_src) \ benchmark/main.cpp \ benchmark/hello_world_benchmark.cpp \ benchmark/log_event_benchmark.cpp \ benchmark/stats_write_benchmark.cpp benchmark/stats_write_benchmark.cpp \ benchmark/filter_value_benchmark.cpp LOCAL_C_INCLUDES := $(statsd_common_c_includes) Loading
cmds/statsd/benchmark/filter_value_benchmark.cpp 0 → 100644 +53 −0 Original line number Diff line number Diff line /* * Copyright (C) 2018 The Android Open Source Project * * 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 <vector> #include "benchmark/benchmark.h" #include "FieldValue.h" #include "HashableDimensionKey.h" #include "logd/LogEvent.h" namespace android { namespace os { namespace statsd { using std::vector; static void BM_FilterValue(benchmark::State& state) { LogEvent event(1, 100000); event.write(3.2f); event.write("LOCATION"); event.write((int64_t)990); event.init(); FieldMatcher field_matcher; field_matcher.set_field(1); field_matcher.add_child()->set_field(2); field_matcher.add_child()->set_field(3); std::vector<Matcher> matchers; translateFieldMatcher(field_matcher, &matchers); while (state.KeepRunning()) { vector<HashableDimensionKey> output; filterValues(matchers, event.getValues(), &output); } } BENCHMARK(BM_FilterValue); } // namespace statsd } // namespace os } // namespace android
cmds/statsd/src/FieldValue.cpp +8 −0 Original line number Diff line number Diff line Loading @@ -135,6 +135,8 @@ Value::Value(const Value& from) { case STRING: str_value = from.str_value; break; default: break; } } Loading @@ -148,6 +150,8 @@ std::string Value::toString() const { return std::to_string(float_value) + "[F]"; case STRING: return str_value + "[S]"; default: return "[UNKNOWN]"; } } Loading @@ -163,6 +167,8 @@ bool Value::operator==(const Value& that) const { return float_value == that.float_value; case STRING: return str_value == that.str_value; default: return false; } } Loading @@ -177,6 +183,8 @@ bool Value::operator!=(const Value& that) const { return float_value != that.float_value; case STRING: return str_value != that.str_value; default: return false; } } Loading
cmds/statsd/src/FieldValue.h +6 −4 Original line number Diff line number Diff line Loading @@ -31,7 +31,7 @@ const int32_t kMaxLogDepth = 2; const int32_t kLastBitMask = 0x80; const int32_t kClearLastBitDeco = 0x7f; enum Type { INT, LONG, FLOAT, STRING }; enum Type { UNKNOWN, INT, LONG, FLOAT, STRING }; int32_t getEncodedField(int32_t pos[], int32_t depth, bool includeDepth); Loading Loading @@ -82,6 +82,8 @@ private: int32_t mField; public: Field() {} Field(int32_t tag, int32_t pos[], int32_t depth) : mTag(tag) { mField = getEncodedField(pos, depth, true); } Loading Loading @@ -229,6 +231,8 @@ struct Matcher { * */ struct Value { Value() : type(UNKNOWN) {} Value(int32_t v) { int_value = v; type = INT; Loading Loading @@ -280,15 +284,13 @@ struct Value { bool operator!=(const Value& that) const; bool operator<(const Value& that) const; private: Value(){}; }; /** * Represents a log item, or a dimension item (They are essentially the same). */ struct FieldValue { FieldValue() {} FieldValue(const Field& field, const Value& value) : mField(field), mValue(value) { } bool operator==(const FieldValue& that) const { Loading
cmds/statsd/src/HashableDimensionKey.cpp +20 −10 Original line number Diff line number Diff line Loading @@ -16,6 +16,8 @@ #define DEBUG false // STOPSHIP if true #include "Log.h" #include <mutex> #include "HashableDimensionKey.h" #include "FieldValue.h" Loading Loading @@ -50,6 +52,8 @@ android::hash_t hashDimension(const HashableDimensionKey& value) { android::hash_type(fieldValue.mValue.float_value)); break; } default: break; } } return JenkinsHashWhiten(hash); Loading @@ -64,26 +68,32 @@ bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue> int prevAnyMatcherPrefix = 0; size_t prevPrevFanout = 0; size_t prevFanout = 0; // For each matcher get matched results. vector<FieldValue> matchedResults(2); for (const auto& matcher : matcherFields) { vector<FieldValue> matchedResults; size_t num_matches = 0; for (const auto& value : values) { // TODO: potential optimization here to break early because all fields are naturally // sorted. if (value.mField.matches(matcher)) { matchedResults.push_back(FieldValue( Field(value.mField.getTag(), (value.mField.getField() & matcher.mMask)), value.mValue)); if (num_matches >= matchedResults.size()) { matchedResults.resize(num_matches * 2); } matchedResults[num_matches].mField.setTag(value.mField.getTag()); matchedResults[num_matches].mField.setField(value.mField.getField() & matcher.mMask); matchedResults[num_matches].mValue = value.mValue; num_matches++; } } if (matchedResults.size() == 0) { if (num_matches == 0) { VLOG("We can't find a dimension value for matcher (%d)%#x.", matcher.mMatcher.getTag(), matcher.mMatcher.getField()); continue; } if (matchedResults.size() == 1) { if (num_matches == 1) { for (auto& dimension : *output) { dimension.addValue(matchedResults[0]); } Loading Loading @@ -119,23 +129,23 @@ bool filterValues(const vector<Matcher>& matcherFields, const vector<FieldValue> // First create fanout (fanout size is matchedResults.Size which could be one, // which means we do nothing here) oldSize = output->size(); for (size_t i = 1; i < matchedResults.size(); i++) { for (size_t i = 1; i < num_matches; i++) { output->insert(output->end(), output->begin(), output->begin() + oldSize); } prevPrevFanout = oldSize; prevFanout = matchedResults.size(); prevFanout = num_matches; } else { // If we should not create fanout, e.g., uid tag from same position should be remain // together. oldSize = prevPrevFanout; if (prevFanout != matchedResults.size()) { if (prevFanout != num_matches) { // sanity check. ALOGE("2 Any matcher result in different output"); return false; } } // now add the matched field value to output for (size_t i = 0; i < matchedResults.size(); i++) { for (size_t i = 0; i < num_matches; i++) { for (int j = 0; j < oldSize; j++) { (*output)[i * oldSize + j].addValue(matchedResults[i]); } Loading