Simulate runtime metrics as though running tasks one at a time in order. These diagnostics can help reveal behaviors of and issues with ``order``. Returns a dict of `namedtuple("OrderInfo")` and a list of the number of outputs held over time. OrderInfo fields: - order : the order
(
dsk: MutableMapping[Key, Any],
o: Mapping[Key, int] | None = None,
dependencies: MutableMapping[Key, set[Key]] | None = None,
)
| 764 | |
| 765 | |
| 766 | def diagnostics( |
| 767 | dsk: MutableMapping[Key, Any], |
| 768 | o: Mapping[Key, int] | None = None, |
| 769 | dependencies: MutableMapping[Key, set[Key]] | None = None, |
| 770 | ) -> tuple[dict[Key, OrderInfo], list[int]]: |
| 771 | """Simulate runtime metrics as though running tasks one at a time in order. |
| 772 | |
| 773 | These diagnostics can help reveal behaviors of and issues with ``order``. |
| 774 | |
| 775 | Returns a dict of `namedtuple("OrderInfo")` and a list of the number of outputs held over time. |
| 776 | |
| 777 | OrderInfo fields: |
| 778 | - order : the order in which the node is run. |
| 779 | - age : how long the output of a node is held. |
| 780 | - num_data_when_run : the number of outputs held in memory when a node is run. |
| 781 | - num_data_when_released : the number of outputs held in memory when the output is released. |
| 782 | - num_dependencies_freed : the number of dependencies freed by running the node. |
| 783 | """ |
| 784 | if dependencies is None: |
| 785 | dependencies, dependents = get_deps(dsk) |
| 786 | else: |
| 787 | dependents = reverse_dict(dependencies) |
| 788 | assert dependencies is not None |
| 789 | if o is None: |
| 790 | o = order(dsk, dependencies=dependencies, return_stats=False) |
| 791 | |
| 792 | pressure = [] |
| 793 | num_in_memory = 0 |
| 794 | age = {} |
| 795 | runpressure = {} |
| 796 | releasepressure = {} |
| 797 | freed = {} |
| 798 | num_needed = {key: len(val) for key, val in dependents.items()} |
| 799 | for i, key in enumerate(sorted(dsk, key=o.__getitem__)): |
| 800 | pressure.append(num_in_memory) |
| 801 | runpressure[key] = num_in_memory |
| 802 | released = 0 |
| 803 | for dep in dependencies[key]: |
| 804 | num_needed[dep] -= 1 |
| 805 | if num_needed[dep] == 0: |
| 806 | age[dep] = i - o[dep] |
| 807 | releasepressure[dep] = num_in_memory |
| 808 | released += 1 |
| 809 | freed[key] = released |
| 810 | if dependents[key]: |
| 811 | num_in_memory -= released - 1 |
| 812 | else: |
| 813 | age[key] = 0 |
| 814 | releasepressure[key] = num_in_memory |
| 815 | num_in_memory -= released |
| 816 | |
| 817 | rv = { |
| 818 | key: OrderInfo( |
| 819 | val, age[key], runpressure[key], releasepressure[key], freed[key] |
| 820 | ) |
| 821 | for key, val in o.items() |
| 822 | } |
| 823 | return rv, pressure |
searching dependent graphs…