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

Commit 62863551 authored by Vishnu Nair's avatar Vishnu Nair
Browse files

SF: Store transaction traces as a serialized blob

Reduce memory usage for transaction traces by storing
the data after serialization since this will pack the
messages tightly.

Test: presubmit
Test: awk '/Private_Dirty:/{ sum += $2 } END { print sum }' /proc/`pidof surfaceflinger`/smaps
Bug: 200284593
Fixes: 210078963
Change-Id: I6d6324264b112a08225bb4335b27fd19dd832d08
parent 7eaec5d5
Loading
Loading
Loading
Loading
+20 −14
Original line number Diff line number Diff line
@@ -37,22 +37,21 @@ public:
    size_t used() const { return mUsedInBytes; }
    size_t frameCount() const { return mStorage.size(); }
    void setSize(size_t newSize) { mSizeInBytes = newSize; }
    EntryProto& front() { return mStorage.front(); }
    const EntryProto& front() const { return mStorage.front(); }
    const EntryProto& back() const { return mStorage.back(); }
    const std::string& front() const { return mStorage.front(); }
    const std::string& back() const { return mStorage.back(); }

    void reset() {
        // use the swap trick to make sure memory is released
        std::deque<EntryProto>().swap(mStorage);
        std::deque<std::string>().swap(mStorage);
        mUsedInBytes = 0U;
    }

    void writeToProto(FileProto& fileProto) {
        fileProto.mutable_entry()->Reserve(static_cast<int>(mStorage.size()) +
                                           fileProto.entry().size());
        for (const EntryProto& entry : mStorage) {
        for (const std::string& entry : mStorage) {
            EntryProto* entryProto = fileProto.add_entry();
            *entryProto = entry;
            entryProto->ParseFromString(entry);
        }
    }

@@ -74,28 +73,35 @@ public:
        return NO_ERROR;
    }

    std::vector<EntryProto> emplace(EntryProto&& proto) {
        std::vector<EntryProto> replacedEntries;
        size_t protoSize = static_cast<size_t>(proto.ByteSize());
    std::vector<std::string> emplace(std::string&& serializedProto) {
        std::vector<std::string> replacedEntries;
        size_t protoSize = static_cast<size_t>(serializedProto.size());
        while (mUsedInBytes + protoSize > mSizeInBytes) {
            if (mStorage.empty()) {
                return {};
            }
            mUsedInBytes -= static_cast<size_t>(mStorage.front().ByteSize());
            mUsedInBytes -= static_cast<size_t>(mStorage.front().size());
            replacedEntries.emplace_back(mStorage.front());
            mStorage.pop_front();
        }
        mUsedInBytes += protoSize;
        mStorage.emplace_back();
        mStorage.back().Swap(&proto);
        mStorage.emplace_back(serializedProto);
        return replacedEntries;
    }

    std::vector<std::string> emplace(EntryProto&& proto) {
        std::string serializedProto;
        proto.SerializeToString(&serializedProto);
        return emplace(std::move(serializedProto));
    }

    void dump(std::string& result) const {
        std::chrono::milliseconds duration(0);
        if (frameCount() > 0) {
            EntryProto entry;
            entry.ParseFromString(mStorage.front());
            duration = std::chrono::duration_cast<std::chrono::milliseconds>(
                    std::chrono::nanoseconds(systemTime() - front().elapsed_realtime_nanos()));
                    std::chrono::nanoseconds(systemTime() - entry.elapsed_realtime_nanos()));
        }
        const int64_t durationCount = duration.count();
        base::StringAppendF(&result,
@@ -107,7 +113,7 @@ public:
private:
    size_t mUsedInBytes = 0U;
    size_t mSizeInBytes = 0U;
    std::deque<EntryProto> mStorage;
    std::deque<std::string> mStorage;
};

} // namespace android
+18 −6
Original line number Diff line number Diff line
@@ -177,9 +177,9 @@ void TransactionTracing::addEntry(const std::vector<CommittedTransactions>& comm
                                  const std::vector<int32_t>& removedLayers) {
    ATRACE_CALL();
    std::scoped_lock lock(mTraceLock);
    std::vector<proto::TransactionTraceEntry> removedEntries;
    for (const CommittedTransactions& entry : committedTransactions) {
    std::vector<std::string> removedEntries;
    proto::TransactionTraceEntry entryProto;
    for (const CommittedTransactions& entry : committedTransactions) {
        entryProto.set_elapsed_realtime_nanos(entry.timestamp);
        entryProto.set_vsync_id(entry.vsyncId);
        entryProto.mutable_added_layers()->Reserve(static_cast<int32_t>(mCreatedLayers.size()));
@@ -202,13 +202,21 @@ void TransactionTracing::addEntry(const std::vector<CommittedTransactions>& comm
                ALOGW("Could not find transaction id %" PRIu64, id);
            }
        }
        std::vector<proto::TransactionTraceEntry> entries = mBuffer->emplace(std::move(entryProto));

        std::string serializedProto;
        entryProto.SerializeToString(&serializedProto);
        entryProto.Clear();
        std::vector<std::string> entries = mBuffer->emplace(std::move(serializedProto));
        removedEntries.reserve(removedEntries.size() + entries.size());
        removedEntries.insert(removedEntries.end(), std::make_move_iterator(entries.begin()),
                              std::make_move_iterator(entries.end()));
    }

    for (const proto::TransactionTraceEntry& removedEntry : removedEntries) {
        updateStartingStateLocked(removedEntry);
    proto::TransactionTraceEntry removedEntryProto;
    for (const std::string& removedEntry : removedEntries) {
        removedEntryProto.ParseFromString(removedEntry);
        updateStartingStateLocked(removedEntryProto);
        removedEntryProto.Clear();
    }
    mTransactionsAddedToBufferCv.notify_one();
}
@@ -220,7 +228,11 @@ void TransactionTracing::flush(int64_t vsyncId) {
    std::unique_lock<std::mutex> lock(mTraceLock);
    base::ScopedLockAssertion assumeLocked(mTraceLock);
    mTransactionsAddedToBufferCv.wait(lock, [&]() REQUIRES(mTraceLock) {
        return mBuffer->used() > 0 && mBuffer->back().vsync_id() >= vsyncId;
        proto::TransactionTraceEntry entry;
        if (mBuffer->used() > 0) {
            entry.ParseFromString(mBuffer->back());
        }
        return mBuffer->used() > 0 && entry.vsync_id() >= vsyncId;
    });
}

+3 −1
Original line number Diff line number Diff line
@@ -56,7 +56,9 @@ protected:

    auto bufferFront() {
        std::scoped_lock<std::mutex> lock(mTracing->mTraceLock);
        return mTracing->mBuffer->front();
        proto::TransactionTraceEntry entry;
        entry.ParseFromString(mTracing->mBuffer->front());
        return entry;
    }

    bool threadIsJoinable() {