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

Commit d5aa01b3 authored by Yao Chen's avatar Yao Chen
Browse files

Remove the hacky HashableDimensionKey.

+ Add a real HashableDimensionKey as a wrapper of the dimension.
So we can get rid of the maps that we kept.

Pay down technical debt and reduce memory usage.

Test: statsd_test & manual
Change-Id: I233280cf1e2ce93da6a8cd4e8514abb066f4016d
parent d10f7b1c
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -54,7 +54,7 @@ statsd_common_src := \
    src/storage/StorageManager.cpp \
    src/StatsLogProcessor.cpp \
    src/StatsService.cpp \
    src/stats_util.cpp \
    src/HashableDimensionKey.cpp \
    src/guardrail/MemoryLeakTrackUtil.cpp \
    src/guardrail/StatsdStats.cpp

@@ -174,7 +174,8 @@ LOCAL_SRC_FILES := \
    tests/metrics/EventMetricProducer_test.cpp \
    tests/metrics/ValueMetricProducer_test.cpp \
    tests/metrics/GaugeMetricProducer_test.cpp \
    tests/guardrail/StatsdStats_test.cpp
    tests/guardrail/StatsdStats_test.cpp \
    tests/metrics/metrics_test_helper.cpp

LOCAL_STATIC_LIBRARIES := \
    $(statsd_common_static_libraries) \
+110 −0
Original line number Diff line number Diff line
@@ -13,19 +13,17 @@
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "stats_util.h"
#include "HashableDimensionKey.h"

namespace android {
namespace os {
namespace statsd {

// There is no existing hash function for the dimension key ("repeated KeyValuePair").
// Temporarily use a string concatenation as the hashable key.
// TODO: Find a better hash function for std::vector<KeyValuePair>.
HashableDimensionKey getHashableKey(std::vector<KeyValuePair> keys) {
    std::string flattened;
    for (const KeyValuePair& pair : keys) {
using std::string;

string HashableDimensionKey::toString() const {
    string flattened;
    for (const auto& pair : mKeyValuePairs) {
        flattened += std::to_string(pair.key());
        flattened += ":";
        switch (pair.value_case()) {
@@ -52,6 +50,61 @@ HashableDimensionKey getHashableKey(std::vector<KeyValuePair> keys) {
    return flattened;
}

bool HashableDimensionKey::operator==(const HashableDimensionKey& that) const {
    const auto& keyValue2 = that.getKeyValuePairs();
    if (mKeyValuePairs.size() != keyValue2.size()) {
        return false;
    }

    for (size_t i = 0; i < keyValue2.size(); i++) {
        const auto& kv1 = mKeyValuePairs[i];
        const auto& kv2 = keyValue2[i];
        if (kv1.key() != kv2.key()) {
            return false;
        }

        if (kv1.value_case() != kv2.value_case()) {
            return false;
        }

        switch (kv1.value_case()) {
            case KeyValuePair::ValueCase::kValueStr:
                if (kv1.value_str() != kv2.value_str()) {
                    return false;
                }
                break;
            case KeyValuePair::ValueCase::kValueInt:
                if (kv1.value_int() != kv2.value_int()) {
                    return false;
                }
                break;
            case KeyValuePair::ValueCase::kValueLong:
                if (kv1.value_long() != kv2.value_long()) {
                    return false;
                }
                break;
            case KeyValuePair::ValueCase::kValueBool:
                if (kv1.value_bool() != kv2.value_bool()) {
                    return false;
                }
                break;
            case KeyValuePair::ValueCase::kValueFloat: {
                if (kv1.value_float() != kv2.value_float()) {
                    return false;
                }
                break;
            }
            case KeyValuePair::ValueCase::VALUE_NOT_SET:
                break;
        }
    }
    return true;
};

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

}  // namespace statsd
}  // namespace os
}  // namespace android
 No newline at end of file
+102 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2017 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.
 */

#pragma once

#include <utils/JenkinsHash.h>
#include "frameworks/base/cmds/statsd/src/stats_log.pb.h"

namespace android {
namespace os {
namespace statsd {

class HashableDimensionKey {
public:
    explicit HashableDimensionKey(const std::vector<KeyValuePair>& keyValuePairs)
        : mKeyValuePairs(keyValuePairs){};

    HashableDimensionKey(){};

    HashableDimensionKey(const HashableDimensionKey& that)
        : mKeyValuePairs(that.getKeyValuePairs()){};

    HashableDimensionKey& operator=(const HashableDimensionKey& from) = default;

    std::string toString() const;

    inline const std::vector<KeyValuePair>& getKeyValuePairs() const {
        return mKeyValuePairs;
    }

    bool operator==(const HashableDimensionKey& that) const;

    bool operator<(const HashableDimensionKey& that) const;

    inline const char* c_str() const {
        return toString().c_str();
    }

private:
    std::vector<KeyValuePair> mKeyValuePairs;
};

}  // namespace statsd
}  // namespace os
}  // namespace android

namespace std {

using android::os::statsd::HashableDimensionKey;
using android::os::statsd::KeyValuePair;

template <>
struct hash<HashableDimensionKey> {
    std::size_t operator()(const HashableDimensionKey& key) const {
        android::hash_t hash = 0;
        for (const auto& pair : key.getKeyValuePairs()) {
            hash = android::JenkinsHashMix(hash, android::hash_type(pair.key()));
            hash = android::JenkinsHashMix(
                    hash, android::hash_type(static_cast<int32_t>(pair.value_case())));
            switch (pair.value_case()) {
                case KeyValuePair::ValueCase::kValueStr:
                    hash = android::JenkinsHashMix(
                            hash,
                            static_cast<uint32_t>(std::hash<std::string>()(pair.value_str())));
                    break;
                case KeyValuePair::ValueCase::kValueInt:
                    hash = android::JenkinsHashMix(hash, android::hash_type(pair.value_int()));
                    break;
                case KeyValuePair::ValueCase::kValueLong:
                    hash = android::JenkinsHashMix(
                            hash, android::hash_type(static_cast<int64_t>(pair.value_long())));
                    break;
                case KeyValuePair::ValueCase::kValueBool:
                    hash = android::JenkinsHashMix(hash, android::hash_type(pair.value_bool()));
                    break;
                case KeyValuePair::ValueCase::kValueFloat: {
                    float floatVal = pair.value_float();
                    hash = android::JenkinsHashMixBytes(hash, (uint8_t*)&floatVal, sizeof(float));
                    break;
                }
                case KeyValuePair::ValueCase::VALUE_NOT_SET:
                    break;
            }
        }
        return hash;
    }
};

}  // namespace std
+1 −1
Original line number Diff line number Diff line
@@ -279,7 +279,7 @@ void SimpleConditionTracker::evaluateCondition(const LogEvent& event,
    }

    // outputKey is the output key values. e.g, uid:1234
    const HashableDimensionKey outputKey = getHashableKey(getDimensionKey(event, mOutputDimension));
    const HashableDimensionKey outputKey(getDimensionKey(event, mOutputDimension));
    handleConditionEvent(outputKey, matchedState == 1, conditionCache, conditionChangedCache);
}

+1 −1
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ HashableDimensionKey getDimensionKeyForCondition(const LogEvent& event,
        kv.set_key(link.key_in_condition(i).key());
    }

    return getHashableKey(dimensionKey);
    return HashableDimensionKey(dimensionKey);
}

}  // namespace statsd
Loading