pmt: fix memory leaks, and improve info function
- Removed --no-write-test argument of memory test function - Fixed memory leak of memory test function - Improved info function with using nlohmann/json header-only library - Some other improvents
This commit is contained in:
@@ -19,7 +19,7 @@ Copyright 2025 Yağız Zengin
|
||||
#include <cerrno>
|
||||
#include <cstdlib>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <nlohmann/json.hpp>
|
||||
|
||||
#define IFUN "infoFunction"
|
||||
|
||||
@@ -39,14 +39,17 @@ bool infoFunction::init(CLI::App &_app) {
|
||||
"be written separately")
|
||||
->default_val(false);
|
||||
cmd->add_option("--json-partition-name", jNamePartition,
|
||||
"Speficy partition name element for JSON body")
|
||||
"Specify partition name element for JSON body")
|
||||
->default_val("name");
|
||||
cmd->add_option("--json-size-name", jNameSize,
|
||||
"Speficy size element name for JSON body")
|
||||
"Specify size element name for JSON body")
|
||||
->default_val("size");
|
||||
cmd->add_option("--json-logical-name", jNameLogical,
|
||||
"Speficy logical element name for JSON body")
|
||||
"Specify logical element name for JSON body")
|
||||
->default_val("isLogical");
|
||||
cmd->add_option("--json-indent-size", jIndentSize,
|
||||
"Set JSON indent size for printing to screen")
|
||||
->default_val(2);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -63,6 +66,7 @@ bool infoFunction::run() {
|
||||
partitions.push_back(name);
|
||||
}
|
||||
|
||||
std::vector<PartitionMap::Partition_t> jParts;
|
||||
for (const auto &partition : partitions) {
|
||||
if (!Variables->PartMap->hasPartition(partition))
|
||||
throw Error("Couldn't find partition: %s", partition.data());
|
||||
@@ -79,14 +83,9 @@ bool infoFunction::run() {
|
||||
}
|
||||
|
||||
if (jsonFormat)
|
||||
#ifdef __LP64__
|
||||
println("{\"%s\": \"%s\", \"%s\": %lu, \"%s\": %s}",
|
||||
#else
|
||||
println("{\"%s\": \"%s\", \"%s\": %llu, \"%s\": %s}",
|
||||
#endif
|
||||
jNamePartition.data(), partition.data(), jNameSize.data(),
|
||||
Variables->PartMap->sizeOf(partition), jNameLogical.data(),
|
||||
Variables->PartMap->isLogical(partition) ? "true" : "false");
|
||||
jParts.push_back({partition,
|
||||
{Variables->PartMap->sizeOf(partition),
|
||||
Variables->PartMap->isLogical(partition)}});
|
||||
else
|
||||
#ifdef __LP64__
|
||||
println("partition=%s size=%lu isLogical=%s",
|
||||
@@ -97,6 +96,18 @@ bool infoFunction::run() {
|
||||
Variables->PartMap->isLogical(partition) ? "true" : "false");
|
||||
}
|
||||
|
||||
if (jsonFormat) {
|
||||
nlohmann::json j;
|
||||
j["partitions"] = nlohmann::json::array();
|
||||
for (const auto &[name, props] : jParts) {
|
||||
j["partitions"].push_back({{jNamePartition, name},
|
||||
{jNameSize, props.size},
|
||||
{jNameLogical, props.isLogical}});
|
||||
}
|
||||
|
||||
println("%s", j.dump(jIndentSize).data());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,17 +34,21 @@ bool memoryTestFunction::init(CLI::App &_app) {
|
||||
cmd->add_option("testDirectory", testPath, "Path to test directory")
|
||||
->default_val("/data/local/tmp")
|
||||
->check([&](const std::string &val) {
|
||||
if (val.find("/sdcard") != std::string::npos ||
|
||||
val.find("/storage") != std::string::npos)
|
||||
return std::string(
|
||||
"Sequential read tests on FUSE-mounted paths do not give correct "
|
||||
"results, so its use is prohibited (by pmt)!");
|
||||
|
||||
if (val != "/data/local/tmp" && !Helper::directoryIsExists(val))
|
||||
return std::string("Couldn't find directory: " + val +
|
||||
", no root? Try executing in ADB shell.");
|
||||
|
||||
return std::string();
|
||||
});
|
||||
cmd->add_option("-s,--file-size", testFileSize, "File size of test file")
|
||||
->transform(CLI::AsSizeValue(false))
|
||||
->default_val("1GB");
|
||||
cmd->add_flag("--no-write-test", doNotWriteTest,
|
||||
"Don't write test data to disk")
|
||||
->default_val(false);
|
||||
cmd->add_flag("--no-read-test", doNotReadTest,
|
||||
"Don't read test data from disk")
|
||||
->default_val(false);
|
||||
@@ -53,13 +57,9 @@ bool memoryTestFunction::init(CLI::App &_app) {
|
||||
}
|
||||
|
||||
bool memoryTestFunction::run() {
|
||||
if (doNotReadTest && doNotWriteTest)
|
||||
throw Error("There must be at least one test transaction, but all of them "
|
||||
"are blocked");
|
||||
|
||||
LOGN(MTFUN, INFO) << "Starting memory test on " << testPath << std::endl;
|
||||
Helper::garbageCollector collector;
|
||||
const std::string test = testPath + "/test.bin";
|
||||
const std::string test = Helper::pathJoin(testPath, "test.bin");
|
||||
|
||||
LOGN(MTFUN, INFO) << "Generating random data for testing" << std::endl;
|
||||
auto *buffer = new (std::nothrow) char[bufferSize];
|
||||
@@ -72,25 +72,24 @@ bool memoryTestFunction::run() {
|
||||
|
||||
collector.delFileAfterProgress(test);
|
||||
|
||||
if (!doNotWriteTest) {
|
||||
const int wfd = Helper::openAndAddToCloseList(
|
||||
test, collector, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
|
||||
if (wfd < 0)
|
||||
throw Error("Can't open/create test file: %s", strerror(errno));
|
||||
const int wfd = Helper::openAndAddToCloseList(
|
||||
test, collector, O_WRONLY | O_CREAT | O_TRUNC | O_SYNC, 0644);
|
||||
if (wfd < 0)
|
||||
throw Error("Can't open/create test file: %s\n", strerror(errno));
|
||||
|
||||
LOGN(MTFUN, INFO) << "Sequential write test started!" << std::endl;
|
||||
const auto startWrite = std::chrono::high_resolution_clock::now();
|
||||
ssize_t bytesWritten = 0;
|
||||
while (bytesWritten < testFileSize) {
|
||||
const ssize_t ret = write(wfd, buffer, bufferSize);
|
||||
if (ret < 0) throw Error("Can't write to test file: %s\n", strerror(errno));
|
||||
bytesWritten += ret;
|
||||
|
||||
LOGN(MTFUN, INFO) << "Sequential write test started!" << std::endl;
|
||||
const auto startWrite = std::chrono::high_resolution_clock::now();
|
||||
ssize_t bytesWritten = 0;
|
||||
while (bytesWritten < testFileSize) {
|
||||
const ssize_t ret = write(wfd, buffer, bufferSize);
|
||||
if (ret < 0) throw Error("Can't write to test file: %s", strerror(errno));
|
||||
bytesWritten += ret;
|
||||
}
|
||||
const auto endWrite = std::chrono::high_resolution_clock::now();
|
||||
|
||||
const double writeTime =
|
||||
std::chrono::duration<double>(endWrite - startWrite).count();
|
||||
println("Sequential write speed: %f MB/s",
|
||||
println("Sequential write speed: %3.f MB/s",
|
||||
(static_cast<double>(testFileSize) / (1024.0 * 1024.0)) /
|
||||
writeTime);
|
||||
LOGN(MTFUN, INFO) << "Sequential write test done!" << std::endl;
|
||||
@@ -99,10 +98,11 @@ bool memoryTestFunction::run() {
|
||||
if (!doNotReadTest) {
|
||||
auto *rawBuffer = new char[bufferSize + 4096];
|
||||
collector.delAfterProgress(rawBuffer);
|
||||
auto *bufferRead = reinterpret_cast<char*>((reinterpret_cast<uintptr_t>(rawBuffer) + 4096 - 1) & ~(4096 - 1));
|
||||
auto *bufferRead = reinterpret_cast<char *>(
|
||||
(reinterpret_cast<uintptr_t>(rawBuffer) + 4096 - 1) & ~(4096 - 1));
|
||||
const int rfd =
|
||||
Helper::openAndAddToCloseList(test, collector, O_RDONLY | O_DIRECT);
|
||||
if (rfd < 0) throw Error("Can't open test file: %s", strerror(errno));
|
||||
if (rfd < 0) throw Error("Can't open test file: %s\n", strerror(errno));
|
||||
|
||||
LOGN(MTFUN, INFO) << "Sequential read test started!" << std::endl;
|
||||
const auto startRead = std::chrono::high_resolution_clock::now();
|
||||
@@ -115,9 +115,8 @@ bool memoryTestFunction::run() {
|
||||
|
||||
const double read_time =
|
||||
std::chrono::duration<double>(endRead - startRead).count();
|
||||
println("Sequential read speed: %f MB/s",
|
||||
(static_cast<double>(total) / (1024.0 * 1024.0)) /
|
||||
read_time);
|
||||
println("Sequential read speed: %3.f MB/s",
|
||||
(static_cast<double>(total) / (1024.0 * 1024.0)) / read_time);
|
||||
LOGN(MTFUN, INFO) << "Sequential read test done!" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ class infoFunction final : public FunctionBase {
|
||||
private:
|
||||
std::vector<std::string> partitions;
|
||||
std::string jNamePartition, jNameSize, jNameLogical;
|
||||
int jIndentSize = 2;
|
||||
bool jsonFormat = false;
|
||||
|
||||
public:
|
||||
@@ -175,7 +176,7 @@ class memoryTestFunction final : public FunctionBase {
|
||||
private:
|
||||
uint64_t bufferSize = MB(4), /* bufferSizeRandom = KB(4),*/ testFileSize = 0;
|
||||
std::string testPath;
|
||||
bool doNotWriteTest = false, doNotReadTest = false;
|
||||
bool doNotReadTest = false;
|
||||
|
||||
public:
|
||||
CLI::App *cmd = nullptr;
|
||||
|
||||
Reference in New Issue
Block a user