Skip to content

Commit

Permalink
add pybind11 wrapper for callprofiler
Browse files Browse the repository at this point in the history
remove unwanted checkin callprofiler driver code

clang-format

clang-format

clang-format RadixTree

flake8

floating number

skip windows timeing test

fix typo

fix conflict

wrap CallProfilerProbe

wrap CallProfilerProbe

profliing result in python dict

profliing result in python dict

add jsonschema

assertGreaterEqual

add MODMESH_PYTHON_WRAPPER_VISIBILITY

busy loop

fix flake8

use perf_counter

flake8

jsonschema

missing jsonschema
  • Loading branch information
q40603 committed Jun 17, 2024
1 parent 4d1a1bb commit 1f07576
Show file tree
Hide file tree
Showing 9 changed files with 343 additions and 17 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/devbuild.yml
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ jobs:
- name: dependency by pip
run: |
sudo pip3 install setuptools
sudo pip3 install numpy pytest flake8
sudo pip3 install numpy pytest flake8 jsonschema
sudo pip3 install pyside6==$(qmake6 -query QT_VERSION)
- name: dependency by manual script
Expand Down Expand Up @@ -314,12 +314,12 @@ jobs:
# suppress the warning of pip because brew forces PEP668 since python3.12
python3 -m pip -v install --upgrade setuptools --break-system-packages
python3 -m pip -v install --upgrade pip --break-system-packages
python3 -m pip -v install --upgrade numpy pytest flake8 --break-system-packages
python3 -m pip -v install --upgrade numpy pytest flake8 jsonschema --break-system-packages
python3 -m pip -v install --upgrade pyside6==$(qmake -query QT_VERSION) --break-system-packages
else
python3 -m pip -v install --upgrade setuptools
python3 -m pip -v install --upgrade pip
python3 -m pip -v install --upgrade numpy pytest flake8
python3 -m pip -v install --upgrade numpy pytest flake8 jsonschema
python3 -m pip -v install --upgrade pyside6==$(qmake -query QT_VERSION)
fi
Expand Down Expand Up @@ -492,7 +492,7 @@ jobs:

- name: dependency by pip
run: |
pip3 install -U numpy pytest flake8 pybind11 pyside6==$(qmake -query QT_VERSION)
pip3 install -U numpy pytest jsonschema flake8 pybind11 pyside6==$(qmake -query QT_VERSION)
# Add PySide6 and Shiboken6 path into system path, that allow exe file can find
# dll during runtime
# If user needs to modified system path in github actions container
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ jobs:
- name: dependency by pip
run: |
sudo pip3 install setuptools
sudo pip3 install numpy pytest flake8 pyside6==$(qmake6 -query QT_VERSION)
sudo pip3 install numpy pytest flake8 jsonschema pyside6==$(qmake6 -query QT_VERSION)
- name: dependency (manual)
run: sudo ${GITHUB_WORKSPACE}/contrib/dependency/install.sh pybind11
Expand Down Expand Up @@ -223,11 +223,11 @@ jobs:
# suppress the warning of pip because brew forces PEP668 since python3.12
python3 -m pip -v install --upgrade setuptools --break-system-packages
python3 -m pip -v install --upgrade pip --break-system-packages
python3 -m pip -v install --upgrade numpy pytest flake8 pyside6==$(qmake -query QT_VERSION) --break-system-packages
python3 -m pip -v install --upgrade numpy pytest flake8 jsonschema pyside6==$(qmake -query QT_VERSION) --break-system-packages
else
python3 -m pip -v install --upgrade setuptools
python3 -m pip -v install --upgrade pip
python3 -m pip -v install --upgrade numpy pytest flake8 pyside6==$(qmake -query QT_VERSION)
python3 -m pip -v install --upgrade numpy pytest flake8 jsonschema pyside6==$(qmake -query QT_VERSION)
fi
- name: dependency (manual)
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/nouse_install.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ jobs:
- name: dependency by pip
run: |
sudo pip3 install setuptools
sudo pip3 install numpy pytest flake8
sudo pip3 install numpy pytest jsonschema flake8
- name: dependency by manual script
run: sudo ${GITHUB_WORKSPACE}/contrib/dependency/install.sh pybind11
Expand Down Expand Up @@ -135,7 +135,7 @@ jobs:
# temporary remove pip upgrade, due to latest pip will let cmake
# fail to find Numpy
# python3 -m pip -v install --upgrade pip
python3 -m pip -v install --upgrade numpy pytest flake8
python3 -m pip -v install --upgrade numpy pytest flake8 jsonschema
- name: dependency by manual script
run: sudo ${GITHUB_WORKSPACE}/contrib/dependency/install.sh pybind11
Expand Down
25 changes: 18 additions & 7 deletions cpp/modmesh/toggle/RadixTree.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@

#include <algorithm>
#include <chrono>
#include <vector>
#include <functional>
#include <iostream>
#include <list>
Expand All @@ -53,8 +54,8 @@ class RadixTreeNode
static_assert(std::is_integral_v<key_type> && std::is_signed_v<key_type>, "signed integral required");

RadixTreeNode(std::string const & name, key_type key)
: m_name(name)
, m_key(key)
: m_key(key)
, m_name(name)
, m_prev(nullptr)
{
}
Expand All @@ -72,6 +73,11 @@ class RadixTreeNode
const T & data() const { return m_data; }
const child_list_type & children() const { return m_children; }

bool no_children() const
{
return m_children.empty();
}

RadixTreeNode<T> * add_child(std::string const & name, key_type key)
{
auto new_child = std::make_unique<RadixTreeNode<T>>(name, key);
Expand Down Expand Up @@ -167,6 +173,7 @@ class RadixTree
return m_current_node == m_root.get();
}

RadixTreeNode<T> * get_root() const { return m_root.get(); }
RadixTreeNode<T> * get_current_node() const { return m_current_node; }
key_type get_unique_node() const { return m_unique_id; }

Expand Down Expand Up @@ -238,19 +245,23 @@ class CallProfiler
CallProfiler & operator=(CallProfiler &&) = delete;
~CallProfiler() = default;

RadixTree<CallerProfile> & radix_tree()
{
return m_radix_tree;
}

// Called when a function starts
void start_caller(const std::string & caller_name, std::function<void()> cancel_callback)
{
m_cancel_callbacks.push_back(cancel_callback);
auto start_time = std::chrono::high_resolution_clock::now();
m_radix_tree.entry(caller_name);
CallerProfile & callProfile = m_radix_tree.get_current_node()->data();
callProfile.caller_name = caller_name;
callProfile.start_stopwatch();
}

// Called when a function ends
void end_caller(const std::string & caller_name)
void end_caller()
{
CallerProfile & call_profile = m_radix_tree.get_current_node()->data();
call_profile.stop_stopwatch(); // Update profiling information
Expand Down Expand Up @@ -293,8 +304,8 @@ class CallProfilerProbe
{
public:
CallProfilerProbe(CallProfiler & profiler, const char * caller_name)
: m_profiler(profiler)
, m_caller_name(caller_name)
: m_caller_name(caller_name)
, m_profiler(profiler)
{
auto cancel_callback = [&]()
{
Expand All @@ -312,7 +323,7 @@ class CallProfilerProbe
{
if (!m_cancel)
{
m_profiler.end_caller(m_caller_name);
m_profiler.end_caller();
}
}

Expand Down
87 changes: 86 additions & 1 deletion cpp/modmesh/toggle/pymod/wrap_profile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#include <modmesh/toggle/pymod/toggle_pymod.hpp> // Must be the first include.
#include <modmesh/modmesh.hpp>
#include <queue>
#include <unordered_map>

namespace modmesh
{
Expand Down Expand Up @@ -163,16 +165,99 @@ class MODMESH_PYTHON_WRAPPER_VISIBILITY WrapTimeRegistry

}; /* end class WrapTimeRegistry */

class MODMESH_PYTHON_WRAPPER_VISIBILITY WrapCallProfiler : public WrapBase<WrapCallProfiler, CallProfiler>
{
public:
friend root_base_type;

protected:
WrapCallProfiler(pybind11::module & mod, char const * pyname, char const * pydoc)
: root_base_type(mod, pyname, pydoc)
{
namespace py = pybind11;

(*this)
.def_property_readonly_static(
"instance",
[](py::object const &) -> wrapped_type &
{ return wrapped_type::instance(); })
.def("result", [](CallProfiler & profiler)
{
const RadixTreeNode<CallerProfile> * root = profiler.radix_tree().get_root();
if (root->no_children()) {
return py::dict();
}
py::dict result;
std::queue<const RadixTreeNode<CallerProfile>*> node_queue;
std::unordered_map<const RadixTreeNode<CallerProfile>*, py::dict> dict_storage;

node_queue.push(root);
dict_storage[root] = result;

while (!node_queue.empty()) {
const RadixTreeNode<CallerProfile>* cur_node = node_queue.front();
const py::dict& current_dict = dict_storage[cur_node];
node_queue.pop();

current_dict["name"] = cur_node->name();
current_dict["total_time"] = cur_node->data().total_time.count() / 1e6;
current_dict["count"] = cur_node->data().call_count;
if (cur_node == profiler.radix_tree().get_current_node()){
current_dict["current_node"] = true;
}

py::list children_list;
for (const auto& child : cur_node->children()) {
dict_storage[child.get()] = py::dict();
py::dict& child_dict = dict_storage[child.get()];
children_list.append(child_dict);
node_queue.push(child.get());
}
current_dict["children"] = children_list;
}
return result; })
.def("reset", &wrapped_type::reset);
;

mod.attr("call_profiler") = mod.attr("CallProfiler").attr("instance");
}
}; /* end class WrapCallProfiler */

class MODMESH_PYTHON_WRAPPER_VISIBILITY WrapCallProfilerProbe : public WrapBase<WrapCallProfilerProbe, CallProfilerProbe>
{
public:
friend root_base_type;

protected:
WrapCallProfilerProbe(pybind11::module & mod, char const * pyname, char const * pydoc)
: root_base_type(mod, pyname, pydoc)
{
namespace py = pybind11;

(*this)
.def(
py::init(
[](const char * caller_name)
{
return std::make_unique<CallProfilerProbe>(CallProfiler::instance(), caller_name);
}),
py::arg("caller_name"))
.def("cancel", &wrapped_type::cancel);
}
}; /* end class WrapCallProfilerProbe */

void wrap_profile(pybind11::module & mod)
{
WrapWrapperProfilerStatus::commit(mod, "WrapperProfilerStatus", "WrapperProfilerStatus");
WrapStopWatch::commit(mod, "StopWatch", "StopWatch");
WrapTimedEntry::commit(mod, "TimedEntry", "TimeEntry");
WrapTimeRegistry::commit(mod, "TimeRegistry", "TimeRegistry");
WrapCallProfiler::commit(mod, "CallProfiler", "CallProfiler");
WrapCallProfilerProbe::commit(mod, "CallProfilerProbe", "CallProfilerProbe");
}

} /* end namespace python */

} /* end namespace modmesh */

// vim: set ff=unix fenc=utf8 et sw=4 ts=4 sts=4:
// vim: set ff=unix fenc=utf8 et sw=4 ts=4 sts=4:
1 change: 1 addition & 0 deletions cpp/modmesh/toggle/toggle.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include <modmesh/base.hpp>
#include <modmesh/buffer/buffer.hpp>
#include <modmesh/toggle/profile.hpp>
#include <modmesh/toggle/RadixTree.hpp>

#include <string>
#include <vector>
Expand Down
3 changes: 3 additions & 0 deletions modmesh/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@
'stop_watch',
'TimeRegistry',
'time_registry',
'CallProfiler',
'call_profiler',
'CallProfilerProbe',
'ConcreteBuffer',
'BufferExpander',
'Gmsh',
Expand Down
41 changes: 41 additions & 0 deletions tests/data/profiler_python_schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"type": "object",
"properties": {
"name": {"type": "string"},
"total_time": {"type": "number"},
"count": {"type": "integer"},
"current_node": {"type": "boolean"},
"children": {
"type": "array",
"items": {
"type": "object",
"properties": {
"name": {"type": "string"},
"total_time": {"type": "number"},
"count": {"type": "integer"},
"children": {
"type": "array",
"items": {"$ref": "#/definitions/child"}
}
},
"required": ["name", "total_time", "count", "children"]
}
}
},
"required": ["name", "total_time", "count", "current_node", "children"],
"definitions": {
"child": {
"type": "object",
"properties": {
"name": {"type": "string"},
"total_time": {"type": "number"},
"count": {"type": "integer"},
"children": {
"type": "array",
"items": {"$ref": "#/definitions/child"}
}
},
"required": ["name", "total_time", "count", "children"]
}
}
}
Loading

0 comments on commit 1f07576

Please sign in to comment.