Skip to content

Commit

Permalink
Merge d2c1b6b into 6d00863
Browse files Browse the repository at this point in the history
  • Loading branch information
finger563 authored Mar 5, 2024
2 parents 6d00863 + d2c1b6b commit d40cfd9
Show file tree
Hide file tree
Showing 102 changed files with 412 additions and 302 deletions.
3 changes: 3 additions & 0 deletions components/monitor/example/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,3 +28,6 @@ idf.py -p PORT flash monitor

See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.

## Example Output

![CleanShot 2024-03-05 at 14 36 04](https://github.com/esp-cpp/espp/assets/213467/342e4d78-deee-4361-9e58-697e6dc6f73c)
47 changes: 29 additions & 18 deletions components/monitor/example/main/monitor_example.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
#include "task.hpp"
#include "task_monitor.hpp"

// must be after tabulate.hpp
#include <tabulate/markdown_exporter.hpp>

// for doing work
#include <math.h>

Expand All @@ -24,9 +27,8 @@ extern "C" void app_main(void) {
auto seconds_since_start = std::chrono::duration<float>(now - start).count();
// do some work
float x = 2.0f * M_PI * sin(exp(task_id) * seconds_since_start);
fmt::print("[Task {}]: {:.03}\n", task_id, x);
// sleep
std::this_thread::sleep_for(100ms);
std::this_thread::sleep_for((10ms * std::abs(x)) + 1ms);
// don't want to stop the task
return false;
};
Expand All @@ -47,17 +49,16 @@ extern "C" void app_main(void) {
}

{
//! [get_latest_info example]
//! [get_latest_info_vector example]
// create threads
auto start = std::chrono::high_resolution_clock::now();
auto task_fn = [&start](int task_id, auto &, auto &) {
auto now = std::chrono::high_resolution_clock::now();
auto seconds_since_start = std::chrono::duration<float>(now - start).count();
// do some work
float x = 2.0f * M_PI * sin(exp(task_id) * seconds_since_start);
fmt::print("[Task {}]: {:.03}\n", task_id, x);
// sleep
std::this_thread::sleep_for(100ms);
std::this_thread::sleep_for((10ms * std::abs(x)) + 1ms);
// don't want to stop the task
return false;
};
Expand All @@ -73,24 +74,25 @@ extern "C" void app_main(void) {
tasks[i]->start();
}
// now sleep for a while to let the monitor do its thing
for (int i = 0; i < 5; i++) {
fmt::print("{}\n", espp::TaskMonitor::get_latest_info());
std::this_thread::sleep_for(1s);
std::this_thread::sleep_for(1s);
auto task_info = espp::TaskMonitor::get_latest_info_vector();
for (const auto &info : task_info) {
fmt::print("{}\n", info);
}
//! [get_latest_info example]
//! [get_latest_info_vector example]
}

{
//! [get_latest_info_table example]
//! [get_latest_info example]
// create threads
auto start = std::chrono::high_resolution_clock::now();
auto task_fn = [&start](int task_id, auto &, auto &) {
auto now = std::chrono::high_resolution_clock::now();
auto seconds_since_start = std::chrono::duration<float>(now - start).count();
// do some work, but don't print it so that the table is easier to read
volatile float x = 2.0f * M_PI * sin(exp(task_id) * seconds_since_start);
// do some work
float x = 2.0f * M_PI * sin(exp(task_id) * seconds_since_start);
// sleep
std::this_thread::sleep_for(100ms);
std::this_thread::sleep_for((10ms * std::abs(x)) + 1ms);
// don't want to stop the task
return false;
};
Expand All @@ -106,11 +108,20 @@ extern "C" void app_main(void) {
tasks[i]->start();
}
// now sleep for a while to let the monitor do its thing
for (int i = 0; i < 5; i++) {
espp::TaskMonitor::get_latest_info_table(std::cout);
std::this_thread::sleep_for(1s);
}
//! [get_latest_info_table example]
std::this_thread::sleep_for(1s);
// single line string
fmt::print("Task Monitor Info (single line):\n");
fmt::print("{}\n", espp::TaskMonitor::get_latest_info_string());
// pretty table
fmt::print("Task Monitor Info (pretty table):\n");
auto task_table = espp::TaskMonitor::get_latest_info_table();
std::cout << task_table << std::endl;
// markdown table
fmt::print("Converting the table above to markdown:\n");
tabulate::MarkdownExporter exporter;
auto markdown = exporter.dump(task_table);
std::cout << markdown << std::endl;
//! [get_latest_info example]
}

fmt::print("Monitor example finished!\n");
Expand Down
2 changes: 1 addition & 1 deletion components/monitor/example/sdkconfig.defaults
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,4 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240
# Common ESP-related
#
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
CONFIG_ESP_MAIN_TASK_STACK_SIZE=10240
CONFIG_ESP_MAIN_TASK_STACK_SIZE=16384
143 changes: 82 additions & 61 deletions components/monitor/include/task_monitor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,21 +26,30 @@ namespace espp {
* (default) or print out the stats for you to analyze. Finally, the
* monitoring period can be configured as well.
*
* @note You can use the static TaskMonitor::get_latest_info() to get a
* string with the latest info without needing to construct a class /
* start the task.
*
* \section task_monitor_ex1 Basic Task Monitor Example
* \snippet monitor_example.cpp TaskMonitor example
*
* \section task_monitor_ex2 get_latest_info() Example
* \snippet monitor_example.cpp get_latest_info example
* \section task_monitor_ex2 get_latest_info_vector() Example
* \snippet monitor_example.cpp get_latest_info_vector example
*
* \section task_monitor_ex3 get_latest_info_table() Example
* \snippet monitor_example.cpp get_latest_info_table example
* \section task_monitor_ex3 get_latest_info_*() Example
* \snippet monitor_example.cpp get_latest_info example
*/
class TaskMonitor : public BaseComponent {
public:
/**
* Info structure for each task monitored.
*/
struct TaskInfo {
std::string name; /**< Name of the task. */
uint32_t cpu_percent; /**< % CPU run time the task has used. */
uint32_t high_water_mark; /**< Stack high water mark (bytes). */
uint32_t priority; /**< Current priority of the task. */
};

/**
* Config structure for TaskMonitor object.
*/
struct Config {
std::chrono::duration<float> period; /**< Period (s) the TaskMonitor::task_callback runs at. */
size_t task_stack_size_bytes{
Expand Down Expand Up @@ -70,35 +79,15 @@ class TaskMonitor : public BaseComponent {
* * % CPU run time the task has used
* * stack high water mark (bytes)
* * current priority of the task
*
* Where each entry is separated by ',' and each set of task data is
* separated by ';'.
*
* @note There is no newline returned.
*
* This is a static function, so it can be called without having to
* instantiate a TaskMonitor object.
*
* @return std::string containing sequence of entries, formatted:
*
* name, cpu%, high_water_mark, priority;;
* @return std::vector<TaskInfo> vector containing info for each task.
*/
static std::string get_latest_info() {
static std::vector<TaskInfo> get_latest_info_vector() {
std::vector<TaskInfo> task_info;
#if CONFIG_FREERTOS_USE_TRACE_FACILITY && CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS
// make this static so that we don't allocate on the stack each time we
// call this function (and then deallocate later). NOTE(WARN): doing this
// makes this function non-reentrant and not thread-safe.
static char info_str[1024] = {0};

TaskStatus_t *pxTaskStatusArray;
volatile UBaseType_t uxArraySize;
uint32_t ulTotalRunTime, ulStatsAsPercentage;

char *pcWriteBuffer = &info_str[0];

// Make sure the write buffer does not contain a string.
*pcWriteBuffer = 0x00;

// Take a snapshot of the number of tasks in case it changes while this
// function is executing.
uxArraySize = uxTaskGetNumberOfTasks();
Expand Down Expand Up @@ -134,64 +123,85 @@ class TaskMonitor : public BaseComponent {
ulStatsAsPercentage = pxTaskStatusArray[x].ulRunTimeCounter / ulTotalRunTime;

if (ulStatsAsPercentage > 0UL) {
sprintf(pcWriteBuffer, "%s,%lu%%,%ld,%d;;", pxTaskStatusArray[x].pcTaskName,
ulStatsAsPercentage, high_water_mark, priority);
task_info.push_back(
{pxTaskStatusArray[x].pcTaskName, ulStatsAsPercentage, high_water_mark, priority});
} else {
// If the percentage is zero here then the task has
// consumed less than 1% of the total run time.
sprintf(pcWriteBuffer, "%s,<1%%,%ld,%d;;", pxTaskStatusArray[x].pcTaskName,
high_water_mark, priority);
task_info.push_back({pxTaskStatusArray[x].pcTaskName, 0, high_water_mark, priority});
}

pcWriteBuffer += strlen((char *)pcWriteBuffer);
}
}
// The array is no longer needed, free the memory it consumes.
vPortFree(pxTaskStatusArray);
}
return std::string{info_str};
#else
return "";
#endif
return task_info;
}

/**
* @brief Get information about all the tasks running.
* Will provide for each task the following information:
* * name
* * % CPU run time the task has used
* * stack high water mark (bytes)
* * current priority of the task
*
* Where each entry is separated by ',' and each set of task data is
* separated by ';'.
*
* @note There is no newline returned.
*
* This is a static function, so it can be called without having to
* instantiate a TaskMonitor object.
*
* @return std::string containing sequence of entries, formatted:
*
* name, cpu%, high_water_mark, priority;;
*
* @note This function calls TaskMonitor::get_latest_info_vector() and then
* formats the data into a single line string separated by , and ;.
*/
static std::string get_latest_info_string() {
std::string info = "";
auto task_info = get_latest_info_vector();
for (const auto &t : task_info) {
if (t.cpu_percent > 0.0f) {
info += fmt::format("{},{},{},{};", t.name, t.cpu_percent, t.high_water_mark, t.priority);
} else {
info += fmt::format("{},<1%,{},{};", t.name, 0, t.high_water_mark, t.priority);
}
}
return info;
}

/**
* @brief Print the latest task information in a nice table format.
* This is a static function, so it can be called without having to
* instantiate a TaskMonitor object.
* @param os std::ostream to write the table to.
* @note This function calls TaskMonitor::get_latest_info() and then formats
* the data into a table using the tabulate library, and then writes
* the table to the provided std::ostream.
* @return A tabulate::Table object which can be streamed to a std::ostream.
* @note This function calls TaskMonitor::get_latest_info_vector() and then
* formats the data into a table using the tabulate library.
*/
static void get_latest_info_table(std::ostream &os) {
std::string info = get_latest_info();
static auto get_latest_info_table() {
using namespace tabulate;
using Row_t = Table::Row_t;
Table table;
table.add_row({"Task Name", "CPU %", "High Water Mark", "Priority"});

std::string task_info;
std::istringstream iss(info);
while (std::getline(iss, task_info, ';')) {
std::istringstream task_iss(task_info);
std::string task_data;
Row_t row;
while (std::getline(task_iss, task_data, ',')) {
row.push_back(task_data);
}
if (row.size() == 4) {
table.add_row(row);
}
auto task_info = get_latest_info_vector();
for (const auto &t : task_info) {
std::string percent = t.cpu_percent > 0 ? fmt::format("{} %", t.cpu_percent) : "<1%";
table.add_row(
{t.name, percent, fmt::format("{} B", t.high_water_mark), fmt::format("{}", t.priority)});
}
os << table << std::endl;
return table;
}

protected:
bool task_callback(std::mutex &m, std::condition_variable &cv) {
auto start = std::chrono::high_resolution_clock::now();
// print out the monitor information
fmt::print("[TM]{}\n", get_latest_info());
fmt::print("[TM]{}\n", get_latest_info_string());
// sleep until our period is up
{
std::unique_lock<std::mutex> lk(m);
Expand All @@ -205,3 +215,14 @@ class TaskMonitor : public BaseComponent {
std::unique_ptr<Task> task_;
};
} // namespace espp

// for printing TaskMonitor::TaskInfo using libfmt
template <> struct fmt::formatter<espp::TaskMonitor::TaskInfo> {
constexpr auto parse(format_parse_context &ctx) { return ctx.begin(); }
template <typename FormatContext>
auto format(const espp::TaskMonitor::TaskInfo &t, FormatContext &ctx) {
return fmt::format_to(ctx.out(),
"TaskInfo(name={}, cpu_percent={}, high_water_mark={}, priority={})",
t.name, t.cpu_percent, t.high_water_mark, t.priority);
}
};
2 changes: 1 addition & 1 deletion docs/adc/adc_types.html
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@
<li><a href="index.html">ADC APIs</a> &raquo;</li>
<li>ADC Types</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/esp-cpp/espp/blob/d5ae840d/docs/en/adc/adc_types.rst" class="fa fa-github"> Edit on GitHub</a>
<a href="https://github.com/esp-cpp/espp/blob/75fe6700/docs/en/adc/adc_types.rst" class="fa fa-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
Expand Down
4 changes: 2 additions & 2 deletions docs/adc/ads1x15.html
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
<li><a href="index.html">ADC APIs</a> &raquo;</li>
<li>ADS1x15 I2C ADC</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/esp-cpp/espp/blob/d5ae840d/docs/en/adc/ads1x15.rst" class="fa fa-github"> Edit on GitHub</a>
<a href="https://github.com/esp-cpp/espp/blob/75fe6700/docs/en/adc/ads1x15.rst" class="fa fa-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
Expand All @@ -168,7 +168,7 @@ <h2>API Reference<a class="headerlink" href="#api-reference" title="Permalink to
<section id="header-file">
<h3>Header File<a class="headerlink" href="#header-file" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/esp-cpp/espp/blob/d5ae840d/components/ads1x15/include/ads1x15.hpp">components/ads1x15/include/ads1x15.hpp</a></p></li>
<li><p><a class="reference external" href="https://github.com/esp-cpp/espp/blob/75fe6700/components/ads1x15/include/ads1x15.hpp">components/ads1x15/include/ads1x15.hpp</a></p></li>
</ul>
</section>
<section id="classes">
Expand Down
4 changes: 2 additions & 2 deletions docs/adc/ads7138.html
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
<li><a href="index.html">ADC APIs</a> &raquo;</li>
<li>ADS7138 I2C ADC</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/esp-cpp/espp/blob/d5ae840d/docs/en/adc/ads7138.rst" class="fa fa-github"> Edit on GitHub</a>
<a href="https://github.com/esp-cpp/espp/blob/75fe6700/docs/en/adc/ads7138.rst" class="fa fa-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
Expand All @@ -173,7 +173,7 @@ <h2>API Reference<a class="headerlink" href="#api-reference" title="Permalink to
<section id="header-file">
<h3>Header File<a class="headerlink" href="#header-file" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/esp-cpp/espp/blob/d5ae840d/components/ads7138/include/ads7138.hpp">components/ads7138/include/ads7138.hpp</a></p></li>
<li><p><a class="reference external" href="https://github.com/esp-cpp/espp/blob/75fe6700/components/ads7138/include/ads7138.hpp">components/ads7138/include/ads7138.hpp</a></p></li>
</ul>
</section>
<section id="classes">
Expand Down
4 changes: 2 additions & 2 deletions docs/adc/continuous_adc.html
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@
<li><a href="index.html">ADC APIs</a> &raquo;</li>
<li>Continuous ADC</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/esp-cpp/espp/blob/d5ae840d/docs/en/adc/continuous_adc.rst" class="fa fa-github"> Edit on GitHub</a>
<a href="https://github.com/esp-cpp/espp/blob/75fe6700/docs/en/adc/continuous_adc.rst" class="fa fa-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
Expand All @@ -173,7 +173,7 @@ <h2>API Reference<a class="headerlink" href="#api-reference" title="Permalink to
<section id="header-file">
<h3>Header File<a class="headerlink" href="#header-file" title="Permalink to this headline"></a></h3>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/esp-cpp/espp/blob/d5ae840d/components/adc/include/continuous_adc.hpp">components/adc/include/continuous_adc.hpp</a></p></li>
<li><p><a class="reference external" href="https://github.com/esp-cpp/espp/blob/75fe6700/components/adc/include/continuous_adc.hpp">components/adc/include/continuous_adc.hpp</a></p></li>
</ul>
</section>
<section id="classes">
Expand Down
2 changes: 1 addition & 1 deletion docs/adc/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@
<li><a href="../index.html" class="icon icon-home"></a> &raquo;</li>
<li>ADC APIs</li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/esp-cpp/espp/blob/d5ae840d/docs/en/adc/index.rst" class="fa fa-github"> Edit on GitHub</a>
<a href="https://github.com/esp-cpp/espp/blob/75fe6700/docs/en/adc/index.rst" class="fa fa-github"> Edit on GitHub</a>
</li>
</ul>
<hr/>
Expand Down
Loading

0 comments on commit d40cfd9

Please sign in to comment.