Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 79dd3eaa authored by Ruchir Rastogi's avatar Ruchir Rastogi
Browse files

Improve stats_event memory usage

We now truncate the buffer to the appropriate length when clients call
stats_event_build().

Benchmarking tests indicate that truncating the buffer to the
appropriate length increases the cost clients pay to write to the socket
by 2%. This is negligible enough that I decided to truncate the buffer
for both pushed and pulled atoms in order to simplify the API.

Test: m libstatssocket
Test: bit libstatssocket_benchmark:*
Bug: 144126231
Change-Id: I35dec748ff87c0821d0d06779a406997e6e64966
Merged-In: Ife976bb383ecff8de5064730692a95e2a3a82c9d
parent 926fa88c
Loading
Loading
Loading
Loading
+20 −0
Original line number Diff line number Diff line
@@ -47,3 +47,23 @@ cc_library_headers {
    export_include_dirs: ["include"],
    host_supported: true,
}

cc_benchmark {
    name: "libstatssocket_benchmark",
    srcs: [
        "benchmark/main.cpp",
        "benchmark/stats_event_benchmark.cpp",
    ],
    cflags: [
        "-Wall",
        "-Werror",
    ],
    static_libs: [
        "libstatssocket",
    ],
    shared_libs: [
        "libcutils",
        "liblog",
        "libgtest_prod",
    ],
}
+19 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <benchmark/benchmark.h>

BENCHMARK_MAIN();
+53 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2019 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "benchmark/benchmark.h"
#include "stats_event.h"

static struct stats_event* constructStatsEvent() {
    struct stats_event* event = stats_event_obtain();
    stats_event_set_atom_id(event, 100);

    // randomly sample atom size
    for (int i = 0; i < rand() % 800; i++) {
        stats_event_write_int32(event, i);
    }

    return event;
}

static void BM_stats_event_truncate_buffer(benchmark::State& state) {
    while (state.KeepRunning()) {
        struct stats_event* event = constructStatsEvent();
        stats_event_build(event);
        stats_event_write(event);
        stats_event_release(event);
    }
}

BENCHMARK(BM_stats_event_truncate_buffer);

static void BM_stats_event_full_buffer(benchmark::State& state) {
    while (state.KeepRunning()) {
        struct stats_event* event = constructStatsEvent();
        stats_event_truncate_buffer(event, false);
        stats_event_build(event);
        stats_event_write(event);
        stats_event_release(event);
    }
}

BENCHMARK(BM_stats_event_full_buffer);
+3 −0
Original line number Diff line number Diff line
@@ -154,6 +154,9 @@ struct stats_event_api_table {
    uint32_t (*get_errors)(struct stats_event*);
};

// exposed for benchmarking only
void stats_event_truncate_buffer(struct stats_event* event, bool truncate);

#ifdef __cplusplus
}
#endif  // __CPLUSPLUS
+13 −6
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
#include <time.h>
#include "stats_buffer_writer.h"

#define STATS_EVENT_TAG 1937006964
#define LOGGER_ENTRY_MAX_PAYLOAD 4068
// Max payload size is 4 bytes less as 4 bytes are reserved for stats_eventTag.
// See android_util_Stats_Log.cpp
@@ -39,13 +38,13 @@
// The stats_event struct holds the serialized encoding of an event
// within a buf. Also includes other required fields.
struct stats_event {
    uint8_t buf[MAX_EVENT_PAYLOAD];
    uint8_t* buf;
    size_t lastFieldPos;  // location of last field within the buf
    size_t size;          // number of valid bytes within buffer
    uint32_t numElements;
    uint32_t atomId;
    uint32_t errors;
    uint32_t tag;
    bool truncate;
    bool built;
};

@@ -58,12 +57,11 @@ static int64_t get_elapsed_realtime_ns() {

struct stats_event* stats_event_obtain() {
    struct stats_event* event = malloc(sizeof(struct stats_event));

    memset(event->buf, 0, MAX_EVENT_PAYLOAD);
    event->buf = (uint8_t*)calloc(MAX_EVENT_PAYLOAD, 1);
    event->buf[0] = OBJECT_TYPE;
    event->atomId = 0;
    event->errors = 0;
    event->tag = STATS_EVENT_TAG;
    event->truncate = true;  // truncate for both pulled and pushed atoms
    event->built = false;

    // place the timestamp
@@ -79,6 +77,7 @@ struct stats_event* stats_event_obtain() {
}

void stats_event_release(struct stats_event* event) {
    free(event->buf);
    free(event);
}

@@ -297,6 +296,10 @@ uint32_t stats_event_get_errors(struct stats_event* event) {
    return event->errors;
}

void stats_event_truncate_buffer(struct stats_event* event, bool truncate) {
    event->truncate = truncate;
}

void stats_event_build(struct stats_event* event) {
    if (event->built) return;

@@ -317,6 +320,10 @@ void stats_event_build(struct stats_event* event) {
        event->size = POS_FIRST_FIELD + sizeof(uint8_t) + sizeof(uint32_t);
    }

    // Truncate the buffer to the appropriate length in order to limit our
    // memory usage.
    if (event->truncate) event->buf = (uint8_t*)realloc(event->buf, event->size);

    event->built = true;
}