Skip to content

bench(interlace): adding test bench tools to justify performance issues#34965

Open
freemine wants to merge 1 commit into
taosdata:mainfrom
freemine:freemine.benchmark.interlace
Open

bench(interlace): adding test bench tools to justify performance issues#34965
freemine wants to merge 1 commit into
taosdata:mainfrom
freemine:freemine.benchmark.interlace

Conversation

@freemine

Copy link
Copy Markdown
Contributor

Description

it seems that TAOS_STMT_OPTIONS::singleStbInsert / singleTableBindOnce does NOT bring the performance improvements as stated in the documentation.
this test benchmark tool is to demon the potential issue.

pls also be kindly noted: the tool is vibe-generated by AI, and no thorough review yet, thus there might be error big or small, and conclusion above might be wrong.

if there's any official tool to demonstrate the same issue, pls let me know and i might be able to compare.

thx!

to produce as an example:

./debug/build/bin/stmtPerfBench --api stmt2 --mode all --scenario all --seed 1 --db test --drop-db yes --verify yes --verbose-metrics yes --cycles 10  --rows-per-table 1000 --batch-rows 1 --wrarmup 1

Issue(s)

Checklist

Please check the items in the checklist if applicable.

  • Is the user manual updated?
  • Are the test cases passed and automated?
  • Is there no significant decrease in test coverage?
截屏2026-03-27 13 48 52 截屏2026-03-27 14 58 50

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a performance benchmarking tool for the client library, specifically targeting the STMT and STMT2 APIs. The implementation includes the core benchmark logic, a shared utility library, and a comprehensive suite of unit tests. The review feedback focuses on improving cross-platform portability by replacing non-standard functions like usleep and getpid, enhancing code readability through explicit struct member initialization, and adopting more idiomatic C++ patterns for error handling and file operations.

int code = taos_errno(result);
while (code == TSDB_CODE_MND_DB_IN_CREATING || code == TSDB_CODE_MND_DB_IN_DROPPING) {
taos_free_result(result);
usleep(200 * 1000);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

usleep is deprecated and not portable as it's not available on Windows. For better portability and to adhere to modern C++ standards, please use std::this_thread::sleep_for from the <thread> header. You already include <chrono>, so you would just need to add an include for <thread>.

Suggested change
usleep(200 * 1000);
std::this_thread::sleep_for(std::chrono::milliseconds(200));

std::chrono::system_clock::now().time_since_epoch())
.count();
std::ostringstream oss;
oss << nowUs << '_' << static_cast<long long>(getpid());

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

getpid is not portable and is unavailable on Windows. To ensure this tool can be compiled and run on different operating systems, please use conditional compilation to provide a platform-specific implementation (e.g., _getpid from <process.h> on Windows).

continue;
}
finalizeStmt2TableBindData(&data);
tableNames.push_back(const_cast<char *>(names.tableNames[static_cast<size_t>(tableId)].c_str()));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

Using const_cast to remove const is dangerous as it subverts the type system and can lead to undefined behavior if the underlying data is modified. The taos_stmt2_bind_param API appears to require a non-const char**. If you are certain the API does not modify the strings, this may work, but it's a significant code smell. It would be best to fix the API to accept const char* const*. If that's not feasible, please add a comment explaining why the const_cast is necessary and considered safe here.

Comment on lines +663 to +665
TAOS_STMT_OPTIONS options = {0, true, true};
TAOS_STMT *stmt = benchCase.mode == StmtPerfBenchMode::kInterlace ? taos_stmt_init_with_options(taos, &options)
: taos_stmt_init(taos);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using C-style aggregate initialization with positional values like {0, true, true} can be unclear about which member is being initialized. For better readability and maintainability, it's preferable to use C++ uniform initialization ({}) and then set the members explicitly by name. This makes the code self-documenting.

  TAOS_STMT_OPTIONS options{};
  options.enable_auto_bind = true;
  options.single_stb_bind = true;
  TAOS_STMT        *stmt = benchCase.mode == StmtPerfBenchMode::kInterlace ? taos_stmt_init_with_options(taos, &options)
                                                                            : taos_stmt_init(taos);

auto prepareEnd = std::chrono::steady_clock::now();
metrics->prepareUs = elapsedUs(prepareStart, prepareEnd);
if (!stmtCodeOk(stmt, code, "taos_stmt_prepare", err)) {
goto cleanup;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The use of goto for error handling is generally discouraged in C++ as it can make the code harder to follow and maintain. Consider using more idiomatic C++ patterns like RAII (Resource Acquisition Is Initialization) with guard classes to handle cleanup automatically, or a do { ... } while (false) loop with break statements.

Comment on lines +816 to +817
TAOS_STMT2_OPTION option = {0, benchCase.mode == StmtPerfBenchMode::kInterlace,
benchCase.mode == StmtPerfBenchMode::kInterlace, NULL, NULL};

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This C-style aggregate initialization is not very readable. Please use C++ uniform initialization and set struct members explicitly by name to make the code's intent clearer.

Suggested change
TAOS_STMT2_OPTION option = {0, benchCase.mode == StmtPerfBenchMode::kInterlace,
benchCase.mode == StmtPerfBenchMode::kInterlace, NULL, NULL};
TAOS_STMT2_OPTION option{};
option.singleStbInsert = (benchCase.mode == StmtPerfBenchMode::kInterlace);
option.singleTableBindOnce = (benchCase.mode == StmtPerfBenchMode::kInterlace);

Comment on lines +890 to +897
ok = true;

cleanup:
if (!ok) {
metrics->totalUs = elapsedUs(totalStart, std::chrono::steady_clock::now());
}
taos_stmt2_close(stmt);
return ok;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

The ok variable and the cleanup block appear to be redundant. The ok variable is always true when this code is reached, making the if(!ok) block dead code. Since error paths return false directly, you can simplify this section by removing the ok variable and the cleanup logic, and simply returning true at the end of a successful execution.

  ok = true;

  taos_stmt2_close(stmt);
  return ok;

std::ofstream fileOutput;
std::ostream *out = &std::cout;
if (!config.outputFile.empty()) {
fileOutput.open(config.outputFile.c_str(), std::ios::out | std::ios::trunc);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For better C++ style, you can pass the std::string object directly to open() instead of converting it to a C-style string with .c_str(). The std::fstream methods have had overloads for std::string since C++11.

Suggested change
fileOutput.open(config.outputFile.c_str(), std::ios::out | std::ios::trunc);
fileOutput.open(config.outputFile, std::ios::out | std::ios::trunc);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants