Skip to content

recordHandledException() causes high CPU load and takes ~300ms to complete #546

@lengfeld

Description

@lengfeld

tl;dr

We have seen that Countly.sharedInstance().crashes().recordHandledException(Exception exception) blocks for ~300ms (tested on a Google emulator) and causes high CPU load in the installd process.

Can you add an API to disable/overwrite the getDiskSpaces e.g. by overwriting MetricProvider in CountlyConfig?

Tested setup

Countly sdk and test app version: commit b8c5ddc and version 18.01-2460-gb8c5ddc2 (from git describe)

Emulator was Android 16.0 x86_64 with Play Services from Google: Medium Phone API 36.0

Added the lines

    val x = Exception("test")
    Countly.sharedInstance().crashes().recordHandledException(x)

in the file app-kotlin/src/main/java/ly/count/android/demo/kotlin/MainActivity.kt.

Observation

When the app is launched, you see the following traces in perfetto

Image
  • The demo app is making a binder call to system_server and blocks. Here on the main_thread
  • The system_server is making a binder call to the installd process.
  • The installd process does some CPU/IO for 300ms to compute the disk usage.

SDK Code

The disk usage is queried in the function getDiskSpaces(). The code is

                public Map.Entry<String, String> getDiskSpaces(Context context) {
                    long totalBytes = 0;
                    long usedBytes = 0;

                    StorageManager sm = (StorageManager) context.getSystemService(Context.STORAGE_SERVICE);
                    if (sm != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                        try {
                            for (android.os.storage.StorageVolume sv : sm.getStorageVolumes()) {
                                if (sv.isPrimary()) {
                                    StorageStatsManager stm = (StorageStatsManager) context.getSystemService(Context.STORAGE_STATS_SERVICE);
                                    totalBytes += stm.getTotalBytes(StorageManager.UUID_DEFAULT);
                                    usedBytes += stm.getTotalBytes(StorageManager.UUID_DEFAULT) - stm.getFreeBytes(StorageManager.UUID_DEFAULT);
                                }
                            }
                        } catch (Exception e) {
                            Countly.sharedInstance().L.w("[DeviceInfo] getDiskSpaces, Got exception while trying to get all volumes storage", e);
                        }

The Android docu for getTotalBytes says:

This method may take several seconds to complete, so it should only be called from a worker thread.

Our Need

We would like to avoid the CPU/IO load on our device. Especially because we sometimes log multiple errors per second.

In the file CountlyConfig there is already some methods to overwrite some of the metrics. E.g. setMetricOverride(). But no method to overwrite MetricProvider. Can this be added? Or another API introduced to control whether and how the disk usage is queried?

Thanks for looking into this.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions