Skip to content

Commit 004c615

Browse files
authored
Merge pull request #133 from senseshift/feature/reduce-overhead
perf: reduce vtable usage
2 parents 32cc34a + 3852b4d commit 004c615

36 files changed

Lines changed: 486 additions & 303 deletions

File tree

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
import json
2+
import pandas as pd
3+
import argparse
4+
5+
6+
# Function to load JSON data from files
7+
def load_json(filename):
8+
with open(filename, 'r') as f:
9+
return json.load(f)
10+
11+
12+
# Function to compare values and create formatted strings
13+
def compare_values(base, current, key):
14+
if key not in base and key not in current:
15+
return None
16+
if key not in base:
17+
return f"🆕 {current[key]}"
18+
if key not in current:
19+
return f"❌"
20+
21+
base_value = base[key]
22+
current_value = current[key]
23+
24+
if base_value == current_value:
25+
return f"🆗 {base_value}"
26+
27+
change = current_value - base_value
28+
sign = "+" if change > 0 else "-"
29+
symbol = "⚠️" if change > 0 else "⬇️"
30+
31+
# round to 2 decimal places
32+
change = round(abs(change), 2)
33+
return f"{symbol} {current_value} <sub>{sign}{change}</sub>"
34+
35+
36+
# Function to generate Markdown table
37+
def generate_markdown_table(base_data, current_data):
38+
table_data = []
39+
40+
all_keys = set(base_data.keys()).union(set(current_data.keys()))
41+
all_keys = sorted(all_keys)
42+
43+
for key in all_keys:
44+
base_ram = base_data.get(key, {}).get("ram", {})
45+
current_ram = current_data.get(key, {}).get("ram", {})
46+
47+
base_flash = base_data.get(key, {}).get("flash", {})
48+
current_flash = current_data.get(key, {}).get("flash", {})
49+
50+
row = [
51+
key.replace("-usage", ""),
52+
compare_values(base_ram, current_ram, "percentage"),
53+
compare_values(base_ram, current_ram, "used"),
54+
compare_values(base_flash, current_flash, "percentage"),
55+
compare_values(base_flash, current_flash, "used")
56+
]
57+
table_data.append(row)
58+
59+
df = pd.DataFrame(table_data, columns=["Variant", "RAM, %", "RAM, bytes", "Flash, %", "Flash, bytes"])
60+
61+
return df.to_markdown(index=False)
62+
63+
64+
# Main function to handle CLI arguments and execute the script
65+
def main():
66+
parser = argparse.ArgumentParser(description='Compare JSON files and generate a markdown table.')
67+
parser.add_argument('base', type=str, help='Path to the base JSON file')
68+
parser.add_argument('current', type=str, help='Path to the current JSON file')
69+
parser.add_argument('--output', type=str, help='Path to the output markdown file')
70+
args = parser.parse_args()
71+
72+
base_data = load_json(args.base)
73+
current_data = load_json(args.current)
74+
75+
markdown_table = generate_markdown_table(base_data, current_data)
76+
77+
if args.output:
78+
with open(args.output, 'w') as f:
79+
f.write(markdown_table)
80+
print(f"Markdown table generated and saved to {args.output}")
81+
else:
82+
print(markdown_table)
83+
84+
85+
# usage: python compare-memory-usage.py base.json current.json --output table.md
86+
if __name__ == "__main__":
87+
main()

.github/workflows/ci.yml

Lines changed: 67 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,11 @@ jobs:
4949
coverage: true
5050
battery_flag: SS_BATTERY_ENABLED=true
5151
nimble_flag: SS_USE_NIMBLE=true
52-
# - target: bhaptics_tactsuit_x40
53-
# os: ubuntu-latest
54-
# coverage: true
55-
# battery_flag: SS_BATTERY_ENABLED=true
56-
# nimble_flag: SS_USE_NIMBLE=false
52+
- target: bhaptics_tactsuit_x40
53+
os: ubuntu-latest
54+
coverage: true
55+
battery_flag: SS_BATTERY_ENABLED=true
56+
nimble_flag: SS_USE_NIMBLE=false
5757
- target: bhaptics_tactsuit_x40
5858
os: ubuntu-latest
5959
coverage: false
@@ -532,8 +532,6 @@ jobs:
532532
pattern: '*-usage'
533533
merge-multiple: true
534534

535-
- run: ls -lahR current-usage
536-
537535
- name: Merge usage files
538536
shell: python
539537
run: |
@@ -579,6 +577,68 @@ jobs:
579577
name: merged-usage
580578
path: current-usage/merged.json
581579

580+
- name: Get base branch job ID
581+
if: github.event_name == 'pull_request'
582+
id: base_branch_workflow
583+
uses: actions/github-script@v7
584+
with:
585+
script: |
586+
const { data: workflows } = await github.rest.actions.listWorkflowRuns({
587+
owner: context.repo.owner,
588+
repo: context.repo.repo,
589+
branch: context.payload.pull_request.base.ref,
590+
event: 'push',
591+
workflow_id: 'ci.yml',
592+
status: 'completed',
593+
per_page: 1
594+
});
595+
596+
const baseBranchJobId = workflows.workflow_runs[0].id;
597+
console.log(baseBranchJobId);
598+
599+
return baseBranchJobId;
600+
601+
602+
- name: Download base branch usage.json artifact
603+
if: github.event_name == 'pull_request'
604+
id: download-base-usage
605+
uses: actions/download-artifact@v4
606+
with:
607+
name: merged-usage
608+
path: base-usage
609+
github-token: ${{ secrets.GITHUB_TOKEN }}
610+
repository: ${{ github.repository }}
611+
run-id: ${{ steps.base_branch_workflow.outputs.result }}
612+
613+
- uses: actions/setup-python@v2
614+
if: github.event_name == 'pull_request'
615+
with:
616+
python-version: '3.x'
617+
618+
- name: Report memory usage table
619+
if: github.event_name == 'pull_request'
620+
shell: bash
621+
run: |
622+
python -m pip install --upgrade pip pandas tabulate
623+
624+
cat ./base-usage/merged.json
625+
cat ./current-usage/merged.json
626+
627+
echo "## Memory Usage Comparison" > memory-usage-comparison.md
628+
echo "" >> memory-usage-comparison.md
629+
echo "<details>" >> memory-usage-comparison.md
630+
echo " <summary>Click to expand</summary>" >> memory-usage-comparison.md
631+
echo "" >> memory-usage-comparison.md
632+
python ./.github/scripts/compare-memory-usage.py ./base-usage/merged.json ./current-usage/merged.json | tee -a memory-usage-comparison.md
633+
echo "</details>" >> memory-usage-comparison.md
634+
635+
cat ./memory-usage-comparison.md > $GITHUB_STEP_SUMMARY
636+
637+
- uses: thollander/actions-comment-pull-request@v2
638+
if: github.event_name == 'pull_request'
639+
with:
640+
filePath: memory-usage-comparison.md
641+
comment_tag: memory-usage-comparison
582642
wokwi:
583643
needs:
584644
- build-bhaptics

.idea/misc.xml

Lines changed: 4 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

.idea/senseshift-firmware.iml

Lines changed: 7 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

firmware/mode_configs/bhaptics/tactsuit_x40.cpp

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,26 +57,24 @@ void setupMode()
5757

5858
// Assign the pins on the configured PCA9685s and PWM pins to locations on the
5959
// vest
60-
auto frontOutputs = PlaneMapper_Margin::
61-
mapMatrixCoordinates<FloatPlane::Actuator*, std::array<std::array<FloatPlane::Actuator*, 4>, 5>>({ {
62-
// clang-format off
60+
auto frontOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator*>({
61+
// clang-format off
6362
{ new PCA9685Output(pwm0, 0), new PCA9685Output(pwm0, 1), new PCA9685Output(pwm0, 2), new PCA9685Output(pwm0, 3) },
6463
{ new PCA9685Output(pwm0, 4), new PCA9685Output(pwm0, 5), new PCA9685Output(pwm0, 6), new PCA9685Output(pwm0, 7) },
6564
{ new PCA9685Output(pwm0, 8), new PCA9685Output(pwm0, 9), new PCA9685Output(pwm0, 10), new PCA9685Output(pwm0, 11) },
6665
{ new PCA9685Output(pwm0, 12), new PCA9685Output(pwm0, 13), new PCA9685Output(pwm0, 14), new PCA9685Output(pwm0, 15) },
6766
{ new LedcOutput(32), new LedcOutput(33), new LedcOutput(25), new LedcOutput(26) },
68-
// clang-format on
69-
} });
70-
auto backOutputs = PlaneMapper_Margin::
71-
mapMatrixCoordinates<FloatPlane::Actuator*, std::array<std::array<FloatPlane::Actuator*, 4>, 5>>({ {
72-
// clang-format off
67+
// clang-format on
68+
});
69+
auto backOutputs = PlaneMapper_Margin::mapMatrixCoordinates<FloatPlane::Actuator*>({
70+
// clang-format off
7371
{ new PCA9685Output(pwm1, 0), new PCA9685Output(pwm1, 1), new PCA9685Output(pwm1, 2), new PCA9685Output(pwm1, 3) },
7472
{ new PCA9685Output(pwm1, 4), new PCA9685Output(pwm1, 5), new PCA9685Output(pwm1, 6), new PCA9685Output(pwm1, 7) },
7573
{ new PCA9685Output(pwm1, 8), new PCA9685Output(pwm1, 9), new PCA9685Output(pwm1, 10), new PCA9685Output(pwm1, 11) },
7674
{ new PCA9685Output(pwm1, 12), new PCA9685Output(pwm1, 13), new PCA9685Output(pwm1, 14), new PCA9685Output(pwm1, 15) },
7775
{ new LedcOutput(27), new LedcOutput(14), new LedcOutput(12), new LedcOutput(13) },
78-
// clang-format on
79-
} });
76+
// clang-format on
77+
});
8078

8179
app->getVibroBody()->addTarget(Target::ChestFront, new FloatPlane_Closest(frontOutputs));
8280
app->getVibroBody()->addTarget(Target::ChestBack, new FloatPlane_Closest(backOutputs));

include/senseshift.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Application final : public IEventDispatcher {
1313
public:
1414
Application();
1515

16-
[[nodiscard]] auto getVibroBody() const -> Body::Haptics::FloatBody*
16+
auto getVibroBody() const -> Body::Haptics::FloatBody*
1717
{
1818
return this->vibro_body_;
1919
}

lib/arduino/senseshift/arduino/input/sensor/analog.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
#include <cstdint>
44

5-
#include <senseshift/input/sensor/sensor.hpp>
5+
#include <senseshift/input/sensor.hpp>
66

77
#include <Arduino.h>
88

@@ -33,7 +33,7 @@ class AnalogSimpleSensor : public ::SenseShift::Input::IFloatSimpleSensor {
3333
pinMode(this->pin_, INPUT);
3434
}
3535

36-
[[nodiscard]] inline auto getValue() -> float override
36+
inline auto getValue() -> float override
3737
{
3838
const std::uint16_t raw = analogRead(this->pin_);
3939
return static_cast<float>(raw) / ANALOG_MAX;

lib/arduino/senseshift/arduino/input/sensor/digital.hpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
#include <Arduino.h>
66

7-
#include <senseshift/input/sensor/sensor.hpp>
7+
#include <senseshift/input/sensor.hpp>
88

99
namespace SenseShift::Arduino::Input {
1010
class DigitalSimpleSensor : public ::SenseShift::Input::IBinarySimpleSensor {
@@ -21,7 +21,7 @@ class DigitalSimpleSensor : public ::SenseShift::Input::IBinarySimpleSensor {
2121
pinMode(this->pin_, this->mode_);
2222
}
2323

24-
[[nodiscard]] auto getValue() -> bool override
24+
auto getValue() -> bool override
2525
{
2626
return digitalRead(this->pin_) == this->inverted_;
2727
}

lib/arduino/senseshift/arduino/input/sensor/multiplexer.hpp

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,19 @@
1111
#include "senseshift/arduino/input/sensor/digital.hpp"
1212

1313
#include <senseshift/core/component.hpp>
14-
#include <senseshift/input/sensor/sensor.hpp>
14+
#include <senseshift/input/sensor.hpp>
1515

1616
namespace SenseShift::Arduino::Input {
1717
template<size_t N>
18-
class Multiplexer : public IInitializable {
18+
class Multiplexer {
1919
public:
2020
/// \param pins The pins to use for the multiplexer.
2121
explicit Multiplexer(const std::array<std::uint8_t, N>& pins, const size_t switch_delay_us = 2) :
2222
pins_(pins), switch_delay_us_(switch_delay_us)
2323
{
2424
}
2525

26-
void init() override
26+
void init()
2727
{
2828
for (const auto pin : this->pins_) {
2929
pinMode(pin, OUTPUT);
@@ -74,7 +74,7 @@ class MultiplexedAnalogSensor : public AnalogSimpleSensor {
7474
AnalogSimpleSensor::init();
7575
}
7676

77-
[[nodiscard]] auto getValue() -> float override
77+
auto getValue() -> float override
7878
{
7979
this->component_->selectChannel(this->channel_);
8080

@@ -86,17 +86,16 @@ class MultiplexedAnalogSensor : public AnalogSimpleSensor {
8686
const std::uint8_t channel_;
8787
};
8888

89+
template<size_t N>
8990
class MultiplexedDigitalSensor : public DigitalSimpleSensor {
9091
public:
9192
/// \param component The CD74HC4057 Component to use.
9293
/// \param pin The SIG pin of the sensor.
9394
/// \param channel The channel to read from.
94-
MultiplexedDigitalSensor(
95-
MUX_CD74HC4057Component* component, const std::uint8_t pin_sig, const std::uint8_t channel
96-
) :
95+
MultiplexedDigitalSensor(Multiplexer<N>* component, const std::uint8_t pin_sig, const std::uint8_t channel) :
9796
component_(component), DigitalSimpleSensor(pin_sig), channel_(channel)
9897
{
99-
assert(channel < 16 && "Channel out of range");
98+
assert(channel < (1 << N) && "Channel out of range");
10099
}
101100

102101
void init() override
@@ -105,15 +104,15 @@ class MultiplexedDigitalSensor : public DigitalSimpleSensor {
105104
DigitalSimpleSensor::init();
106105
}
107106

108-
[[nodiscard]] auto getValue() -> bool override
107+
auto getValue() -> bool override
109108
{
110109
this->component_->selectChannel(this->channel_);
111110

112111
return DigitalSimpleSensor::getValue();
113112
}
114113

115114
private:
116-
MUX_CD74HC4057Component* component_;
115+
Multiplexer<N>* component_;
117116
const std::uint8_t channel_;
118117
};
119118

lib/arduino_esp32/senseshift/arduino/output/ledc.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class LedcOutput : public ::SenseShift::Output::IFloatOutput {
4141
}
4242
}
4343

44-
[[nodiscard]] inline auto getMaxValue() const -> std::uint32_t
44+
inline auto getMaxValue() const -> std::uint32_t
4545
{
4646
return (1 << this->analog_resolution_) - 1;
4747
}

0 commit comments

Comments
 (0)