Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Exemplars pre-allocates memory even when exemplars are not used #5581

Open
Tracked by #21121
asafm opened this issue Jun 29, 2023 · 3 comments
Open
Tracked by #21121

Exemplars pre-allocates memory even when exemplars are not used #5581

asafm opened this issue Jun 29, 2023 · 3 comments
Labels
Feature Request Suggest an idea for this project

Comments

@asafm
Copy link
Contributor

asafm commented Jun 29, 2023

Is your feature request related to a problem? Please describe.

When you create a SdkMeterProviderBuilder and specify an ExemplarFilter, which is off, you would expect there won't be any memory allocations made since exemplars are not being collected in effect.

SdkMeterProviderUtil.setExemplarFilter(builder, ExemplarFilter.alwaysOff());

It happens in multiple locations, where an aggregator is created with an exemplar reservoir. In all places, it is wrapped with a filtered reservoir, but it's created either way without considering the filter might be off.

Example:

                ExemplarReservoir.filtered(
                    exemplarFilter,
                    ExemplarReservoir.doubleFixedSizeReservoir(
                        Clock.getDefault(),
                        Runtime.getRuntime().availableProcessors(),
                        RandomSupplier.platformDefault())),
            maxBuckets,
            maxScale);

For a single aggregator with 100k attributes, it's 70 MB of memory not needed.

Describe the solution you'd like

Since the filter is not an enum, there's no way to know from it whether it's off or not.
Also, some filters might not introduce any sampling for certain attributes but are not declared as off.

I suggest changing the argument of ExemplarReservoir<T> original in ExemplarReservoir.filtered() , to a function providing that (Supplier<ExemplarReservoir<T>>). FilteredExemplarReservoir methods would ensure private ExemplarReservoir<T> reservoir; is initialized before use. Initialization would be done using the supplier.
Lazy init.

Describe alternatives you've considered
None at the moment

Additional context
None at the moment

@asafm asafm added the Feature Request Suggest an idea for this project label Jun 29, 2023
@asafm asafm changed the title Exemplas pre-allocates memory even when exemplars are not used Exemplars pre-allocates memory even when exemplars are not used Jun 29, 2023
@jack-berg
Copy link
Member

Nice find. I wonder if we can lazily initialize somewhere deeper down in the reservoir itself to keep the code flow the same. Something like this this: 823e46c

@asafm
Copy link
Contributor Author

asafm commented Jul 2, 2023

I believe so.
For FixedSizeExemplarReservoir, we can start with null value for ReservoirCell[] storage;
In offerLongMeasurement and offerDoubleMeasurement, I'll call ensureInitialized(), which will check if null, and if so, init the array as the c'tor does:

    this.storage = new ReservoirCell[size];
    for (int i = 0; i < size; ++i) {
      this.storage[i] = new ReservoirCell(clock);
    }

I thought of lazy init easy item in the array, but the selector gets access to the array in full, so there is not interface to hide behind.

WDYT

@jack-berg
Copy link
Member

I thought of lazy init easy item in the array, but the selector gets access to the array in full,

The selector? In the commit I posted above the code that iterates over the array is made to handle nullable array entries.

But I'm also fine with initializing ReservoirCell[] storage to null. Achieves the same affect and may be a bit simpler.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Feature Request Suggest an idea for this project
Projects
None yet
Development

No branches or pull requests

2 participants