python: Move find from group to AbstractStat
This expands the 'find' feature to be recursive and find all the stats/groups of stats of that regex all the way down the SimStats tree. Change-Id: Id888911a6189e0440d2537f9720aa594353e00c7 Reviewed-on: https://gem5-review.googlesource.com/c/public/gem5/+/63692 Maintainer: Bobby Bruce <bbruce@ucdavis.edu> Reviewed-by: Bobby Bruce <bbruce@ucdavis.edu> Tested-by: kokoro <noreply+kokoro@google.com>
This commit is contained in:
committed by
Bobby Bruce
parent
b65fa9e0d8
commit
905b71c375
@@ -26,6 +26,15 @@
|
||||
|
||||
from .serializable_stat import SerializableStat
|
||||
|
||||
import re
|
||||
from typing import (
|
||||
Callable,
|
||||
List,
|
||||
Optional,
|
||||
Pattern,
|
||||
Union,
|
||||
)
|
||||
|
||||
|
||||
class AbstractStat(SerializableStat):
|
||||
"""
|
||||
@@ -34,4 +43,55 @@ class AbstractStat(SerializableStat):
|
||||
All PyStats are JsonSerializable.
|
||||
"""
|
||||
|
||||
pass
|
||||
def children(
|
||||
self,
|
||||
predicate: Optional[Callable[[str], bool]] = None,
|
||||
recursive: bool = False,
|
||||
) -> List["AbstractStat"]:
|
||||
"""Iterate through all of the children, optionally with a predicate
|
||||
|
||||
```
|
||||
>>> system.children(lambda _name: 'cpu' in name)
|
||||
[cpu0, cpu1, cpu2]
|
||||
```
|
||||
|
||||
:param: predicate(str) -> bool: Optional. Each child's name is passed
|
||||
to this function. If it returns true, then the child is
|
||||
yielded. Otherwise, the child is skipped.
|
||||
If not provided then all children are returned.
|
||||
"""
|
||||
|
||||
to_return = []
|
||||
for attr in self.__dict__:
|
||||
obj = getattr(self, attr)
|
||||
if isinstance(obj, AbstractStat):
|
||||
if (predicate and predicate(attr)) or not predicate:
|
||||
to_return.append(obj)
|
||||
if recursive:
|
||||
to_return = to_return + obj.children(
|
||||
predicate=predicate, recursive=True
|
||||
)
|
||||
|
||||
return to_return
|
||||
|
||||
def find(self, regex: Union[str, Pattern]) -> List["AbstractStat"]:
|
||||
"""Find all stats that match the name, recursively through all the
|
||||
SimStats.
|
||||
|
||||
|
||||
```
|
||||
>>> system.find('cpu[0-9]')
|
||||
[cpu0, cpu1, cpu2]
|
||||
```
|
||||
Note: The above will not match `cpu_other`.
|
||||
|
||||
:param: regex: The regular expression used to search. Can be a
|
||||
precompiled regex or a string in regex format
|
||||
"""
|
||||
if isinstance(regex, str):
|
||||
pattern = re.compile(regex)
|
||||
else:
|
||||
pattern = regex
|
||||
return self.children(
|
||||
lambda _name: re.match(pattern, _name), recursive=True
|
||||
)
|
||||
|
||||
@@ -24,15 +24,11 @@
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import re
|
||||
from typing import (
|
||||
Callable,
|
||||
Dict,
|
||||
Iterator,
|
||||
List,
|
||||
Mapping,
|
||||
Optional,
|
||||
Pattern,
|
||||
Union,
|
||||
)
|
||||
|
||||
@@ -68,87 +64,6 @@ class Group(AbstractStat):
|
||||
for key, value in kwargs.items():
|
||||
setattr(self, key, value)
|
||||
|
||||
def children(
|
||||
self, predicate: Optional[Callable[[str], bool]] = None
|
||||
) -> Iterator[Union["Group", Statistic]]:
|
||||
"""Iterate through all of the children, optionally with a predicate
|
||||
|
||||
```
|
||||
>>> system.children(lambda _name: 'cpu' in name)
|
||||
[cpu0, cpu1, cpu2]
|
||||
```
|
||||
|
||||
:param: predicate(str) -> bool: Optional. Each child's name is passed
|
||||
to this function. If it returns true, then the child is
|
||||
yielded. Otherwise, the child is skipped.
|
||||
If not provided then all children are returned.
|
||||
"""
|
||||
for attr in self.__dict__:
|
||||
# Check the provided predicate. If not a match, skip this child
|
||||
if predicate and not predicate(attr):
|
||||
continue
|
||||
obj = getattr(self, attr)
|
||||
if isinstance(obj, Group) or isinstance(obj, Statistic):
|
||||
yield obj
|
||||
|
||||
def find(self, name: str) -> Iterator[Union["Group", Statistic]]:
|
||||
"""Find all stats that match the name
|
||||
|
||||
This function searches all of the "children" in this group. It yields
|
||||
the set of attributes (children) that have the `name` as a substring.
|
||||
The order of the objects returned by the generator is arbitrary.
|
||||
|
||||
```
|
||||
>>> system.find('cpu')
|
||||
[cpu0, cpu1, cpu2, cpu3, other_cpu, ...]
|
||||
```
|
||||
|
||||
This is useful for performing aggregates over substats. For instance:
|
||||
|
||||
```
|
||||
>>> total_instructions = sum([cpu.exec_context.thread_0.numInsts.value
|
||||
for cpu in simstat.system.find('cpu')])
|
||||
100000
|
||||
```
|
||||
|
||||
:param: name: The name to search for
|
||||
"""
|
||||
yield from self.children(lambda _name: _name in name)
|
||||
|
||||
def find_re(
|
||||
self, regex: Union[str, Pattern]
|
||||
) -> Iterator[Union["Group", Statistic]]:
|
||||
"""Find all stats that match the name
|
||||
|
||||
This function searches all of the "children" in this group. It yields
|
||||
the set of attributes (children) that have the `name` mathing the
|
||||
regex provided. The order of the objects returned by the generator is
|
||||
arbitrary.
|
||||
|
||||
```
|
||||
>>> system.find_re('cpu[0-9]')
|
||||
[cpu0, cpu1, cpu2]
|
||||
```
|
||||
Note: The above will not match `cpu_other`.
|
||||
|
||||
:param: regex: The regular expression used to search. Can be a
|
||||
precompiled regex or a string in regex format
|
||||
"""
|
||||
if isinstance(regex, str):
|
||||
pattern = re.compile(regex)
|
||||
else:
|
||||
pattern = regex
|
||||
yield from self.children(lambda _name: bool(pattern.search(_name)))
|
||||
|
||||
def _repr_name(self) -> str:
|
||||
return "Group"
|
||||
|
||||
def __repr__(self) -> str:
|
||||
stats_list = []
|
||||
for key in self.__dict__:
|
||||
stats_list.append(key)
|
||||
return f"{self._repr_name()}: {stats_list}"
|
||||
|
||||
|
||||
class Vector(Group):
|
||||
"""
|
||||
|
||||
Reference in New Issue
Block a user