Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b3d38d9 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Avoid creating temporary objects in FiterValue()."

parents 1184694c f5204922
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -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)

+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
+8 −0
Original line number Diff line number Diff line
@@ -135,6 +135,8 @@ Value::Value(const Value& from) {
        case STRING:
            str_value = from.str_value;
            break;
        default:
            break;
    }
}

@@ -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]";
    }
}

@@ -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;
    }
}

@@ -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;
    }
}

+6 −4
Original line number Diff line number Diff line
@@ -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);

@@ -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);
    }
@@ -229,6 +231,8 @@ struct Matcher {
 *
 */
struct Value {
    Value() : type(UNKNOWN) {}

    Value(int32_t v) {
        int_value = v;
        type = INT;
@@ -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 {
+20 −10
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@
#define DEBUG false  // STOPSHIP if true
#include "Log.h"

#include <mutex>

#include "HashableDimensionKey.h"
#include "FieldValue.h"

@@ -50,6 +52,8 @@ android::hash_t hashDimension(const HashableDimensionKey& value) {
                                               android::hash_type(fieldValue.mValue.float_value));
                break;
            }
            default:
                break;
        }
    }
    return JenkinsHashWhiten(hash);
@@ -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]);
            }
@@ -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