[Stress] Redesign of MemCheckTests (#650)
authorVitaliy Urusovskij <vitaliy.urusovskij@intel.com>
Thu, 23 Jul 2020 08:07:13 +0000 (11:07 +0300)
committerGitHub <noreply@github.com>
Thu, 23 Jul 2020 08:07:13 +0000 (11:07 +0300)
* [Stress] Redesigned MemCheckTests: 1. Added MemCheckPipeline to incapsulate measures and logging. 2. Moved references to array

* [Stress] Added tracking of THREADS in MemCheckTests

tests/stress_tests/memcheck_tests/tests.cpp
tests/stress_tests/memcheck_tests/tests_pipelines/tests_pipelines.cpp
tests/stress_tests/memcheck_tests/tests_pipelines/tests_pipelines.h
tests/stress_tests/memcheck_tests/tests_utils.h
tests/stress_tests/scripts/memcheck_upload.py

index ce44db7..60baa84 100644 (file)
@@ -9,49 +9,87 @@
 
 #include <gtest/gtest.h>
 
-#define checkRefVmValues()                                                                          \
-    if (!Environment::Instance().getCollectResultsOnly()) {                                         \
-        ASSERT_GT(test_refs.ref_vmsize, 0) << "Reference value of VmSize is less than 0. Value: "   \
-                                           << test_refs.ref_vmsize;                                 \
-        ASSERT_GT(test_refs.ref_vmsize, 0) << "Reference value of VmPeak is less than 0. Value: "   \
-                                           << test_refs.ref_vmpeak;                                 \
-        ASSERT_GT(test_refs.ref_vmrss, 0) << "Reference value of VmRSS is less than 0. Value: "     \
-                                          << test_refs.ref_vmrss;                                   \
-        ASSERT_GT(test_refs.ref_vmrss, 0) << "Reference value of VmHWM is less than 0. Value: "     \
-                                          << test_refs.ref_vmhwm;                                   \
-    }
+#include <inference_engine.hpp>
+
+using namespace InferenceEngine;
+
 
 class MemCheckTestSuite : public ::testing::TestWithParam<TestCase> {
+public:
+    std::string test_name, model, model_name, device;
+    TestReferences test_refs;
+
+    void SetUp() override {
+        const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info();
+        test_name = std::string(test_info->name()).substr(0, std::string(test_info->name()).find('/'));
+        //const std::string full_test_name = std::string(test_info->test_case_name()) + "." + std::string(test_info->name());
+
+        const auto& test_params = GetParam();
+        model = test_params.model;
+        model_name = test_params.model_name;
+        device = test_params.device;
+
+        test_refs.collect_vm_values_for_test(test_name, test_params);
+        if (!Environment::Instance().getCollectResultsOnly()) {
+            ASSERT_GT(test_refs.references[VMSIZE], 0) << "Reference value of VmSize is less than 0. Value: "
+                                               << test_refs.references[VMSIZE];
+            ASSERT_GT(test_refs.references[VMPEAK], 0) << "Reference value of VmPeak is less than 0. Value: "
+                                               << test_refs.references[VMPEAK];
+            ASSERT_GT(test_refs.references[VMRSS], 0) << "Reference value of VmRSS is less than 0. Value: "
+                                              << test_refs.references[VMRSS];
+            ASSERT_GT(test_refs.references[VMHWM], 0) << "Reference value of VmHWM is less than 0. Value: "
+                                              << test_refs.references[VMHWM];
+        }
+    }
 };
 
 // tests_pipelines/tests_pipelines.cpp
 TEST_P(MemCheckTestSuite, create_exenetwork) {
-    std::string test_name = "create_exenetwork";
-    auto test_params = GetParam();
+    log_info("Create ExecutableNetwork from network: \"" << model
+                                                         << "\" for device: \"" << device << "\"");
+    auto test_pipeline = [&]{
+        MemCheckPipeline memCheckPipeline;
 
-    TestReferences test_refs;
-    test_refs.collect_vm_values_for_test(test_name, test_params);
+        Core ie;
+        ie.GetVersions(device);
+        CNNNetwork cnnNetwork = ie.ReadNetwork(model);
+        ExecutableNetwork exeNetwork = ie.LoadNetwork(cnnNetwork, device);
 
-    checkRefVmValues();
+        log_info("Memory consumption after LoadNetwork:");
+        memCheckPipeline.record_measures(test_name);
 
-    TestResult res = test_create_exenetwork(test_params.model_name, test_params.model, test_params.device,
-                                            test_refs.ref_vmsize, test_refs.ref_vmpeak, test_refs.ref_vmrss,
-                                            test_refs.ref_vmhwm);
+        log_debug(memCheckPipeline.get_reference_record_for_test(test_name, model_name, device));
+        return memCheckPipeline.measure();
+    };
+
+    TestResult res = common_test_pipeline(test_pipeline, test_refs.references);
     EXPECT_EQ(res.first, TestStatus::TEST_OK) << res.second;
 }
 
 TEST_P(MemCheckTestSuite, infer_request_inference) {
-    std::string test_name = "infer_request_inference";
-    auto test_params = GetParam();
+    log_info("Inference of InferRequest from network: \"" << model
+                                                          << "\" for device: \"" << device << "\"");
+    auto test_pipeline = [&]{
+        MemCheckPipeline memCheckPipeline;
 
-    TestReferences test_refs;
-    test_refs.collect_vm_values_for_test(test_name, test_params);
+        Core ie;
+        ie.GetVersions(device);
+        CNNNetwork cnnNetwork = ie.ReadNetwork(model);
+        ExecutableNetwork exeNetwork = ie.LoadNetwork(cnnNetwork, device);
+        InferRequest inferRequest = exeNetwork.CreateInferRequest();
+        inferRequest.Infer();
+        OutputsDataMap output_info(cnnNetwork.getOutputsInfo());
+        for (auto &output : output_info)
+            Blob::Ptr outputBlob = inferRequest.GetBlob(output.first);
+
+        log_info("Memory consumption after Inference:");
+        memCheckPipeline.record_measures(test_name);
 
-    checkRefVmValues();
+        log_debug(memCheckPipeline.get_reference_record_for_test(test_name, model_name, device));
+        return memCheckPipeline.measure();
+    };
 
-    TestResult res = test_infer_request_inference(test_params.model_name, test_params.model, test_params.device,
-                                                  test_refs.ref_vmsize, test_refs.ref_vmpeak, test_refs.ref_vmrss,
-                                                  test_refs.ref_vmhwm);
+    TestResult res = common_test_pipeline(test_pipeline, test_refs.references);
     EXPECT_EQ(res.first, TestStatus::TEST_OK) << res.second;
 }
 // tests_pipelines/tests_pipelines.cpp
index 171adc6..49f26aa 100644 (file)
 
 #include <string>
 #include <math.h>
-#include <chrono>
-
-#include <inference_engine.hpp>
 
 #define REPORTING_THRESHOLD 1.3
+// delimiter used for measurements print. Should be compatible with script parses tests logs
+#define MEMCHECK_DELIMITER "\t\t"
 
-using namespace InferenceEngine;
-
-#define getAlignedVmValues(vmsize, vmpeak, vmrss, vmhwm, vmsize_to_align, vmrss_to_align)   \
-        getVmValues(test_cur_vmsize, test_cur_vmpeak, test_cur_vmrss, test_cur_vmhwm);      \
-        test_cur_vmsize -= vmsize_before_test;                                              \
-        test_cur_vmpeak -= vmsize_before_test;                                              \
-        test_cur_vmrss -= vmrss_before_test;                                                \
-        test_cur_vmhwm -= vmrss_before_test;
-
-#define log_debug_ref_record_for_test(test_name)                                                            \
-        log_debug("Record to update reference config: "                                                           \
-                  << "<model path=\"" + model_name + "\"" + " test=\"" + test_name + "\" device=\"" +       \
-                  target_device +                                                                           \
-                  "\" vmsize=\"" + std::to_string((int) (test_cur_vmsize * REPORTING_THRESHOLD)) +          \
-                  "\" vmpeak=\"" + std::to_string((int) (test_cur_vmpeak * REPORTING_THRESHOLD)) +          \
-                  "\" vmrss=\"" + std::to_string((int) (test_cur_vmrss * REPORTING_THRESHOLD)) +            \
-                  "\" vmhwm=\"" + std::to_string((int) (test_cur_vmhwm * REPORTING_THRESHOLD)) + "\" />");
-
-#define log_info_ref_mem_usage()                                                                \
-        log_info("Reference values of virtual memory consumption:");                            \
-        log_info("VMRSS\t\tVMHWM\t\tVMSIZE\t\tVMPEAK");                                               \
-        log_info(ref_vmrss << "\t\t" << ref_vmhwm << "\t\t" << ref_vmsize << "\t\t" << ref_vmpeak);
-
-#define log_info_cur_mem_usage()                                                                                    \
-        log_info("Current values of virtual memory consumption:");                                                  \
-        log_info("VMRSS\t\tVMHWM\t\tVMSIZE\t\tVMPEAK");                                                                   \
-        log_info(test_cur_vmrss << "\t\t" << test_cur_vmhwm << "\t\t" << test_cur_vmsize << "\t\t" << test_cur_vmpeak);
-
-TestResult
-test_create_exenetwork(const std::string &model_name, const std::string &model_path, const std::string &target_device,
-                       const long &ref_vmsize, const long &ref_vmpeak, const long &ref_vmrss, const long &ref_vmhwm) {
-    log_info("Create ExecutableNetwork from network: \"" << model_path
-                                                         << "\" for device: \"" << target_device << "\"");
-    long vmsize_before_test = 0, vmrss_before_test = 0,
-            test_cur_vmsize = 0, test_cur_vmpeak = 0,
-            test_cur_vmrss = 0, test_cur_vmhwm = 0;
 
-    vmsize_before_test = (long) getVmSizeInKB();
-    vmrss_before_test = (long) getVmRSSInKB();
-
-    Core ie;
-    CNNNetwork cnnNetwork = ie.ReadNetwork(model_path);
-    ExecutableNetwork exeNetwork = ie.LoadNetwork(cnnNetwork, target_device);
-
-    getAlignedVmValues(test_cur_vmsize, test_cur_vmpeak, test_cur_vmrss, test_cur_vmhwm,
-                       vmsize_before_test, vmrss_before_test);
-
-    log_debug_ref_record_for_test("create_exenetwork");
-    log_info_ref_mem_usage();
-    log_info_cur_mem_usage();
-
-    if ((!Environment::Instance().getCollectResultsOnly()) && (test_cur_vmrss > ref_vmrss))
-        return TestResult(TestStatus::TEST_FAILED,
-                          "Test failed: RSS virtual memory consumption became greater than reference.\n"
-                          "Reference RSS memory consumption: " + std::to_string(ref_vmrss) + " KB.\n" +
-                          "Current RSS memory consumption: " + std::to_string(test_cur_vmrss) + " KB.\n");
-
-    if ((!Environment::Instance().getCollectResultsOnly()) && (test_cur_vmhwm > ref_vmhwm))
-        return TestResult(TestStatus::TEST_FAILED,
-                          "Test failed: HWM (peak of RSS) virtual memory consumption is greater than reference.\n"
-                          "Reference HWM of memory consumption: " + std::to_string(ref_vmhwm) + " KB.\n" +
-                          "Current HWM of memory consumption: " + std::to_string(test_cur_vmhwm) + " KB.\n");
-
-    return TestResult(TestStatus::TEST_OK, "");
+MemCheckPipeline::MemCheckPipeline() {
+    start_measures[VMRSS] = (long) getVmRSSInKB();
+    start_measures[VMHWM] = start_measures[VMRSS];
+    start_measures[VMSIZE] = (long) getVmSizeInKB();
+    start_measures[VMPEAK] = start_measures[VMSIZE];
+    start_measures[THREADS] = (long) getThreadsNum();
 }
 
-TestResult
-test_infer_request_inference(const std::string &model_name, const std::string &model_path,
-                             const std::string &target_device,
-                             const long &ref_vmsize, const long &ref_vmpeak, const long &ref_vmrss,
-                             const long &ref_vmhwm) {
-    log_info("Inference of InferRequest from network: \"" << model_path
-                                                          << "\" for device: \"" << target_device << "\"");
-    long vmsize_before_test = 0, vmrss_before_test = 0,
-            test_cur_vmsize = 0, test_cur_vmpeak = 0,
-            test_cur_vmrss = 0, test_cur_vmhwm = 0;
-    std::chrono::system_clock::time_point t_start, t_end;
-    std::chrono::duration<double> t_diff;
-
-    vmsize_before_test = (long) getVmSizeInKB();
-    vmrss_before_test = (long) getVmRSSInKB();
-
-    Core ie;
-    CNNNetwork cnnNetwork = ie.ReadNetwork(model_path);
-    ExecutableNetwork exeNetwork = ie.LoadNetwork(cnnNetwork, target_device);
-    InferRequest infer_request = exeNetwork.CreateInferRequest();
+std::array<long, MeasureValueMax> MemCheckPipeline::_measure() {
+    std::array<long, MeasureValueMax> measures;
+    measures[VMRSS] = (long) getVmRSSInKB();
+    measures[VMHWM] = (long) getVmHWMInKB();
+    measures[VMSIZE] = (long) getVmSizeInKB();
+    measures[VMPEAK] = (long) getVmPeakInKB();
+    measures[THREADS] = (long) getThreadsNum();     // TODO: resolve *-32295
+    return measures;
+}
 
-    log_info_ref_mem_usage();
+std::array<long, MeasureValueMax> MemCheckPipeline::measure() {
+    std::array<long, MeasureValueMax> measures = _measure();
+    std::transform(std::begin(measures), std::end(measures), std::begin(start_measures), std::begin(measures),
+                   [](long measure, long start_measure) -> long {
+                       return measure - start_measure;
+                   });
+    return measures;
+}
 
-    t_start = std::chrono::system_clock::now();
-    int seconds = 1;
-    do {
-        infer_request.Infer();
-        OutputsDataMap output_info(cnnNetwork.getOutputsInfo());
-        for (auto &output : output_info)
-            Blob::Ptr outputBlob = infer_request.GetBlob(output.first);
-        t_end = std::chrono::system_clock::now();
-        t_diff = t_end - t_start;
+void MemCheckPipeline::record_measures(const std::string & id) {
+    std::array<long, MeasureValueMax> measures = measure();
+    log_debug("[ MEASURE ] " << MEMCHECK_DELIMITER << id);
+    log_info(util::get_measure_values_headers(MEMCHECK_DELIMITER));
+    log_info(util::get_measure_values_as_str(measures, MEMCHECK_DELIMITER));
+}
 
-        getAlignedVmValues(test_cur_vmsize, test_cur_vmpeak, test_cur_vmrss, test_cur_vmhwm,
-                           vmsize_before_test, vmrss_before_test);
+std::string MemCheckPipeline::get_reference_record_for_test(std::string test_name, std::string model_name,
+                                              std::string target_device) {
+    std::array<long, MeasureValueMax> measures = measure();
+    std::stringstream ss;
+    ss << "Record to update reference config: "
+       << "<model path=\"" << model_name << "\"" <<
+       " test=\"" << test_name << "\" device=\"" << target_device <<
+       "\" vmsize=\"" << (int) (measures[VMSIZE] * REPORTING_THRESHOLD) <<
+       "\" vmpeak=\"" << (int) (measures[VMPEAK] * REPORTING_THRESHOLD) <<
+       "\" vmrss=\"" << (int) (measures[VMRSS] * REPORTING_THRESHOLD) <<
+       "\" vmhwm=\"" << (int) (measures[VMHWM] * REPORTING_THRESHOLD) << "\" />";
+    return ss.str();
+}
 
-        if (t_diff.count() > (double) (seconds)) {
-            log_info("Current values of virtual memory consumption after " << seconds << " seconds:");
-            log_info("VMRSS\t\tVMHWM\t\tVMSIZE\t\tVMPEAK");
-            log_info(test_cur_vmrss << "\t\t" << test_cur_vmhwm << "\t\t" << test_cur_vmsize << "\t\t" << test_cur_vmpeak);
-            seconds++;
-        }
-    } while (t_diff.count() < 5);
+TestResult common_test_pipeline(const std::function<std::array<long, MeasureValueMax>()>& test_pipeline,
+                                const std::array<long, MeasureValueMax> &references) {
+    log_info("Reference values of virtual memory consumption:");
+    log_info(util::get_measure_values_headers(MEMCHECK_DELIMITER));
+    log_info(util::get_measure_values_as_str(references, MEMCHECK_DELIMITER));
 
-    log_debug_ref_record_for_test("infer_request_inference");
+    std::array<long, MeasureValueMax> measures = test_pipeline();
 
-    if ((!Environment::Instance().getCollectResultsOnly()) && (test_cur_vmrss > ref_vmrss))
+    if ((!Environment::Instance().getCollectResultsOnly()) && (measures[VMRSS] > references[VMRSS]))
         return TestResult(TestStatus::TEST_FAILED,
                           "Test failed: RSS virtual memory consumption became greater than reference.\n"
-                          "Reference RSS memory consumption: " + std::to_string(ref_vmrss) + " KB.\n" +
-                          "Current RSS memory consumption: " + std::to_string(test_cur_vmrss) + " KB.\n");
+                          "Reference RSS memory consumption: " + std::to_string(references[VMRSS]) + " KB.\n" +
+                          "Current RSS memory consumption: " + std::to_string(measures[VMRSS]) + " KB.\n");
 
-    if ((!Environment::Instance().getCollectResultsOnly()) && (test_cur_vmhwm > ref_vmhwm))
+    if ((!Environment::Instance().getCollectResultsOnly()) && (measures[VMHWM] > references[VMHWM]))
         return TestResult(TestStatus::TEST_FAILED,
                           "Test failed: HWM (peak of RSS) virtual memory consumption is greater than reference.\n"
-                          "Reference HWM of memory consumption: " + std::to_string(ref_vmhwm) + " KB.\n" +
-                          "Current HWM of memory consumption: " + std::to_string(test_cur_vmhwm) + " KB.\n");
+                          "Reference HWM of memory consumption: " + std::to_string(references[VMHWM]) + " KB.\n" +
+                          "Current HWM of memory consumption: " + std::to_string(measures[VMHWM]) + " KB.\n");
 
     return TestResult(TestStatus::TEST_OK, "");
 }
index c12f1c3..f3f36dc 100644 (file)
@@ -4,14 +4,56 @@
 
 #pragma once
 
+#include "../tests_utils.h"
 #include "../../common/tests_utils.h"
 #include "../../common/utils.h"
 
 #include <string>
 
 // tests_pipelines/tests_pipelines.cpp
-TestResult test_create_exenetwork(const std::string &model_name, const std::string &model_path, const std::string &target_device,
-                                  const long &ref_vmsize, const long &ref_vmpeak, const long &ref_vmrss, const long &ref_vmhwm);
-TestResult test_infer_request_inference(const std::string &model_name, const std::string &model_path, const std::string &target_device,
-                                        const long &ref_vmsize, const long &ref_vmpeak, const long &ref_vmrss, const long &ref_vmhwm);
+/**
+ * @brief Class response for encapsulating measure and measurements printing
+ *
+ * Current class measures only in scope of it's lifetime. In this case need
+ * to note that deletion of objects created before class creation may lead
+ * to negative values because of alignment on starting values.
+ * Also deletion of objects created in scope of class lifetime may decrease
+ * values computed on previous measure.
+ */
+class MemCheckPipeline {
+private:
+    std::array<long, MeasureValueMax> start_measures;      // measures before run (will be used as baseline)
+
+    /**
+     * @brief Measures values at the current point of time
+     */
+    std::array<long, MeasureValueMax> _measure();
+public:
+    /**
+     * @brief Constructs MemCheckPipeline object and
+     *        measure values to use as baseline
+     */
+    MemCheckPipeline();
+
+    /**
+     * @brief Measures values at the current point of time and
+     *        returns measurements aligned on a baseline
+     */
+    std::array<long, MeasureValueMax> measure();
+
+    /**
+     * @brief Measures values and records aligned measurements using provided identifier
+     *        provided identifier
+     */
+    void record_measures(const std::string & id);
+
+    /**
+     * @brief Prepares string used for fast generation of file with references
+     */
+    std::string get_reference_record_for_test(std::string test_name, std::string model_name,
+                                              std::string target_device);
+};
+
+TestResult common_test_pipeline(const std::function<std::array<long, MeasureValueMax>()>& test_pipeline,
+                                const std::array<long, MeasureValueMax> &references);
 // tests_pipelines/tests_pipelines.cpp
index 23d4398..670a182 100644 (file)
@@ -2,10 +2,35 @@
 // SPDX-License-Identifier: Apache-2.0
 //
 
+#pragma once
+
 #include "../common/tests_utils.h"
 
 #include <pugixml.hpp>
 
+// Measure values
+enum MeasureValue { VMRSS = 0, VMHWM, VMSIZE, VMPEAK, THREADS, MeasureValueMax };
+// Measure values headers
+const std::array<std::string, MeasureValueMax> MeasureValueHeader { "VMRSS", "VMHWM", "VMSIZE", "VMPEAK", "THREADS" };
+
+namespace util {
+    template <typename Type>
+    static std::string get_measure_values_as_str(const std::array<Type, MeasureValueMax> & array,
+                                                 const std::string & delimiter = "\t\t") {
+        std::string str = std::to_string(*array.begin());
+        for (auto it = array.begin() + 1; it != array.end(); it++)
+            str += delimiter + std::to_string(*it);
+        return str;
+    }
+
+    static std::string get_measure_values_headers(const std::string & delimiter = "\t\t") {
+        std::string str = *MeasureValueHeader.begin();
+        for (auto it = MeasureValueHeader.begin() + 1; it != MeasureValueHeader.end(); it++)
+            str += delimiter + *it;
+        return str;
+    }
+}
+
 class MemCheckEnvironment {
 private:
     pugi::xml_document _refs_config;
@@ -32,9 +57,11 @@ private:
     std::vector<std::string> model_path_v, test_name_v, device_v;
     std::vector<long> vmsize_v, vmpeak_v, vmrss_v, vmhwm_v;
 public:
-    long ref_vmsize = -1, ref_vmpeak = -1, ref_vmrss = -1, ref_vmhwm = -1;
+    std::array<long, MeasureValueMax> references;
 
     TestReferences () {
+        std::fill(references.begin(), references.end(), -1);
+
         // Parse RefsConfig from MemCheckEnvironment
         std::string models_path = Environment::Instance().getEnvConfig()
                 .child("attributes").child("irs_path").child("value").text().as_string();
@@ -68,10 +95,10 @@ public:
             if (test_name_v[i] == test_name)
                 if (model_path_v[i] == test_params.model)
                     if (device_v[i] == test_params.device) {
-                        ref_vmsize = vmsize_v[i];
-                        ref_vmpeak = vmpeak_v[i];
-                        ref_vmrss = vmrss_v[i];
-                        ref_vmhwm = vmhwm_v[i];
+                        references[VMSIZE] = vmsize_v[i];
+                        references[VMPEAK] = vmpeak_v[i];
+                        references[VMRSS] = vmrss_v[i];
+                        references[VMHWM] = vmhwm_v[i];
                     }
     }
 };
index 1163452..0569a98 100644 (file)
@@ -30,8 +30,7 @@ DB_COLLECTIONS = ["commit", "nightly", "weekly"]
 
 PRODUCT_NAME = 'dldt'   # product name from build manifest
 RE_GTEST_MODEL_XML = re.compile(r'<model[^>]*>')
-RE_GTEST_CUR_MEASURE = re.compile(
-    r'Current values of virtual memory consumption')
+RE_GTEST_CUR_MEASURE = re.compile(r'\[\s*MEASURE\s*\]')
 RE_GTEST_REF_MEASURE = re.compile(
     r'Reference values of virtual memory consumption')
 RE_GTEST_PASSED = re.compile(r'\[\s*PASSED\s*\]')
@@ -99,13 +98,14 @@ def parse_memcheck_log(log_path):
             ref_metrics = dict(zip(heading, values))
     for index in reversed(range(len(log_lines))):
         if RE_GTEST_CUR_MEASURE.search(log_lines[index]):
+            test_name = log_lines[index].split()[-1]
             heading = [name.lower() for name in log_lines[index+1]
                        [len(GTEST_INFO):].split()]
             values = [int(val) for val in log_lines[index+2]
                       [len(GTEST_INFO):].split()]
             entry = SimpleNamespace(
                 metrics=dict(zip(heading, values)),
-                test_name=model['test'],
+                test_name=test_name,
                 model_name=os.path.splitext(
                     os.path.basename(model['path']))[0],
                 precision=next(pr for pr in PRECISSIONS if pr.upper()