summaryrefslogtreecommitdiff
path: root/rtemsspec
diff options
context:
space:
mode:
authorSebastian Huber <sebastian.huber@embedded-brains.de>2023-11-21 11:13:15 +0100
committerSebastian Huber <sebastian.huber@embedded-brains.de>2023-11-21 11:15:24 +0100
commit010b732a89352993eda688f2352375464fd712e3 (patch)
treea3452f1080cb143f30d83a2ffd102e7eed47d646 /rtemsspec
parent07aaa327e54123c2c9852a650fd9db598c3dc11a (diff)
membench: Support variant comparison
Diffstat (limited to 'rtemsspec')
-rw-r--r--rtemsspec/membench.py367
-rw-r--r--rtemsspec/tests/spec-membench/r2.yml15
-rw-r--r--rtemsspec/tests/spec-membench/r3.yml15
-rw-r--r--rtemsspec/tests/spec-membench/r4.yml15
-rw-r--r--rtemsspec/tests/spec-membench/rtems/val/mem-basic.yml54
-rw-r--r--rtemsspec/tests/spec-membench/t1.yml2
-rw-r--r--rtemsspec/tests/spec-membench/t2.yml20
-rw-r--r--rtemsspec/tests/spec-membench/t3.yml20
-rw-r--r--rtemsspec/tests/test_membench.py194
9 files changed, 654 insertions, 48 deletions
diff --git a/rtemsspec/membench.py b/rtemsspec/membench.py
index 6453aad1..b395f728 100644
--- a/rtemsspec/membench.py
+++ b/rtemsspec/membench.py
@@ -4,7 +4,7 @@ This module provides functions for the generation of memory benchmark
documentation.
"""
-# Copyright (C) 2021 embedded brains GmbH & Co. KG
+# Copyright (C) 2021, 2023 embedded brains GmbH & Co. KG
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -29,12 +29,25 @@ documentation.
import os
import re
-from typing import Dict, List, Tuple
+from typing import Any, Dict, List, NamedTuple, Tuple
-from rtemsspec.items import Item, ItemMapper
-from rtemsspec.sphinxcontent import make_label, get_reference, SphinxContent
+from rtemsspec.items import Item, ItemCache, ItemMapper
+from rtemsspec.sphinxcontent import get_reference, SphinxContent
from rtemsspec.util import run_command
+
+class MembenchVariant(NamedTuple):
+ """ Represents a static memory benchmark configuration. """
+ name: str
+ build_label: str
+
+
+SectionsByUID = Dict[str, Dict[str, int]]
+
+_SECTIONS = {".text": 0, ".rodata": 1, ".data": 2, ".bss": 3, ".noinit": 4}
+
+_SECTION_KEYS = tuple(sorted(_SECTIONS.keys(), key=lambda x: _SECTIONS[x]))
+
_SECTION = re.compile(
r"^\s*\d+\s+(\S+)\s+([0-9a-fA-F]+)\s+([0-9a-fA-F]+)\s+[0-9a-fA-F]+"
r"\s+[0-9a-fA-F]+\s+.*$")
@@ -53,6 +66,7 @@ _SECTION_MAP = {
".debug_line_str": None,
".debug_loc": None,
".debug_loclists": None,
+ ".debug_pubnames": None,
".debug_ranges": None,
".debug_rnglists": None,
".debug_str": None,
@@ -81,6 +95,184 @@ _SECTION_MAP = {
".xbarrier": None,
}
+_OBJECT_SIZES = {
+ "/c/void-pointer": {
+ "commands": ["sizeof(void *)"],
+ "uid": "/rtems/val/mem-basic"
+ },
+ "/rtems/barrier/info": {
+ "commands": ["sizeof(_Barrier_Information)"],
+ "uid": "/rtems/barrier/val/mem-wait-rel-del"
+ },
+ "/rtems/barrier/obj": {
+ "commands": ["sizeof(Objects_Control *) + sizeof(Barrier_Control)"],
+ "uid": "/rtems/barrier/val/mem-wait-rel-del"
+ },
+ "/rtems/message/info": {
+ "commands": ["sizeof(_Message_queue_Information)"],
+ "uid": "/rtems/message/val/mem-snd-rcv-del"
+ },
+ "/rtems/message/obj": {
+ "commands":
+ ["sizeof(Objects_Control *) + sizeof(Message_queue_Control)"],
+ "uid": "/rtems/message/val/mem-snd-rcv-del"
+ },
+ "/rtems/part/info": {
+ "commands": ["sizeof(_Partition_Information)"],
+ "uid": "/rtems/part/val/mem-get-ret-del"
+ },
+ "/rtems/part/obj": {
+ "commands": ["sizeof(Objects_Control *) + sizeof(Partition_Control)"],
+ "uid": "/rtems/part/val/mem-get-ret-del"
+ },
+ "/rtems/priority/control": {
+ "commands": ["sizeof(Priority_Control)"],
+ "uid": "/rtems/sem/val/mem-obt-rel-del"
+ },
+ "/rtems/ratemon/info": {
+ "commands": ["sizeof(_Rate_monotonic_Information)"],
+ "uid": "/rtems/ratemon/val/mem-period-del"
+ },
+ "/rtems/ratemon/obj": {
+ "commands":
+ ["sizeof(Objects_Control *) + sizeof(Rate_monotonic_Control)"],
+ "uid": "/rtems/ratemon/val/mem-period-del"
+ },
+ "/rtems/sem/info": {
+ "commands": ["sizeof(_Semaphore_Information)"],
+ "uid": "/rtems/sem/val/mem-obt-rel-del"
+ },
+ "/rtems/sem/obj": {
+ "commands": ["sizeof(Objects_Control *) + sizeof(Semaphore_Control)"],
+ "uid": "/rtems/sem/val/mem-obt-rel-del"
+ },
+ "/rtems/sem/obj-mrsp": {
+ "commands": [
+ "sizeof(Objects_Control *) + sizeof(Objects_Control) + "
+ "sizeof(MRSP_Control)"
+ ],
+ "uid":
+ "/rtems/sem/val/mem-obt-rel-del"
+ },
+ "/rtems/task/info": {
+ "commands": ["sizeof(_RTEMS_tasks_Information)"],
+ "uid": "/rtems/val/mem-basic"
+ },
+ "/rtems/task/obj": {
+ "commands": [
+ "sizeof(Objects_Control *) + sizeof(Thread_Control) + "
+ "sizeof(RTEMS_API_Control) + sizeof(Thread_queue_Heads)",
+ "sizeof(Objects_Control *) + sizeof(Thread_Control) + "
+ "sizeof(RTEMS_API_Control)"
+ ],
+ "uid":
+ "/rtems/val/mem-basic"
+ },
+ "/rtems/timer/info": {
+ "commands": ["sizeof(_Timer_Information)"],
+ "uid": "/rtems/timer/val/mem-after"
+ },
+ "/rtems/timer/obj": {
+ "commands": ["sizeof(Objects_Control *) + sizeof(Timer_Control)"],
+ "uid": "/rtems/timer/val/mem-after"
+ },
+ "/rtems/userext/info": {
+ "commands": ["sizeof(_Extension_Information)"],
+ "uid": "/rtems/userext/val/mem-create"
+ },
+ "/rtems/userext/obj": {
+ "commands": ["sizeof(Objects_Control *) + sizeof(Extension_Control)"],
+ "uid": "/rtems/userext/val/mem-create"
+ },
+ "/scheduler/control": {
+ "commands": ["sizeof(Scheduler_Control)"],
+ "uid": "/rtems/val/mem-basic"
+ },
+ "/scheduler/priority/context": {
+ "commands": ["sizeof(Scheduler_priority_Context)"],
+ "uid": "/rtems/val/mem-basic"
+ },
+ "/scheduler/priority/node": {
+ "commands": ["sizeof(Scheduler_priority_Node)"],
+ "uid": "/rtems/val/mem-basic"
+ },
+ "/scheduler/smp/edf/context": {
+ "commands": [
+ "sizeof(Scheduler_EDF_SMP_Context) + "
+ "sizeof(Scheduler_EDF_SMP_Ready_queue)"
+ ],
+ "uid":
+ "/rtems/val/mem-smp-1"
+ },
+ "/scheduler/smp/edf/node": {
+ "commands": ["sizeof(Scheduler_EDF_SMP_Node)"],
+ "uid": "/rtems/val/mem-smp-1"
+ },
+ "/scheduler/smp/edf/ready-queue": {
+ "commands": ["sizeof(Scheduler_EDF_SMP_Ready_queue)"],
+ "uid": "/rtems/val/mem-smp-1"
+ },
+ "/score/chain/control": {
+ "commands": ["sizeof(Chain_Control)"],
+ "uid": "/rtems/val/mem-basic"
+ },
+ "/score/tq/priority-queue": {
+ "commands": ["sizeof(Thread_queue_Priority_queue)"],
+ "uid": "/rtems/val/mem-basic"
+ },
+}
+
+
+def _section_key(key_value: Tuple[str, Any]) -> int:
+ return _SECTIONS[key_value[0]]
+
+
+def _get_sections_of_item(sections_by_uid: SectionsByUID,
+ item: Item) -> Tuple[int, ...]:
+ return tuple(size for _, size in sorted(
+ sections_by_uid.get(item.uid, {}).items(), key=_section_key))
+
+
+def gather_sections(item_cache: ItemCache, path: str, objdump: str,
+ gdb: str) -> Dict[str, Dict[str, int]]:
+ """
+ Gathers the object sizes for all memory benchmarks of the item cache using
+ the programs of the path.
+ """
+ sections_by_uid: Dict[str, Dict[str, int]] = {}
+ for item in item_cache.items_by_type["memory-benchmark"]:
+ sections = _get_sections(item, path, objdump, gdb)
+ if sections:
+ sections_by_uid[item.uid] = sections
+ return sections_by_uid
+
+
+def gather_object_sizes(item_cache: ItemCache, path: str,
+ gdb: str) -> Dict[str, int]:
+ """
+ Gathers the object sizes for all memory benchmarks of the item cache using
+ the programs of the path.
+ """
+ object_sizes: Dict[str, int] = {}
+ for key, value in _OBJECT_SIZES.items():
+ try:
+ item = item_cache[value["uid"]]
+ except KeyError:
+ continue
+ file = _get_path_to_test_suite_elf_file(item, path)
+ for command in value["commands"]:
+ cmd = [gdb, "-ex", f"p {command}", "--batch", ""]
+ cmd[-1] = file
+ stdout: List[str] = []
+ status = run_command(cmd, stdout=stdout)
+ if status == 0:
+ output = " ".join(stdout)
+ match = re.search(r"\$[0-9]+\s*=\s*([0-9]+)", output)
+ assert match
+ object_sizes[key] = int(match.group(1))
+ break
+ return object_sizes
+
def _do_gather_test_suites(items: List[Item], item: Item) -> None:
if item.type == "memory-benchmark":
@@ -91,26 +283,64 @@ def _do_gather_test_suites(items: List[Item], item: Item) -> None:
_do_gather_test_suites(items, child)
-def gather_benchmarks(root: Item) -> List[Item]:
+def _gather_benchmarks(root: Item) -> List[Item]:
""" Gather all test suite items related to the root item. """
items: List[Item] = []
_do_gather_test_suites(items, root)
return items
-def get_path_to_test_suite_elf_file(item: Item, path: str) -> str:
+def _get_path_to_test_suite_elf_file(item: Item, path: str) -> str:
""" Returns the path to the ELF file of the test suite. """
- name = os.path.basename(item.uid).replace("mem-", "")
- module = os.path.basename(os.path.dirname(os.path.dirname(item.uid)))
- return f"{path}/mem-{module}-{name}.norun.exe"
+ name = item["test-target"]
+ return os.path.join(path, f"{name[:name.rfind('.')]}.norun.exe")
+
+
+def _try_add_workspace(gdb: str, elf: str,
+ section_limits: Dict[str, Tuple[int, int]]) -> None:
+ if ".noinit" in section_limits:
+ return
+ # Maybe an older version of RTEMS
+ stdout: List[str] = []
+ cmd = [gdb, "-ex", "p Configuration.work_space_size", "--batch", elf]
+ status = run_command(cmd, stdout=stdout)
+ if status == 0 and stdout[0].startswith("$1 = "):
+ section_limits[".noinit"] = (0, int(stdout[0][5:]))
+
+
+def _get_size(section_limits: Dict[str, Tuple[int, int]], key: str) -> int:
+ limits = section_limits.get(key, (0, 0))
+ return limits[1] - limits[0]
-def _get_sections(item: Item, path: str) -> Dict[str, Tuple[int, int]]:
- elf = get_path_to_test_suite_elf_file(item, path)
+def _run_objdump(objdump: str, elf: str) -> List[str]:
stdout: List[str] = []
- status = run_command(["objdump", "-h", elf], stdout=stdout)
- assert status == 0
- sections: Dict[str, Tuple[int, int]] = {}
+ status = run_command([objdump, "-h", elf], stdout=stdout)
+ if status != 0:
+ return []
+ return stdout
+
+
+def _make_sections(
+ section_limits: Dict[str, Tuple[int, int]]) -> Dict[str, int]:
+ sections: Dict[str, int] = {}
+ for key in _SECTIONS:
+ sections[key] = _get_size(section_limits, key)
+ sections[".noinit"] += _get_size(section_limits, ".vector")
+ return sections
+
+
+def _get_sections(item: Item, path_to_elf_files: str, objdump: str,
+ gdb: str) -> Dict[str, int]:
+ """
+ Gets the memory benchmark sections of the program associated with the item
+ in the path to ELF files.
+ """
+ elf = _get_path_to_test_suite_elf_file(item, path_to_elf_files)
+ stdout = _run_objdump(objdump, elf)
+ if not stdout:
+ return {}
+ section_limits: Dict[str, Tuple[int, int]] = {}
for line in stdout:
match = _SECTION.search(line)
if match:
@@ -120,29 +350,34 @@ def _get_sections(item: Item, path: str) -> Dict[str, Tuple[int, int]]:
if size != 0 and section:
start = int(match.group(3), 16)
end = start + size
- info = sections.get(section, (2**64, 0))
- sections[section] = (min(info[0], start), max(info[1], end))
- return sections
+ limits = section_limits.get(section, (2**64, 0))
+ section_limits[section] = (min(limits[0],
+ start), max(limits[1], end))
+ _try_add_workspace(gdb, elf, section_limits)
+ return _make_sections(section_limits)
def _make_label(item: Item) -> str:
- return make_label(f"MemBenchmark {item.uid[1:]}")
+ return f"Membench{item.ident}"
-def _generate_table(content: SphinxContent, items: List[Item],
- path: str) -> None:
+def _generate_table(content: SphinxContent, sections_by_uid: SectionsByUID,
+ items: List[Item]) -> None:
rows: List[Tuple[str, ...]] = []
for index, item in enumerate(items):
- sections = _get_sections(item, path)
- name = (get_reference(_make_label(item), item.uid), )
+ sections = _get_sections_of_item(sections_by_uid, item)
+ spec = (get_reference(_make_label(item), item.uid), )
if index == 0:
- keys = ("spec", ) + tuple(sections.keys())
- base = {key: info[1] - info[0] for key, info in sections.items()}
+ assert sections
+ keys = ("Specification", ) + _SECTION_KEYS
+ base = sections
rows.append(keys)
- rows.append(name + tuple(map(str, base.values())))
+ rows.append(spec + tuple(map(str, sections)))
+ elif sections:
+ rows.append(spec + tuple(f"{i - j:+}"
+ for i, j in zip(sections, base)))
else:
- rows.append(name + tuple(f"{info[1] - info[0] - base[key]:+}"
- for key, info in sections.items()))
+ rows.append(spec + tuple("?") * len(keys))
pivot = items[0]
section = f"Benchmarks Based on: {pivot.spec}"
@@ -153,23 +388,83 @@ memory benchmark defined by
content.add_simple_table(rows)
-def _generate_paragraphs(content: SphinxContent, items: List[Item],
- mapper: ItemMapper) -> None:
+_WARNING_NO_MEMBENCH = """.. topic:: WARNING
+
+ There are no results available for this static memory usage benchmark.
+"""
+
+
+def _generate_paragraphs(content: SphinxContent,
+ sections_by_uid: SectionsByUID, mapper: ItemMapper,
+ items: List[Item]) -> None:
for item in items:
section = f"Benchmark: {item.spec}"
with content.section(section, label=_make_label(item)):
content.wrap(mapper.substitute(item["test-brief"], item))
content.wrap(mapper.substitute(item["test-description"], item))
+ sections = _get_sections_of_item(sections_by_uid, item)
+ if sections:
+ content.add_simple_table(
+ [_SECTION_KEYS, tuple(map(str, sections))])
+ else:
+ content.add(_WARNING_NO_MEMBENCH)
+
+
+def _generate_tables(content: SphinxContent, sections_by_uid: SectionsByUID,
+ root: Item, table_pivots: List[str]) -> List[Item]:
+ root_items = _gather_benchmarks(root)
+ _generate_table(content, sections_by_uid, root_items)
+ for pivot_uid in table_pivots:
+ pivot = root.map(pivot_uid)
+ if not pivot.enabled:
+ continue
+ pivot_items = _gather_benchmarks(pivot)
+ _generate_table(content, sections_by_uid, pivot_items)
+ return root_items
+
+
+def generate_tables(content: SphinxContent, sections_by_uid: SectionsByUID,
+ root: Item, table_pivots: List[str]) -> None:
+ """ Generates memory benchmark tables. """
+ _generate_tables(content, sections_by_uid, root, table_pivots)
+
+
+def generate_variants_table(content: SphinxContent,
+ sections_by_build_label: Dict[str,
+ Dict[str,
+ SectionsByUID]],
+ root: Item,
+ variants: List[MembenchVariant]) -> None:
+ """ Generates memory benchmark variant comparison tables. """
+ items = _gather_benchmarks(root)
+ rows: List[Tuple[str,
+ ...]] = [("Specification", "Variant") + _SECTION_KEYS]
+ for item in items:
+ spec = get_reference(_make_label(item), item.uid)
+ for index, variant in enumerate(variants):
+ sections = _get_sections_of_item(
+ sections_by_build_label[variant.build_label]["membench"], item)
+ what = (spec, variant.name)
+ if index == 0:
+ assert sections
+ base = sections
+ rows.append(what + tuple(map(str, sections)))
+ else:
+ if sections:
+ rows.append(what + tuple(f"{i - j:+}"
+ for i, j in zip(sections, base)))
+ else:
+ rows.append(what + tuple("?") * len(base))
+ spec = ""
+ with content.latex_tiny("scriptsize"):
+ content.add_grid_table(rows, [35, 20, 9, 9, 9, 9, 9])
-def generate(content: SphinxContent, root: Item, mapper: ItemMapper,
- table_pivots: List[str], path: str) -> None:
+def generate(content: SphinxContent, sections_by_uid: SectionsByUID,
+ root: Item, table_pivots: List[str], mapper: ItemMapper) -> None:
"""
Generates memory benchmark documentation for items dependent on the root
item and executables in the path.
"""
- for pivot in table_pivots:
- items = gather_benchmarks(root.map(pivot))
- _generate_table(content, items, path)
- items = gather_benchmarks(root)
- _generate_paragraphs(content, items, mapper)
+ root_items = _generate_tables(content, sections_by_uid, root, table_pivots)
+ _generate_paragraphs(content, sections_by_uid, mapper, root_items)
diff --git a/rtemsspec/tests/spec-membench/r2.yml b/rtemsspec/tests/spec-membench/r2.yml
new file mode 100644
index 00000000..2ac74b9d
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/r2.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: requirement-refinement
+ uid: r0
+non-functional-type: quality
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+ The system shall provide a benchmark program to show the static memory usage
+ of a basic application configuration.
+type: requirement
diff --git a/rtemsspec/tests/spec-membench/r3.yml b/rtemsspec/tests/spec-membench/r3.yml
new file mode 100644
index 00000000..2ac74b9d
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/r3.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+links:
+- role: requirement-refinement
+ uid: r0
+non-functional-type: quality
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+ The system shall provide a benchmark program to show the static memory usage
+ of a basic application configuration.
+type: requirement
diff --git a/rtemsspec/tests/spec-membench/r4.yml b/rtemsspec/tests/spec-membench/r4.yml
new file mode 100644
index 00000000..6ad6dc06
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/r4.yml
@@ -0,0 +1,15 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: false
+links:
+- role: requirement-refinement
+ uid: r0
+non-functional-type: quality
+rationale: null
+references: []
+requirement-type: non-functional
+text: |
+ The system shall provide a benchmark program to show the static memory usage
+ of a basic application configuration.
+type: requirement
diff --git a/rtemsspec/tests/spec-membench/rtems/val/mem-basic.yml b/rtemsspec/tests/spec-membench/rtems/val/mem-basic.yml
new file mode 100644
index 00000000..8cfcd1cf
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/rtems/val/mem-basic.yml
@@ -0,0 +1,54 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+copyrights:
+- Copyright (C) 2021 embedded brains GmbH & Co. KG
+enabled-by: true
+links: []
+test-brief: |
+ This static memory usage benchmark program facilitates a basic application
+ configuration.
+test-code: |
+ static void Init( rtems_task_argument arg )
+ {
+ (void) arg;
+
+ /* Nothing to do */
+ }
+
+ #define TASK_ATTRIBUTES RTEMS_DEFAULT_ATTRIBUTES
+
+ #define TASK_STORAGE_SIZE \
+ RTEMS_TASK_STORAGE_SIZE( \
+ RTEMS_MINIMUM_STACK_SIZE, \
+ TASK_ATTRIBUTES )
+
+ #define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+
+ #define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 0
+
+ #define CONFIGURE_DISABLE_NEWLIB_REENTRANCY
+
+ #define CONFIGURE_APPLICATION_DISABLE_FILESYSTEM
+
+ #define CONFIGURE_IDLE_TASK_STORAGE_SIZE RTEMS_MINIMUM_STACK_SIZE
+
+ #define CONFIGURE_MAXIMUM_TASKS 1
+
+ #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+
+ #define CONFIGURE_INIT_TASK_ATTRIBUTES TASK_ATTRIBUTES
+
+ #define CONFIGURE_INIT_TASK_INITIAL_MODES RTEMS_DEFAULT_MODES
+
+ #define CONFIGURE_INIT_TASK_CONSTRUCT_STORAGE_SIZE TASK_STORAGE_SIZE
+
+ #define CONFIGURE_INIT
+
+ #include <rtems/confdefs.h>
+test-description: |
+ This resource benchmark is configured for exactly one processor, no clock
+ driver, no Newlib reentrancy support, and no file system.
+test-includes:
+- rtems.h
+test-local-includes: []
+test-target: mem-rtems-basic.c
+type: memory-benchmark
diff --git a/rtemsspec/tests/spec-membench/t1.yml b/rtemsspec/tests/spec-membench/t1.yml
index 1ea13629..b5683255 100644
--- a/rtemsspec/tests/spec-membench/t1.yml
+++ b/rtemsspec/tests/spec-membench/t1.yml
@@ -16,5 +16,5 @@ test-includes:
- blue.h
test-local-includes:
- green.h
-test-target: t0.c
+test-target: t1.c
type: memory-benchmark
diff --git a/rtemsspec/tests/spec-membench/t2.yml b/rtemsspec/tests/spec-membench/t2.yml
new file mode 100644
index 00000000..2fff64c4
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/t2.yml
@@ -0,0 +1,20 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+code: |
+ /* Blue green code */
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH & Co. KG
+description: The Blue Green description.
+enabled-by: true
+links:
+- role: validation
+ uid: r2
+test-brief: The Blue Green brief description.
+test-code: |
+ /* Blue green code */
+test-description: The Blue Green description.
+test-includes:
+- blue.h
+test-local-includes:
+- green.h
+test-target: t2.c
+type: memory-benchmark
diff --git a/rtemsspec/tests/spec-membench/t3.yml b/rtemsspec/tests/spec-membench/t3.yml
new file mode 100644
index 00000000..cf20ed3f
--- /dev/null
+++ b/rtemsspec/tests/spec-membench/t3.yml
@@ -0,0 +1,20 @@
+SPDX-License-Identifier: CC-BY-SA-4.0 OR BSD-2-Clause
+code: |
+ /* Blue green code */
+copyrights:
+- Copyright (C) 2020 embedded brains GmbH & Co. KG
+description: The Blue Green description.
+enabled-by: true
+links:
+- role: validation
+ uid: r3
+test-brief: The Blue Green brief description.
+test-code: |
+ /* Blue green code */
+test-description: The Blue Green description.
+test-includes:
+- blue.h
+test-local-includes:
+- green.h
+test-target: t3.c
+type: memory-benchmark
diff --git a/rtemsspec/tests/test_membench.py b/rtemsspec/tests/test_membench.py
index 76de9180..66ca8c7d 100644
--- a/rtemsspec/tests/test_membench.py
+++ b/rtemsspec/tests/test_membench.py
@@ -24,13 +24,26 @@
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
-from rtemsspec.membench import generate
+from rtemsspec.membench import gather_object_sizes, gather_sections, \
+ generate, generate_tables, generate_variants_table, MembenchVariant
from rtemsspec.items import ItemCache, ItemMapper
from rtemsspec.sphinxcontent import SphinxContent
from rtemsspec.tests.util import create_item_cache_config_and_copy_spec
def run_command(args, cwd=None, stdout=None):
+ if args[0] == "object-sizes":
+ if "Thread" in args[2]:
+ stdout.append("$1 = 42")
+ return 0
+ return 1
+ if args[0] == "gdb" and "t3" in args[-1]:
+ stdout.append("$1 = 133")
+ return 0
+ if "t2" in args[-1]:
+ return 1
+ if "t1" in args[-1] and "path-2" in args[-1]:
+ return 1
stdout.extend([
" 0 .start 00000708 00100000 00100000 00010000 2**2",
" CONTENTS, ALLOC, LOAD, READONLY, CODE",
@@ -38,6 +51,11 @@ def run_command(args, cwd=None, stdout=None):
" CONTENTS, ALLOC, LOAD, READONLY, CODE",
" 22 .debug_aranges 000011d8 00000000 00000000 000202e8 2**3"
])
+ if "t1" in args[-1]:
+ stdout.extend([
+ " 3 .noinit 00001900 400809e0 400809e0 000909e0 2**3",
+ " ALLOC"
+ ])
return 0
@@ -46,28 +64,55 @@ def test_membench(tmpdir, monkeypatch):
item_cache_config = create_item_cache_config_and_copy_spec(
tmpdir, "spec-membench", with_spec_types=True)
item_cache = ItemCache(item_cache_config)
+ object_sizes = gather_object_sizes(item_cache, "path", "object-sizes")
+ assert len(object_sizes) == 2
+ assert object_sizes["/rtems/task/obj"] == 42
+ sections_by_uid = gather_sections(item_cache, "path", "objdump", "gdb")
+ sections_by_uid_2 = gather_sections(item_cache, "path-2", "objdump", "gdb")
root = item_cache["/r0"]
content = SphinxContent()
- generate(content, root, ItemMapper(root), ["/r0"], "path")
+ generate(content, sections_by_uid, root, ["r0", "r4"], ItemMapper(root))
assert str(content) == """.. _BenchmarksBasedOnSpecT0:
Benchmarks Based on: spec:/t0
=============================
The following memory benchmarks are based on the memory benchmark defined by
-:ref:`spec:/t0 <MemBenchmarkT0>`.
+:ref:`spec:/t0 <MembenchT0>`.
.. table::
:class: longtable
- =========================== =====
- spec .text
- =========================== =====
- :ref:`/t0 <MemBenchmarkT0>` 38908
- :ref:`/t1 <MemBenchmarkT1>` +0
- =========================== =====
+ ======================= ===== ======= ===== ==== =======
+ Specification .text .rodata .data .bss .noinit
+ ======================= ===== ======= ===== ==== =======
+ :ref:`/t0 <MembenchT0>` 38908 0 0 0 0
+ :ref:`/t1 <MembenchT1>` +0 +0 +0 +0 +6400
+ :ref:`/t2 <MembenchT2>` ? ? ? ? ?
+ :ref:`/t3 <MembenchT3>` +0 +0 +0 +0 +133
+ ======================= ===== ======= ===== ==== =======
-.. _MemBenchmarkT0:
+.. _BenchmarksBasedOnSpecT0:
+
+Benchmarks Based on: spec:/t0
+=============================
+
+The following memory benchmarks are based on the memory benchmark defined by
+:ref:`spec:/t0 <MembenchT0>`.
+
+.. table::
+ :class: longtable
+
+ ======================= ===== ======= ===== ==== =======
+ Specification .text .rodata .data .bss .noinit
+ ======================= ===== ======= ===== ==== =======
+ :ref:`/t0 <MembenchT0>` 38908 0 0 0 0
+ :ref:`/t1 <MembenchT1>` +0 +0 +0 +0 +6400
+ :ref:`/t2 <MembenchT2>` ? ? ? ? ?
+ :ref:`/t3 <MembenchT3>` +0 +0 +0 +0 +133
+ ======================= ===== ======= ===== ==== =======
+
+.. _MembenchT0:
Benchmark: spec:/t0
===================
@@ -76,7 +121,16 @@ The Blue Green brief description.
The Blue Green description.
-.. _MemBenchmarkT1:
+.. table::
+ :class: longtable
+
+ ===== ======= ===== ==== =======
+ .text .rodata .data .bss .noinit
+ ===== ======= ===== ==== =======
+ 38908 0 0 0 0
+ ===== ======= ===== ==== =======
+
+.. _MembenchT1:
Benchmark: spec:/t1
===================
@@ -84,4 +138,122 @@ Benchmark: spec:/t1
The Blue Green brief description.
The Blue Green description.
+
+.. table::
+ :class: longtable
+
+ ===== ======= ===== ==== =======
+ .text .rodata .data .bss .noinit
+ ===== ======= ===== ==== =======
+ 38908 0 0 0 6400
+ ===== ======= ===== ==== =======
+
+.. _MembenchT2:
+
+Benchmark: spec:/t2
+===================
+
+The Blue Green brief description.
+
+The Blue Green description.
+
+.. topic:: WARNING
+
+ There are no results available for this static memory usage benchmark.
+
+.. _MembenchT3:
+
+Benchmark: spec:/t3
+===================
+
+The Blue Green brief description.
+
+The Blue Green description.
+
+.. table::
+ :class: longtable
+
+ ===== ======= ===== ==== =======
+ .text .rodata .data .bss .noinit
+ ===== ======= ===== ==== =======
+ 38908 0 0 0 133
+ ===== ======= ===== ==== =======
+"""
+ content = SphinxContent()
+ generate_tables(content, sections_by_uid, root, ["r0", "r4"])
+ assert str(content) == """.. _BenchmarksBasedOnSpecT0:
+
+Benchmarks Based on: spec:/t0
+=============================
+
+The following memory benchmarks are based on the memory benchmark defined by
+:ref:`spec:/t0 <MembenchT0>`.
+
+.. table::
+ :class: longtable
+
+ ======================= ===== ======= ===== ==== =======
+ Specification .text .rodata .data .bss .noinit
+ ======================= ===== ======= ===== ==== =======
+ :ref:`/t0 <MembenchT0>` 38908 0 0 0 0
+ :ref:`/t1 <MembenchT1>` +0 +0 +0 +0 +6400
+ :ref:`/t2 <MembenchT2>` ? ? ? ? ?
+ :ref:`/t3 <MembenchT3>` +0 +0 +0 +0 +133
+ ======================= ===== ======= ===== ==== =======
+
+.. _BenchmarksBasedOnSpecT0:
+
+Benchmarks Based on: spec:/t0
+=============================
+
+The following memory benchmarks are based on the memory benchmark defined by
+:ref:`spec:/t0 <MembenchT0>`.
+
+.. table::
+ :class: longtable
+
+ ======================= ===== ======= ===== ==== =======
+ Specification .text .rodata .data .bss .noinit
+ ======================= ===== ======= ===== ==== =======
+ :ref:`/t0 <MembenchT0>` 38908 0 0 0 0
+ :ref:`/t1 <MembenchT1>` +0 +0 +0 +0 +6400
+ :ref:`/t2 <MembenchT2>` ? ? ? ? ?
+ :ref:`/t3 <MembenchT3>` +0 +0 +0 +0 +133
+ ======================= ===== ======= ===== ==== =======
+"""
+ content = SphinxContent()
+ root_2 = item_cache["/r1"]
+ generate_variants_table(
+ content, {
+ "bla": {
+ "membench": sections_by_uid
+ },
+ "blb": {
+ "membench": sections_by_uid_2
+ }
+ }, root_2, [MembenchVariant("a", "bla"),
+ MembenchVariant("b", "blb")])
+ assert str(content) == """.. raw:: latex
+
+ \\begin{scriptsize}
+
+.. table::
+ :class: longtable
+ :widths: 35,20,9,9,9,9,9
+
+ +-------------------------+---------+-------+---------+-------+------+---------+
+ | Specification | Variant | .text | .rodata | .data | .bss | .noinit |
+ +=========================+=========+=======+=========+=======+======+=========+
+ | :ref:`/t0 <MembenchT0>` | a | 38908 | 0 | 0 | 0 | 0 |
+ + +---------+-------+---------+-------+------+---------+
+ | | b | +0 | +0 | +0 | +0 | +0 |
+ +-------------------------+---------+-------+---------+-------+------+---------+
+ | :ref:`/t1 <MembenchT1>` | a | 38908 | 0 | 0 | 0 | 6400 |
+ + +---------+-------+---------+-------+------+---------+
+ | | b | ? | ? | ? | ? | ? |
+ +-------------------------+---------+-------+---------+-------+------+---------+
+
+.. raw:: latex
+
+ \\end{scriptsize}
"""