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

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

Merge "Cpu usage optimization: 1/ Avoid unnecessary field/dimension proto...

Merge "Cpu usage optimization: 1/ Avoid unnecessary field/dimension proto construction. 2/ use unordered_map for slicing. 3/ Use dimension fields to compare dimension keys."
parents a14bbf55 7ba8fc35
Loading
Loading
Loading
Loading
+48 −7
Original line number Diff line number Diff line
@@ -69,18 +69,17 @@ android::hash_t hashDimensionsValue(const DimensionsValue& value) {

using std::string;


string HashableDimensionKey::toString() const {
    string flattened;
    DimensionsValueToString(getDimensionsValue(), &flattened);
    return flattened;
}

bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2) {
bool EqualsTo(const DimensionsValue& s1, const DimensionsValue& s2) {
    if (s1.field() != s2.field()) {
        return false;
    }
    if (s1.value_case() != s1.value_case()) {
    if (s1.value_case() != s2.value_case()) {
        return false;
    }
    switch (s1.value_case()) {
@@ -102,7 +101,7 @@ bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2
                }
                bool allMatched = true;
                for (int i = 0; allMatched && i < s1.value_tuple().dimensions_value_size(); ++i) {
                    allMatched &= compareDimensionsValue(s1.value_tuple().dimensions_value(i),
                    allMatched &= EqualsTo(s1.value_tuple().dimensions_value(i),
                                           s2.value_tuple().dimensions_value(i));
                }
                return allMatched;
@@ -113,12 +112,54 @@ bool compareDimensionsValue(const DimensionsValue& s1, const DimensionsValue& s2
    }
}

bool LessThan(const DimensionsValue& s1, const DimensionsValue& s2) {
    if (s1.field() != s2.field()) {
        return s1.field() < s2.field();
    }
    if (s1.value_case() != s2.value_case()) {
        return s1.value_case() < s2.value_case();
    }
    switch (s1.value_case()) {
        case DimensionsValue::ValueCase::kValueStr:
            return s1.value_str() < s2.value_str();
        case DimensionsValue::ValueCase::kValueInt:
            return s1.value_int() < s2.value_int();
        case DimensionsValue::ValueCase::kValueLong:
            return s1.value_long() < s2.value_long();
        case DimensionsValue::ValueCase::kValueBool:
            return (int)s1.value_bool() < (int)s2.value_bool();
        case DimensionsValue::ValueCase::kValueFloat:
            return s1.value_float() < s2.value_float();
        case DimensionsValue::ValueCase::kValueTuple:
            {
                if (s1.value_tuple().dimensions_value_size() !=
                        s2.value_tuple().dimensions_value_size()) {
                    return s1.value_tuple().dimensions_value_size() <
                        s2.value_tuple().dimensions_value_size();
                }
                for (int i = 0;  i < s1.value_tuple().dimensions_value_size(); ++i) {
                    if (EqualsTo(s1.value_tuple().dimensions_value(i),
                                 s2.value_tuple().dimensions_value(i))) {
                        continue;
                    } else {
                        return LessThan(s1.value_tuple().dimensions_value(i),
                                        s2.value_tuple().dimensions_value(i));
                    }
                }
                return false;
            }
        case DimensionsValue::ValueCase::VALUE_NOT_SET:
        default:
            return false;
    }
}

bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const {
    return compareDimensionsValue(getDimensionsValue(), that.getDimensionsValue());
    return EqualsTo(getDimensionsValue(), that.getDimensionsValue());
};

bool HashableDimensionKey::operator<(const HashableDimensionKey& that) const {
    return toString().compare(that.toString()) < 0;
    return LessThan(getDimensionsValue(), that.getDimensionsValue());
};

}  // namespace statsd
+10 −11
Original line number Diff line number Diff line
@@ -91,23 +91,22 @@ void StatsLogProcessor::onAnomalyAlarmFired(
}

void StatsLogProcessor::mapIsolatedUidToHostUidIfNecessaryLocked(LogEvent* event) const {
    std::vector<Field> uidFields;
    std::set<Field, FieldCmp> uidFields;
    if (android::util::kAtomsWithAttributionChain.find(event->GetTagId()) !=
        android::util::kAtomsWithAttributionChain.end()) {
        findFields(
            event->getFieldValueMap(),
            buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY),
            &uidFields);
        FieldMatcher matcher;
        buildAttributionUidFieldMatcher(event->GetTagId(), Position::ANY, &matcher);
        findFields(event->getFieldValueMap(), matcher, &uidFields);
    } else if (android::util::kAtomsWithUidField.find(event->GetTagId()) !=
               android::util::kAtomsWithUidField.end()) {
        findFields(
            event->getFieldValueMap(),
            buildSimpleAtomFieldMatcher(event->GetTagId(), 1 /* uid is always the 1st field. */),
            &uidFields);
        FieldMatcher matcher;
        buildSimpleAtomFieldMatcher(
            event->GetTagId(), 1 /* uid is always the 1st field. */, &matcher);
        findFields(event->getFieldValueMap(), matcher, &uidFields);
    }

    for (size_t i = 0; i < uidFields.size(); ++i) {
        DimensionsValue* value = event->findFieldValueOrNull(uidFields[i]);
    for (const auto& uidField : uidFields) {
        DimensionsValue* value = event->findFieldValueOrNull(uidField);
        if (value != nullptr && value->value_case() == DimensionsValue::ValueCase::kValueInt) {
            const int uid = mUidMap->getHostUidOrSelf(value->value_int());
            value->set_value_int(uid);
+2 −1
Original line number Diff line number Diff line
@@ -289,7 +289,8 @@ void SimpleConditionTracker::evaluateCondition(const LogEvent& event,
    }

    // outputKey is the output values. e.g, uid:1234
    const std::vector<DimensionsValue> outputValues = getDimensionKeys(event, mOutputDimensions);
    std::vector<DimensionsValue> outputValues;
    getDimensionKeys(event, mOutputDimensions, &outputValues);
    if (outputValues.size() == 0) {
        // The original implementation would generate an empty string dimension hash when condition
        // is not sliced.
+29 −28
Original line number Diff line number Diff line
@@ -116,28 +116,30 @@ void OrBooleanVector(const std::vector<bool>& ref, vector<bool> * ored) {
    }
}

void getFieldsFromFieldMatcher(const FieldMatcher& matcher, const Field& parentField,
void getFieldsFromFieldMatcher(const FieldMatcher& matcher, Field* rootField, Field* leafField,
                               std::vector<Field> *allFields) {
    Field newParent = parentField;
    Field* leaf = getSingleLeaf(&newParent);
    leaf->set_field(matcher.field());
    if (matcher.child_size() == 0) {
        allFields->push_back(newParent);
        allFields->push_back(*rootField);
        return;
    }
    for (int i = 0; i < matcher.child_size(); ++i) {
        leaf->add_child();
        getFieldsFromFieldMatcher(matcher.child(i), newParent, allFields);
        Field* newLeafField = leafField->add_child();
        newLeafField->set_field(matcher.child(i).field());
        getFieldsFromFieldMatcher(matcher.child(i), rootField, newLeafField, allFields);
    }
}

void getFieldsFromFieldMatcher(const FieldMatcher& matcher, std::vector<Field> *allFields) {
    Field parentField;
    getFieldsFromFieldMatcher(matcher, parentField, allFields);
    if (!matcher.has_field()) {
        return;
    }
    Field rootField;
    rootField.set_field(matcher.field());
    getFieldsFromFieldMatcher(matcher, &rootField, &rootField, allFields);
}

void flattenValueLeaves(const DimensionsValue& value,
                        std::vector<DimensionsValue> *allLaves) {
                        std::vector<const DimensionsValue*> *allLaves) {
    switch (value.value_case()) {
        case DimensionsValue::ValueCase::kValueStr:
        case DimensionsValue::ValueCase::kValueInt:
@@ -145,7 +147,7 @@ void flattenValueLeaves(const DimensionsValue& value,
        case DimensionsValue::ValueCase::kValueBool:
        case DimensionsValue::ValueCase::kValueFloat:
        case DimensionsValue::ValueCase::VALUE_NOT_SET:
            allLaves->push_back(value);
            allLaves->push_back(&value);
            break;
        case DimensionsValue::ValueCase::kValueTuple:
            for (int i = 0; i < value.value_tuple().dimensions_value_size(); ++i) {
@@ -155,45 +157,44 @@ void flattenValueLeaves(const DimensionsValue& value,
    }
}

std::vector<HashableDimensionKey> getDimensionKeysForCondition(
    const LogEvent& event, const MetricConditionLink& link) {
void getDimensionKeysForCondition(
    const LogEvent& event, const MetricConditionLink& link,
    std::vector<HashableDimensionKey> *hashableDimensionKeys) {
    std::vector<Field> whatFields;
    getFieldsFromFieldMatcher(link.fields_in_what(), &whatFields);
    std::vector<Field> conditionFields;
    getFieldsFromFieldMatcher(link.fields_in_condition(), &conditionFields);

    std::vector<HashableDimensionKey> hashableDimensionKeys;

    // TODO(yanglu): here we could simplify the logic to get the leaf value node in what and
    // directly construct the full condition value tree.
    std::vector<DimensionsValue> whatValues = getDimensionKeys(event, link.fields_in_what());
    std::vector<DimensionsValue> whatValues;
    getDimensionKeys(event, link.fields_in_what(), &whatValues);

    for (size_t i = 0; i < whatValues.size(); ++i) {
        std::vector<DimensionsValue> whatLeaves;
        std::vector<const DimensionsValue*> whatLeaves;
        flattenValueLeaves(whatValues[i], &whatLeaves);
        if (whatLeaves.size() != whatFields.size() ||
            whatLeaves.size() != conditionFields.size()) {
            ALOGE("Dimensions between what and condition not equal.");
            return hashableDimensionKeys;
            return;
        }
        FieldValueMap conditionValueMap;
        for (size_t j = 0; j < whatLeaves.size(); ++j) {
            if (!setFieldInLeafValueProto(conditionFields[j], &whatLeaves[j])) {
            DimensionsValue* conditionValue = &conditionValueMap[conditionFields[j]];
            *conditionValue = *whatLeaves[i];
            if (!setFieldInLeafValueProto(conditionFields[j], conditionValue)) {
                ALOGE("Not able to reset the field for condition leaf value.");
                return hashableDimensionKeys;
                return;
            }
            conditionValueMap.insert(std::make_pair(conditionFields[j], whatLeaves[j]));
        }
        std::vector<DimensionsValue> conditionValues;
        findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValues);
        if (conditionValues.size() != 1) {
        std::vector<DimensionsValue> conditionValueTrees;
        findDimensionsValues(conditionValueMap, link.fields_in_condition(), &conditionValueTrees);
        if (conditionValueTrees.size() != 1) {
            ALOGE("Not able to find unambiguous field value in condition atom.");
            continue;
        }
        hashableDimensionKeys.push_back(HashableDimensionKey(conditionValues[0]));
        hashableDimensionKeys->push_back(HashableDimensionKey(conditionValueTrees[0]));
    }

    return hashableDimensionKeys;
}

}  // namespace statsd
+3 −2
Original line number Diff line number Diff line
@@ -40,8 +40,9 @@ ConditionState evaluateCombinationCondition(const std::vector<int>& children,
                                            const LogicalOperation& operation,
                                            const std::vector<ConditionState>& conditionCache);

std::vector<HashableDimensionKey> getDimensionKeysForCondition(
        const LogEvent& event, const MetricConditionLink& link);
void getDimensionKeysForCondition(
        const LogEvent& event, const MetricConditionLink& link,
        std::vector<HashableDimensionKey> *dimensionKeys);
}  // namespace statsd
}  // namespace os
}  // namespace android
Loading