Skip to content

Commit

Permalink
Cache additional methods in MetricLookup / SemanticModelLookup (#…
Browse files Browse the repository at this point in the history
…1438)

Similar to the previous PRs, this PR caches a few additional methods. I
did a little bit of memory profiling using a large manifest, and total
memory allocation did not change significantly. I believe this is
because these additional caches reference objects that are already
stored in `ValidLinkableSpecResolver` or the cached objects have low
overhead.
  • Loading branch information
plypaul authored Oct 2, 2024
1 parent 975446b commit 2ee4e79
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,14 @@ def __init__(
max_entity_links=MAX_JOIN_HOPS,
)

# Cache for `get_min_queryable_time_granularity()`
self._metric_reference_to_min_metric_time_grain: Dict[MetricReference, TimeGranularity] = {}

# Cache for `get_valid_agg_time_dimensions_for_metric()`.
self._metric_reference_to_valid_agg_time_dimension_specs: Dict[
MetricReference, Sequence[TimeDimensionSpec]
] = {}

@functools.lru_cache
def linkable_elements_for_measure(
self,
Expand Down Expand Up @@ -183,6 +191,18 @@ def get_valid_agg_time_dimensions_for_metric(
self, metric_reference: MetricReference
) -> Sequence[TimeDimensionSpec]:
"""Get the agg time dimension specs that can be used in place of metric time for this metric, if applicable."""
result = self._metric_reference_to_valid_agg_time_dimension_specs.get(metric_reference)
if result is not None:
return result

result = self._get_valid_agg_time_dimensions_for_metric(metric_reference)
self._metric_reference_to_valid_agg_time_dimension_specs[metric_reference] = result

return result

def _get_valid_agg_time_dimensions_for_metric(
self, metric_reference: MetricReference
) -> Sequence[TimeDimensionSpec]:
agg_time_dimension_specs = self._get_agg_time_dimension_specs_for_metric(metric_reference)
distinct_agg_time_dimension_identifiers = set(
[(spec.reference, spec.entity_links) for spec in agg_time_dimension_specs]
Expand All @@ -204,6 +224,15 @@ def get_min_queryable_time_granularity(self, metric_reference: MetricReference)
Maps to the largest granularity defined for any of the metric's agg_time_dimensions.
"""
result = self._metric_reference_to_min_metric_time_grain.get(metric_reference)
if result is not None:
return result

result = self._get_min_queryable_time_granularity(metric_reference)
self._metric_reference_to_min_metric_time_grain[metric_reference] = result
return result

def _get_min_queryable_time_granularity(self, metric_reference: MetricReference) -> TimeGranularity:
agg_time_dimension_specs = self._get_agg_time_dimension_specs_for_metric(metric_reference)
assert (
agg_time_dimension_specs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,9 @@ def __init__(self, model: SemanticManifest, custom_granularities: Dict[str, Expa
# Cache for defined time granularity.
self._time_dimension_to_defined_time_granularity: Dict[TimeDimensionReference, TimeGranularity] = {}

# Cache for agg. time dimension for measure.
self._measure_reference_to_agg_time_dimension_specs: Dict[MeasureReference, Sequence[TimeDimensionSpec]] = {}

def get_dimension_references(self) -> Sequence[DimensionReference]:
"""Retrieve all dimension references from the collection of semantic models."""
return tuple(self._dimension_index.keys())
Expand Down Expand Up @@ -364,6 +367,17 @@ def get_agg_time_dimension_specs_for_measure(
self, measure_reference: MeasureReference
) -> Sequence[TimeDimensionSpec]:
"""Get the agg time dimension specs that can be used in place of metric time for this measure."""
result = self._measure_reference_to_agg_time_dimension_specs.get(measure_reference)
if result is not None:
return result

result = self._get_agg_time_dimension_specs_for_measure(measure_reference)
self._measure_reference_to_agg_time_dimension_specs[measure_reference] = result
return result

def _get_agg_time_dimension_specs_for_measure(
self, measure_reference: MeasureReference
) -> Sequence[TimeDimensionSpec]:
agg_time_dimension = self.get_agg_time_dimension_for_measure(measure_reference)
# A measure's agg_time_dimension is required to be in the same semantic model as the measure,
# so we can assume the same semantic model for both measure and dimension.
Expand Down

0 comments on commit 2ee4e79

Please sign in to comment.