!4373 PGO新增UT测试

Merge pull request !4373 from yingguofeng/master_ut
This commit is contained in:
openharmony_ci 2023-07-07 12:26:24 +00:00 committed by Gitee
commit 5c3bbf5ae6
No known key found for this signature in database
GPG Key ID: 173E9B9CA92EEF8F
6 changed files with 391 additions and 1 deletions

View File

@ -16,6 +16,33 @@ import("//arkcompiler/ets_runtime/test/test_helper.gni")
module_output_path = "arkcompiler/ets_runtime"
test_js_path =
"//arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/pgo_test_case/"
test_js_files = [
"op_type_test",
"class_test",
"call_test",
]
foreach(file, test_js_files) {
es2abc_gen_abc("gen_${file}_abc") {
test_js = "${test_js_path}${file}.js"
test_abc = "$target_out_dir/${file}.abc"
# Only targets in this file can depend on this.
extra_visibility = [ ":*" ]
src_js = rebase_path(test_js)
dst_file = rebase_path(test_abc)
extra_args = []
extra_args += [ "--module" ]
extra_args += [ "--merge-abc" ]
extra_args += [ "--type-extractor" ]
in_puts = [ test_js ]
out_puts = [ test_abc ]
}
}
host_unittest_action("PGOProfilerTest") {
module_out_path = module_output_path
@ -38,6 +65,17 @@ host_unittest_action("PGOProfilerTest") {
sdk_libc_secshared_dep,
]
foreach(file, test_js_files) {
deps += [ ":gen_${file}_abc" ]
}
if (is_ohos && is_standard_system) {
test_abc_dir = "/data/test"
} else {
test_abc_dir = rebase_path(target_out_dir)
}
defines = [ "TARGET_ABC_PATH=\"${test_abc_dir}/\"" ]
# hiviewdfx libraries
external_deps = hiviewdfx_ext_deps
deps += hiviewdfx_deps

View File

@ -85,6 +85,26 @@ protected:
return pf;
}
std::shared_ptr<JSPandaFile> ExecuteAndLoadJSPandaFile(std::string profDir, std::string recordName)
{
RuntimeOption option;
option.SetLogLevel(LOG_LEVEL::INFO);
option.SetEnableProfile(true);
option.SetProfileDir(profDir);
vm_ = JSNApi::CreateJSVM(option);
JSNApi::EnableUserUncaughtErrorHandler(vm_);
std::string targetAbcPath = TARGET_ABC_PATH + recordName + ".abc";
auto result = JSNApi::Execute(vm_, targetAbcPath, recordName, false);
EXPECT_TRUE(result);
std::shared_ptr<JSPandaFile> jsPandaFile =
JSPandaFileManager::GetInstance()->FindJSPandaFile(CString(targetAbcPath));
JSNApi::DestroyJSVM(vm_);
return jsPandaFile;
}
EcmaVM *vm_ = nullptr;
};
@ -672,4 +692,180 @@ HWTEST_F_L0(PGOProfilerTest, FailResetProfilerInWorker)
ASSERT_TRUE(loader.Match(expectRecordName, methodLiterals[0]->GetMethodId()));
rmdir("ark-profiler12/");
}
#if defined(SUPPORT_ENABLE_ASM_INTERP)
HWTEST_F_L0(PGOProfilerTest, ProfileCallTest)
{
mkdir("ark-profiler13/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
const char *targetRecordName = "call_test";
std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler13/", targetRecordName);
ASSERT_NE(jsPandaFile, nullptr);
uint32_t checksum = jsPandaFile->GetChecksum();
// Loader
PGOProfilerDecoder decoder("ark-profiler13/modules.ap", 1);
PGOProfilerDecoder decoder1("ark-profiler13/modules.ap", 10);
PGOProfilerDecoder decoder2("ark-profiler13/modules.ap", 11000);
ASSERT_TRUE(decoder.LoadAndVerify(checksum));
ASSERT_TRUE(decoder1.LoadAndVerify(checksum));
ASSERT_TRUE(decoder2.LoadAndVerify(checksum));
auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
for (auto iter : methodLiterals) {
auto methodLiteral = iter.second;
auto methodId = methodLiteral->GetMethodId();
auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
decoder1.MatchAndMarkMethod(targetRecordName, methodName, methodId);
decoder2.MatchAndMarkMethod(targetRecordName, methodName, methodId);
ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
if (std::string(methodName) == "foo") {
ASSERT_TRUE(decoder1.Match(targetRecordName, methodId));
} else {
ASSERT_TRUE(!decoder1.Match(targetRecordName, methodId));
}
ASSERT_TRUE(!decoder2.Match(targetRecordName, methodId));
}
unlink("ark-profiler13/modules.ap");
rmdir("ark-profiler13/");
}
HWTEST_F_L0(PGOProfilerTest, UseClassTypeTest)
{
mkdir("ark-profiler14/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
const char *targetRecordName = "class_test";
std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler14/", targetRecordName);
ASSERT_NE(jsPandaFile, nullptr);
uint32_t checksum = jsPandaFile->GetChecksum();
// Loader
PGOProfilerDecoder decoder("ark-profiler14/modules.ap", 1);
ASSERT_TRUE(decoder.LoadAndVerify(checksum));
auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
for (auto iter : methodLiterals) {
auto methodLiteral = iter.second;
auto methodId = methodLiteral->GetMethodId();
auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
auto callback = [methodName, methodId](uint32_t offset, PGOType *type) {
ASSERT_NE(offset, 0);
if (type->IsScalarOpType()) {
} else if (type->IsRwOpType()) {
auto pgoRWOpType = *reinterpret_cast<PGORWOpType *>(type);
if (std::string(methodName) == "Foot" || std::string(methodName) == "Arm") {
ASSERT_TRUE(pgoRWOpType.GetCount() == 1);
ASSERT_EQ(pgoRWOpType.GetObjectInfo(0).GetClassType(), ClassType(methodId.GetOffset()));
} else if (std::string(methodName) == "foo" || std::string(methodName) == "Body") {
ASSERT_TRUE(pgoRWOpType.GetCount() == 3);
}
} else {
ASSERT_TRUE(false);
}
};
decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
}
unlink("ark-profiler14/modules.ap");
rmdir("ark-profiler14/");
}
HWTEST_F_L0(PGOProfilerTest, DefineClassTypeTest)
{
mkdir("ark-profiler15/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
const char *targetRecordName = "class_test";
std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler15/", targetRecordName);
ASSERT_NE(jsPandaFile, nullptr);
uint32_t checksum = jsPandaFile->GetChecksum();
// Loader
PGOProfilerDecoder decoder("ark-profiler15/modules.ap", 1);
ASSERT_TRUE(decoder.LoadAndVerify(checksum));
auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
for (auto iter : methodLiterals) {
auto methodLiteral = iter.second;
auto methodId = methodLiteral->GetMethodId();
auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
auto callback = [methodName, &decoder, jsPandaFile](uint32_t offset, PGOType *type) {
ASSERT_NE(offset, 0);
if (type->IsScalarOpType()) {
auto sampleType = *reinterpret_cast<PGOSampleType *>(type);
if (sampleType.IsClassType()) {
ASSERT_EQ(std::string(methodName), "func_main_0");
PGOHClassLayoutDesc *desc;
ASSERT_TRUE(decoder.GetHClassLayoutDesc(sampleType, &desc));
ASSERT_EQ(desc->GetCtorLayoutDesc().size(), 3);
ASSERT_EQ(desc->GetPtLayoutDesc().size(), 1);
auto classId = EntityId(sampleType.GetClassType().GetClassType());
auto className = MethodLiteral::GetMethodName(jsPandaFile.get(), classId);
if (std::string(className) == "Arm") {
auto superClassId = EntityId(desc->GetSuperClassType().GetClassType());
auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
ASSERT_EQ(std::string(superClassName), "Body");
ASSERT_EQ(desc->GetLayoutDesc().size(), 3);
ASSERT_EQ(desc->GetLayoutDesc()[0].first, "x");
ASSERT_EQ(desc->GetLayoutDesc()[1].first, "y");
ASSERT_EQ(desc->GetLayoutDesc()[2].first, "t");
} else if (std::string(className) == "Foot") {
auto superClassId = EntityId(desc->GetSuperClassType().GetClassType());
auto superClassName = MethodLiteral::GetMethodName(jsPandaFile.get(), superClassId);
ASSERT_EQ(std::string(superClassName), "Body");
ASSERT_EQ(desc->GetLayoutDesc().size(), 4);
ASSERT_EQ(desc->GetLayoutDesc()[0].first, "x");
ASSERT_EQ(desc->GetLayoutDesc()[1].first, "y");
ASSERT_EQ(desc->GetLayoutDesc()[2].first, "u");
ASSERT_EQ(desc->GetLayoutDesc()[3].first, "v");
} else {
ASSERT_EQ(desc->GetSuperClassType().GetClassType(), 0);
ASSERT_EQ(desc->GetLayoutDesc().size(), 2);
ASSERT_EQ(desc->GetLayoutDesc()[0].first, "x");
ASSERT_EQ(desc->GetLayoutDesc()[1].first, "y");
}
}
}
};
decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
}
unlink("ark-profiler15/modules.ap");
rmdir("ark-profiler15/");
}
HWTEST_F_L0(PGOProfilerTest, OpTypeTest)
{
mkdir("ark-profiler16/", S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
const char *targetRecordName = "op_type_test";
std::shared_ptr<JSPandaFile> jsPandaFile = ExecuteAndLoadJSPandaFile("ark-profiler16/", targetRecordName);
ASSERT_NE(jsPandaFile, nullptr);
uint32_t checksum = jsPandaFile->GetChecksum();
// Loader
PGOProfilerDecoder decoder("ark-profiler16/modules.ap", 1);
ASSERT_TRUE(decoder.LoadAndVerify(checksum));
std::string types[17] = { "1", "1", "1", "5", "4", "4", "4", "4", "4", "4", "5", "4", "4", "1", "4", "5", "1" };
int index = 0;
auto methodLiterals = jsPandaFile->GetMethodLiteralMap();
for (auto iter : methodLiterals) {
auto methodLiteral = iter.second;
auto methodId = methodLiteral->GetMethodId();
auto methodName = methodLiteral->GetMethodName(jsPandaFile.get(), methodId);
decoder.MatchAndMarkMethod(targetRecordName, methodName, methodId);
ASSERT_TRUE(decoder.Match(targetRecordName, methodId));
auto callback = [methodName, types, &index](uint32_t offset, PGOType *type) {
ASSERT_NE(offset, 0);
if (type->IsScalarOpType()) {
auto sampleType = *reinterpret_cast<PGOSampleType *>(type);
if (sampleType.IsClassType()) {
return;
}
if (std::string(methodName) == "advance") {
ASSERT_EQ(sampleType.GetTypeString(), types[index++]);
}
}
};
decoder.GetTypeInfo(jsPandaFile.get(), targetRecordName, methodLiteral, callback);
}
unlink("ark-profiler16/modules.ap");
rmdir("ark-profiler16/");
}
#endif
} // namespace panda::test

View File

@ -0,0 +1,33 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* 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.
*/
class Test {
x
y
constructor(x, y) {
this.x = x;
this.y = y;
}
}
function foo(p)
{
return p.x
}
let a = new Test(1, 23)
for (let i = 0; i < 1000000; i++) {
foo(a)
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* 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.
*/
class Body {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
class Foot extends Body {
constructor(x, y, u, v) {
super(x, y)
this.u = u
this.v = v
}
}
class Arm extends Body {
constructor(x, y, t) {
super(x, y)
this.t = t
}
}
function foo(p)
{
return p.x
}
let a = new Body(1, 23)
let b = new Foot(3, 3.2, 2, 32.3)
let c = new Arm(1.3, 23.2, 23)
for (let i = 0; i < 1000000; i++) {
foo(a)
foo(b)
foo(c)
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2023 Huawei Device Co., Ltd.
* 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.
*/
class Body {
constructor(x, vx, mass) {
this.x = x;
this.vx = vx;
this.mass = mass;
}
}
function advance(bodies, dt) {
const sqrt = Math.sqrt;
const size = bodies.length;
for (let i = 0; i < size; i++) {
const bodyi = bodies[i];
let vxi = bodyi.vx;
const xi = bodyi.x;
const massi = bodyi.mass;
for (let j = i + 1; j < size; j++) {
const bodyj = bodies[j];
const dx = xi - bodyj.x;
const d2 = dx * dx;
const mag = dt / (d2 * sqrt(d2));
const massiMag = massi * mag;
const massj = bodyj.mass;
const massjMag = massj * mag;
vxi -= dx * massjMag;
bodyj.vx += dx * massiMag;
}
bodyi.vx = vxi;
bodyi.x += dt * vxi;
}
}
const PI = Math.PI;
const SOLAR_MASS = 4 * PI * PI;
function Sun() {
return new Body(0.0, 0.0, SOLAR_MASS);
}
function Sun1() {
return new Body(1.2, 3.1, PI);
}
const bodies = [Sun(), Sun1()];
const n = 100000;
for (let i = 0; i < n; i++) {
advance(bodies, 0.01);
}

View File

@ -128,7 +128,7 @@
<option name="push" value="test/test/libark_jsruntime_test.so -> /data/test" src="out"/>
</preparer>
</target>
<target name="ContainersVectorAddFuzzTest">
<target name="ContainersVectorAddFuzzTest">
<preparer>
<option name="push" value="test/test/libark_jsruntime_test.so -> /data/test" src="out"/>
</preparer>
@ -335,6 +335,9 @@
<target name="PGOProfilerTest">
<preparer>
<option name="push" value="test/test/libark_jsruntime_test.so -> /data/test" src="out"/>
<option name="push" value="obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/call_test.abc -> /data/test" src="out"/>
<option name="push" value="obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/class_test.abc -> /data/test" src="out"/>
<option name="push" value="obj/arkcompiler/ets_runtime/ecmascript/pgo_profiler/tests/op_type_test.abc -> /data/test" src="out"/>
</preparer>
</target>
<target name="HeapTrackerTest">