diff --git a/test/test_perf/test_api.cpp b/test/test_perf/test_api.cpp index 800b9415703243693da896590eee28d6d9c1a9ba..2b72ceea161ef6821019e51566d758d0c32cfe3e 100644 --- a/test/test_perf/test_api.cpp +++ b/test/test_perf/test_api.cpp @@ -1,3 +1,17 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * libkperf licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: Mr.Gan + * Create: 2024-04-24 + * Description: Unit tests for api functions. + ******************************************************************************/ #include #include #include "util_time.h" diff --git a/test/test_perf/test_common.cpp b/test/test_perf/test_common.cpp index 052b93b45d5dc99ba4fda4c0757cb3150f8ae142..6d0b00d4ecf013bd061926c95e65a81e16c625b3 100644 --- a/test/test_perf/test_common.cpp +++ b/test/test_perf/test_common.cpp @@ -1,3 +1,17 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * libkperf licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: Mr.Gan + * Create: 2024-04-24 + * Description: Common functions for unit test. + ******************************************************************************/ #include #include #include "process_map.h" diff --git a/test/test_perf/test_count.cpp b/test/test_perf/test_count.cpp new file mode 100644 index 0000000000000000000000000000000000000000..9b566c14823a3661f41af1b3eefd853a42241585 --- /dev/null +++ b/test/test_perf/test_count.cpp @@ -0,0 +1,161 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * libkperf licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: Mr.Gan + * Create: 2024-04-24 + * Description: Unit test for counting. + ******************************************************************************/ +#include "test_common.h" + +using namespace std; + +class TestCount : public testing::Test { +public: + void TearDown() + { + if (appPid != 0) { + KillApp(appPid); + appPid = 0; + } + if (data != nullptr) { + PmuDataFree(data); + data = nullptr; + } + PmuClose(pd); + } + +protected: + int pd; + pid_t appPid = 0; + PmuData *data = nullptr; + static const unsigned collectInterval = 100; +}; + +TEST_F(TestCount, CountProcess) +{ + // Count a process with one event. + appPid = RunTestApp("simple"); + int pidList[1] = {appPid}; + char *evtList[1] = {"r11"}; + PmuAttr attr = {0}; + attr.pidList = pidList; + attr.numPid = 1; + attr.evtList = evtList; + attr.numEvt = 1; + + pd = PmuOpen(COUNTING, &attr); + int ret = PmuCollect(pd, 100, collectInterval); + ASSERT_EQ(ret, SUCCESS); + int len = PmuRead(pd, &data); + // Only one sample, only one buffer for one pid. + ASSERT_EQ(len, 1); + ASSERT_TRUE(CheckDataEvt(data, len, "r11")); + ASSERT_TRUE(CheckDataPid(data, len, appPid)); +} + +TEST_F(TestCount, CountSystem) +{ + // Count system with one event. + char *evtList[1] = {"r11"}; + PmuAttr attr = {0}; + attr.evtList = evtList; + attr.numEvt = 1; + + pd = PmuOpen(COUNTING, &attr); + int ret = PmuCollect(pd, 100, collectInterval); + ASSERT_EQ(ret, SUCCESS); + int len = PmuRead(pd, &data); + // Only one sample, only one buffer for one pid. + ASSERT_EQ(len, GetCpuNums()); + ASSERT_TRUE(CheckDataEvt(data, len, "r11")); +} + +TEST_F(TestCount, OpenDDRC) +{ + // Open flux_rd and flux_wr of all DDRC device. + vector eventNames; + vector scclIdx = {1, 3, 5, 7}; + vector ddrcIdx = {0, 1, 2, 3}; + for (auto sccl : scclIdx) { + for (auto ddrc : ddrcIdx) { + const unsigned maxEvtLen =1024; + char *fluxRdEvt = new char[maxEvtLen]; + snprintf(fluxRdEvt, maxEvtLen, "hisi_sccl%d_ddrc%d/flux_rd/",sccl,ddrc); + char *fluxWrEvt = new char[maxEvtLen]; + snprintf(fluxWrEvt, maxEvtLen, "hisi_sccl%d_ddrc%d/flux_wr/",sccl,ddrc); + eventNames.push_back(fluxRdEvt); + eventNames.push_back(fluxWrEvt); + } + } + PmuAttr attr = {0}; + attr.evtList = eventNames.data(); + attr.numEvt = eventNames.size(); + + pd = PmuOpen(COUNTING, &attr); + ASSERT_NE(pd, -1); + for (auto evt : eventNames) { + delete[] evt; + } +} + +TEST_F(TestCount, NumaFluxWr) +{ + // Test data of uncore event ddrc/flux_wr/. + + // Run application which will write memory on numa node 2. + appPid = RunTestApp("write_on_numa2"); + + // Prepare ddr events. + char *evtList[4] = {"hisi_sccl5_ddrc0/flux_wr/", "hisi_sccl5_ddrc1/flux_wr/", "hisi_sccl5_ddrc2/flux_wr/", "hisi_sccl5_ddrc3/flux_wr/"}; + PmuAttr attr = {0}; + attr.evtList = evtList; + attr.numEvt = 4; + + // Collect pmu data. + pd = PmuOpen(COUNTING, &attr); + ASSERT_NE(pd, -1); + DelayContinue(appPid, 100); + int ret = PmuCollect(pd, 8000, collectInterval); + ASSERT_EQ(ret, SUCCESS); + int len = PmuRead(pd, &data); + ASSERT_EQ(len, 4); + + // Check flux event count which should be greater than total memory bytes divided by 256 bits. + size_t cntSum = 0; + for (int i=0;icount, 0); +} \ No newline at end of file diff --git a/test/test_perf/test_pmu.cpp b/test/test_perf/test_pmu.cpp new file mode 100644 index 0000000000000000000000000000000000000000..542ac709ab3e075d57cb822200f63b5e75166b57 --- /dev/null +++ b/test/test_perf/test_pmu.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * libkperf licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: Mr.Gan + * Create: 2024-04-24 + * Description: Common functions for pmu sampling. + ******************************************************************************/ +#include "test_common.h" + +using namespace std; + +class TestPMU : public testing::Test { +public: + void TearDown() + { + if (appPid != 0) { + KillApp(appPid); + appPid = 0; + } + if (data != nullptr) { + PmuDataFree(data); + data = nullptr; + } + PmuClose(pd); + } + +protected: + PmuAttr GetSystemAttribute() + { + PmuAttr attr = {0}; + attr.evtList = evtList; + attr.numEvt = 1; + attr.pidList = nullptr; + attr.numPid = 0; + attr.cpuList = nullptr; + attr.numCpu = 0; + attr.freq = 1000; + attr.useFreq = 1; + return attr; + } + + PmuAttr GetProcAttribute(pid_t pid[], int nums) + { + auto attr = GetSystemAttribute(); + attr.pidList = pid; + attr.numPid = nums; + return attr; + } + + int Collect(PmuAttr &attr, PmuData **data, int sec = 1) + { + pd = PmuOpen(SAMPLING, &attr); + int ret = PmuCollect(pd, 1000 * sec, collectInterval); + int len = PmuRead(pd, data); + return len; + } + + int pd; + pid_t appPid = 0; + char *evtList[1] = {"r11"}; + PmuData *data = nullptr; + static const unsigned collectInterval = 100; +}; + +TEST_F(TestPMU, PmuSystemCollectTwoThreads) +{ + // Start a two-thread process. + appPid = RunTestApp("test_create_thread"); + auto attr = GetSystemAttribute(); + // Start sampling for SYSTEM. + pd = PmuOpen(SAMPLING, &attr); + usleep(1000); + // Tell process to create thread. + kill(appPid, SIGCONT); + int ret = PmuCollect(pd, 100, collectInterval); + int len = PmuRead(pd, &data); + ASSERT_TRUE(data != nullptr); + ASSERT_TRUE(FoundAllTids(data, len, appPid)); +} + +TEST_F(TestPMU, PmuProcCollectTwoThreads) +{ + // Start a two-thread process. + appPid = RunTestApp("test_create_thread"); + pid_t pidList[1] = {appPid}; + auto attr = GetProcAttribute(pidList, 1); + // Start sampling for PROCESS. + pd = PmuOpen(SAMPLING, &attr); + usleep(1000); + // Tell process to create thread. + DelayContinue(appPid, 100); + int ret = PmuCollect(pd, 1000, collectInterval); + int len = PmuRead(pd, &data); + ASSERT_TRUE(data != nullptr); + ASSERT_TRUE(FoundAllTids(data, len, appPid)); +} + +TEST_F(TestPMU, PmuSystemCollect12Threads) +{ + // Start a 12-thread process. + // Threads are created on startup. + appPid = RunTestApp("test_12threads"); + auto attr = GetSystemAttribute(); + // Start sampling for system. + int len = Collect(attr, &data); + ASSERT_TRUE(data != nullptr); + // Check all threads are sampled. + ASSERT_TRUE(FoundAllTids(data, len, appPid)); +} + +TEST_F(TestPMU, PmuProcCollect12Threads) +{ + // Start a 12-thread process. + // Threads are created on startup. + appPid = RunTestApp("test_12threads"); + pid_t pidList[1] = {appPid}; + auto attr = GetProcAttribute(pidList, 1); + // Start sampling for process. + int len = Collect(attr, &data); + ASSERT_TRUE(data != nullptr); + // Check all threads are sampled. + ASSERT_TRUE(FoundAllTids(data, len, appPid)); +} + +TEST_F(TestPMU, PmuSystemCollectSubProc) +{ + // Start a process that will for child. + appPid = RunTestApp("test_fork"); + auto attr = GetSystemAttribute(); + // Start sampling for SYSTEM. + pd = PmuOpen(SAMPLING, &attr); + usleep(1000); + // Tell process to create thread. + kill(appPid, SIGCONT); + int ret = PmuCollect(pd, 100, collectInterval); + int len = PmuRead(pd, &data); + ASSERT_TRUE(data != nullptr); + ASSERT_TRUE(FoundAllChildren(data, len, appPid)); +} + +TEST_F(TestPMU, PmuProcCollectSubProc) +{ + // Start a process that will for child. + appPid = RunTestApp("test_fork"); + pid_t pidList[1] = {appPid}; + auto attr = GetProcAttribute(pidList, 1); + // Start sampling for SYSTEM. + pd = PmuOpen(SAMPLING, &attr); + usleep(1000); + // Tell process to create thread. + kill(appPid, SIGCONT); + int ret = PmuCollect(pd, 1000, collectInterval); + int len = PmuRead(pd, &data); + ASSERT_TRUE(data != nullptr); + ASSERT_TRUE(FoundAllChildren(data, len, appPid)); +} \ No newline at end of file diff --git a/test/test_perf/test_spe.cpp b/test/test_perf/test_spe.cpp new file mode 100644 index 0000000000000000000000000000000000000000..40fb40db2d363c7742ce0ef7a6b58edb4e0e7f79 --- /dev/null +++ b/test/test_perf/test_spe.cpp @@ -0,0 +1,163 @@ +/****************************************************************************** + * Copyright (c) Huawei Technologies Co., Ltd. 2024. All rights reserved. + * libkperf licensed under the Mulan PSL v2. + * You can use this software according to the terms and conditions of the Mulan PSL v2. + * You may obtain a copy of Mulan PSL v2 at: + * http://license.coscl.org.cn/MulanPSL2 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR + * PURPOSE. + * See the Mulan PSL v2 for more details. + * Author: Mr.Gan + * Create: 2024-04-24 + * Description: Common functions for spe sampling. + ******************************************************************************/ +#include "test_common.h" + +using namespace std; + +class TestSPE : public testing::Test { +public: + void TearDown() + { + if (appPid != 0) { + KillApp(appPid); + appPid = 0; + } + if (data != nullptr) { + PmuDataFree(data); + data = nullptr; + } + PmuClose(pd); + } + +protected: + PmuAttr GetSystemAttribute() + { + PmuAttr attr = {0}; + attr.pidList = nullptr; + attr.numPid = 0; + attr.cpuList = nullptr; + attr.numCpu = 0; + attr.period = 1000; + attr.useFreq = 0; + attr.dataFilter = SPE_DATA_ALL; + attr.evFilter = SPE_EVENT_RETIRED; + attr.minLatency = 0x40; + return attr; + } + + PmuAttr GetProcAttribute(pid_t pid[], int nums) + { + auto attr = GetSystemAttribute(); + attr.pidList = pid; + attr.numPid = nums; + return attr; + } + + int SpeCollect(PmuAttr &attr, PmuData **data, int sec = 1) + { + pd = PmuOpen(SPE_SAMPLING, &attr); + int ret = PmuCollect(pd, 1000 * sec, collectInterval); + int len = PmuRead(pd, data); + return len; + } + + int pd; + pid_t appPid = 0; + PmuData *data = nullptr; + static const unsigned collectInterval = 100; +}; + +TEST_F(TestSPE, SpeSystemCollectTwoThreads) +{ + // Start a two-thread process. + appPid = RunTestApp("test_create_thread"); + auto attr = GetSystemAttribute(); + // Start sampling for SYSTEM. + pd = PmuOpen(SPE_SAMPLING, &attr); + ASSERT_NE(pd, -1); + usleep(1000); + // Tell process to create thread. + DelayContinue(appPid, 100); + int ret = PmuCollect(pd, 500, collectInterval); + int len = PmuRead(pd, &data); + ASSERT_TRUE(data != nullptr); + ASSERT_TRUE(FoundAllTids(data, len, appPid)); +} + +TEST_F(TestSPE, SpeProcCollectTwoThreads) +{ + // Start a two-thread process. + appPid = RunTestApp("test_create_thread"); + pid_t pidList[1] = {appPid}; + auto attr = GetProcAttribute(pidList, 1); + // Start sampling for PROCESS. + pd = PmuOpen(SPE_SAMPLING, &attr); + usleep(1000); + // Tell process to create thread. + DelayContinue(appPid, 100); + int ret = PmuCollect(pd, 1000, collectInterval); + int len = PmuRead(pd, &data); + ASSERT_TRUE(data != nullptr); + ASSERT_TRUE(FoundAllTids(data, len, appPid)); +} + +TEST_F(TestSPE, SpeSystemCollect12Threads) +{ + // Start a 12-thread process. + // Threads are created on startup. + appPid = RunTestApp("test_12threads"); + auto attr = GetSystemAttribute(); + // Start sampling for system. + int len = SpeCollect(attr, &data); + ASSERT_TRUE(data != nullptr); + // Check all threads are sampled. + ASSERT_TRUE(FoundAllTids(data, len, appPid)); +} + +TEST_F(TestSPE, SpeProcCollect12Threads) +{ + // Start a 12-thread process. + // Threads are created on startup. + appPid = RunTestApp("test_12threads"); + pid_t pidList[1] = {appPid}; + auto attr = GetProcAttribute(pidList, 1); + // Start sampling for process. + int len = SpeCollect(attr, &data); + ASSERT_TRUE(data != nullptr); + // Check all threads are sampled. + ASSERT_TRUE(FoundAllTids(data, len, appPid)); +} + +TEST_F(TestSPE, SpeSystemCollectSubProc) +{ + // Start a process that will for child. + appPid = RunTestApp("test_fork"); + auto attr = GetSystemAttribute(); + // Start sampling for SYSTEM. + pd = PmuOpen(SPE_SAMPLING, &attr); + usleep(1000); + // Tell process to create thread. + kill(appPid, SIGCONT); + int ret = PmuCollect(pd, 100, collectInterval); + int len = PmuRead(pd, &data); + ASSERT_TRUE(data != nullptr); + ASSERT_TRUE(FoundAllChildren(data, len, appPid)); +} + +TEST_F(TestSPE, SpeProcCollectSubProc) +{ + // Start a process that will for child. + appPid = RunTestApp("test_fork"); + pid_t pidList[1] = {appPid}; + auto attr = GetProcAttribute(pidList, 1); + // Start sampling for SYSTEM. + pd = PmuOpen(SPE_SAMPLING, &attr); + // Tell process to create thread. + DelayContinue(appPid, 100); + int ret = PmuCollect(pd, 1000, collectInterval); + int len = PmuRead(pd, &data); + ASSERT_TRUE(data != nullptr); + ASSERT_TRUE(FoundAllChildren(data, len, appPid)); +} \ No newline at end of file