diff options
| -rw-r--r-- | services/surfaceflinger/SurfaceTracing.cpp | 78 | ||||
| -rw-r--r-- | services/surfaceflinger/SurfaceTracing.h | 34 |
2 files changed, 79 insertions, 33 deletions
diff --git a/services/surfaceflinger/SurfaceTracing.cpp b/services/surfaceflinger/SurfaceTracing.cpp index 67dcd06187..1835929940 100644 --- a/services/surfaceflinger/SurfaceTracing.cpp +++ b/services/surfaceflinger/SurfaceTracing.cpp @@ -26,22 +26,48 @@ namespace android { -void SurfaceTracing::enable() { - ATRACE_CALL(); +void SurfaceTracing::LayersTraceBuffer::reset(size_t newSize) { + // use the swap trick to make sure memory is released + std::queue<LayersTraceProto>().swap(mStorage); + mSizeInBytes = newSize; + mUsedInBytes = 0U; +} + +void SurfaceTracing::LayersTraceBuffer::emplace(LayersTraceProto&& proto) { + auto protoSize = proto.ByteSize(); + while (mUsedInBytes + protoSize > mSizeInBytes) { + if (mStorage.empty()) { + return; + } + mUsedInBytes -= mStorage.front().ByteSize(); + mStorage.pop(); + } + mUsedInBytes += protoSize; + mStorage.emplace(); + mStorage.back().Swap(&proto); +} + +void SurfaceTracing::LayersTraceBuffer::flush(LayersTraceFileProto* fileProto) { + fileProto->mutable_entry()->Reserve(mStorage.size()); + + while (!mStorage.empty()) { + auto entry = fileProto->add_entry(); + entry->Swap(&mStorage.front()); + mStorage.pop(); + } +} + +void SurfaceTracing::enable(size_t bufferSizeInByte) { std::lock_guard<std::mutex> protoGuard(mTraceMutex); if (mEnabled) { return; } mEnabled = true; - - mTrace = std::make_unique<LayersTraceFileProto>(); - mTrace->set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 | - LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L); + mBuffer.reset(bufferSizeInByte); } status_t SurfaceTracing::disable() { - ATRACE_CALL(); std::lock_guard<std::mutex> protoGuard(mTraceMutex); if (!mEnabled) { @@ -51,7 +77,7 @@ status_t SurfaceTracing::disable() { status_t err(writeProtoFileLocked()); ALOGE_IF(err == PERMISSION_DENIED, "Could not save the proto file! Permission denied"); ALOGE_IF(err == NOT_ENOUGH_DATA, "Could not save the proto file! There are missing fields"); - mTrace.reset(); + mBuffer.reset(0); return err; } @@ -65,32 +91,29 @@ void SurfaceTracing::traceLayers(const char* where, LayersProto layers) { if (!mEnabled) { return; } - LayersTraceProto* entry = mTrace->add_entry(); - entry->set_elapsed_realtime_nanos(elapsedRealtimeNano()); - entry->set_where(where); - entry->mutable_layers()->Swap(&layers); - - constexpr int maxBufferedEntryCount = 3600; - if (mTrace->entry_size() >= maxBufferedEntryCount) { - // TODO: flush buffered entries without disabling tracing - ALOGE("too many buffered frames; force disable tracing"); - mEnabled = false; - writeProtoFileLocked(); - mTrace.reset(); - } + + LayersTraceProto entry; + entry.set_elapsed_realtime_nanos(elapsedRealtimeNano()); + entry.set_where(where); + entry.mutable_layers()->Swap(&layers); + + mBuffer.emplace(std::move(entry)); } status_t SurfaceTracing::writeProtoFileLocked() { ATRACE_CALL(); - if (!mTrace->IsInitialized()) { - return NOT_ENOUGH_DATA; - } + LayersTraceFileProto fileProto; std::string output; - if (!mTrace->SerializeToString(&output)) { + + fileProto.set_magic_number(uint64_t(LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_H) << 32 | + LayersTraceFileProto_MagicNumber_MAGIC_NUMBER_L); + mBuffer.flush(&fileProto); + + if (!fileProto.SerializeToString(&output)) { return PERMISSION_DENIED; } - if (!android::base::WriteStringToFile(output, mOutputFileName, true)) { + if (!android::base::WriteStringToFile(output, kDefaultFileName, true)) { return PERMISSION_DENIED; } @@ -101,7 +124,8 @@ void SurfaceTracing::dump(String8& result) const { std::lock_guard<std::mutex> protoGuard(mTraceMutex); result.appendFormat("Tracing state: %s\n", mEnabled ? "enabled" : "disabled"); - result.appendFormat(" number of entries: %d\n", mTrace ? mTrace->entry_size() : 0); + result.appendFormat(" number of entries: %zu (%.2fMB / %.2fMB)\n", mBuffer.frameCount(), + float(mBuffer.used()) / float(1_MB), float(mBuffer.size()) / float(1_MB)); } } // namespace android diff --git a/services/surfaceflinger/SurfaceTracing.h b/services/surfaceflinger/SurfaceTracing.h index fd8cb82a9b..ec01be7170 100644 --- a/services/surfaceflinger/SurfaceTracing.h +++ b/services/surfaceflinger/SurfaceTracing.h @@ -22,32 +22,54 @@ #include <memory> #include <mutex> +#include <queue> using namespace android::surfaceflinger; namespace android { +constexpr auto operator""_MB(unsigned long long const num) { + return num * 1024 * 1024; +} + /* * SurfaceTracing records layer states during surface flinging. */ class SurfaceTracing { public: - void enable(); + void enable() { enable(kDefaultBufferCapInByte); } + void enable(size_t bufferSizeInByte); status_t disable(); - bool isEnabled() const; - void traceLayers(const char* where, LayersProto); + + bool isEnabled() const; void dump(String8& result) const; private: - static constexpr auto DEFAULT_FILENAME = "/data/misc/wmtrace/layers_trace.pb"; + static constexpr auto kDefaultBufferCapInByte = 100_MB; + static constexpr auto kDefaultFileName = "/data/misc/wmtrace/layers_trace.pb"; + + class LayersTraceBuffer { // ring buffer + public: + size_t size() const { return mSizeInBytes; } + size_t used() const { return mUsedInBytes; } + size_t frameCount() const { return mStorage.size(); } + + void reset(size_t newSize); + void emplace(LayersTraceProto&& proto); + void flush(LayersTraceFileProto* fileProto); + + private: + size_t mUsedInBytes = 0U; + size_t mSizeInBytes = 0U; + std::queue<LayersTraceProto> mStorage; + }; status_t writeProtoFileLocked(); bool mEnabled = false; - std::string mOutputFileName = DEFAULT_FILENAME; mutable std::mutex mTraceMutex; - std::unique_ptr<LayersTraceFileProto> mTrace; + LayersTraceBuffer mBuffer; }; } // namespace android |