Avoid creating temporary objects in FiterValue().

It reduces the cpu time from 1000ns to 750ns

Test: statsd test.
Change-Id: Ifa7e98e3368f8d55f85c7b09d05a6c416482981d
diff --git a/cmds/statsd/Android.mk b/cmds/statsd/Android.mk
index 740fdc0..dbcc888 100644
--- a/cmds/statsd/Android.mk
+++ b/cmds/statsd/Android.mk
@@ -239,7 +239,8 @@
                    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)
 
diff --git a/cmds/statsd/benchmark/filter_value_benchmark.cpp b/cmds/statsd/benchmark/filter_value_benchmark.cpp
new file mode 100644
index 0000000..b9ddf36
--- /dev/null
+++ b/cmds/statsd/benchmark/filter_value_benchmark.cpp
@@ -0,0 +1,53 @@
+/*
+ * 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
diff --git a/cmds/statsd/src/FieldValue.cpp b/cmds/statsd/src/FieldValue.cpp
index 6894bcf..b541612 100644
--- a/cmds/statsd/src/FieldValue.cpp
+++ b/cmds/statsd/src/FieldValue.cpp
@@ -135,6 +135,8 @@
         case STRING:
             str_value = from.str_value;
             break;
+        default:
+            break;
     }
 }
 
@@ -148,6 +150,8 @@
             return std::to_string(float_value) + "[F]";
         case STRING:
             return str_value + "[S]";
+        default:
+            return "[UNKNOWN]";
     }
 }
 
@@ -163,6 +167,8 @@
             return float_value == that.float_value;
         case STRING:
             return str_value == that.str_value;
+        default:
+            return false;
     }
 }
 
@@ -177,6 +183,8 @@
             return float_value != that.float_value;
         case STRING:
             return str_value != that.str_value;
+        default:
+            return false;
     }
 }
 
diff --git a/cmds/statsd/src/FieldValue.h b/cmds/statsd/src/FieldValue.h
index d17dded..21f30e2 100644
--- a/cmds/statsd/src/FieldValue.h
+++ b/cmds/statsd/src/FieldValue.h
@@ -31,7 +31,7 @@
 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 @@
     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 Value {
+    Value() : type(UNKNOWN) {}
+
     Value(int32_t v) {
         int_value = v;
         type = INT;
@@ -280,15 +284,13 @@
     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 {
diff --git a/cmds/statsd/src/HashableDimensionKey.cpp b/cmds/statsd/src/HashableDimensionKey.cpp
index d901bd6..7b21fb0 100644
--- a/cmds/statsd/src/HashableDimensionKey.cpp
+++ b/cmds/statsd/src/HashableDimensionKey.cpp
@@ -16,6 +16,8 @@
 #define DEBUG false  // STOPSHIP if true
 #include "Log.h"
 
+#include <mutex>
+
 #include "HashableDimensionKey.h"
 #include "FieldValue.h"
 
@@ -48,6 +50,8 @@
                 hash = android::JenkinsHashMixBytes(hash, (uint8_t*)&floatVal, sizeof(float));
                 break;
             }
+            default:
+                break;
         }
     }
     return JenkinsHashWhiten(hash);
@@ -62,26 +66,32 @@
     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]);
             }
@@ -117,23 +127,23 @@
             // 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]);
             }
diff --git a/cmds/statsd/src/stats_log_util.cpp b/cmds/statsd/src/stats_log_util.cpp
index 2c7b919..78ebe33 100644
--- a/cmds/statsd/src/stats_log_util.cpp
+++ b/cmds/statsd/src/stats_log_util.cpp
@@ -183,6 +183,8 @@
                 case STRING:
                     protoOutput->write(FIELD_TYPE_STRING | fieldNum, dim.mValue.str_value);
                     break;
+                default:
+                    break;
             }
             (*index)++;
         } else if (valueDepth > depth && valuePrefix == prefix) {