diff --git a/flow/raster_cache.cc b/flow/raster_cache.cc index 1927321a032386be26dee9c2179a1c3a21ffc922..9f10e47de250c64a4b602b6682ee8d81115286c5 100644 --- a/flow/raster_cache.cc +++ b/flow/raster_cache.cc @@ -97,6 +97,7 @@ static RasterCacheResult Rasterize( bool checkerboard, const SkRect& logical_rect, std::function draw_function) { + TRACE_EVENT0("flutter", "RasterCachePopulate"); SkIRect cache_rect = RasterCache::GetDeviceBounds(logical_rect, ctm); const SkImageInfo image_info = SkImageInfo::MakeN32Premul( @@ -129,8 +130,6 @@ RasterCacheResult RasterizePicture(SkPicture* picture, const SkMatrix& ctm, SkColorSpace* dst_color_space, bool checkerboard) { - TRACE_EVENT0("flutter", "RasterCachePopulate"); - return Rasterize(context, ctm, dst_color_space, checkerboard, picture->cullRect(), [=](SkCanvas* canvas) { canvas->drawPicture(picture); }); @@ -240,6 +239,7 @@ void RasterCache::SweepAfterFrame() { SweepOneCacheAfterFrame(picture_cache_); SweepOneCacheAfterFrame(layer_cache_); picture_cached_this_frame_ = 0; + TraceStatsToTimeline(); } void RasterCache::Clear() { @@ -259,4 +259,35 @@ void RasterCache::SetCheckboardCacheImages(bool checkerboard) { Clear(); } +void RasterCache::TraceStatsToTimeline() const { +#if FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE + + size_t layer_cache_count = 0; + size_t layer_cache_bytes = 0; + size_t picture_cache_count = 0; + size_t picture_cache_bytes = 0; + + for (const auto& item : layer_cache_) { + const auto dimensions = item.second.image.image_dimensions(); + layer_cache_count++; + layer_cache_bytes += dimensions.width() * dimensions.height() * 4; + } + + for (const auto& item : picture_cache_) { + const auto dimensions = item.second.image.image_dimensions(); + picture_cache_count++; + picture_cache_bytes += dimensions.width() * dimensions.height() * 4; + } + + FML_TRACE_COUNTER("flutter", "RasterCache", + reinterpret_cast(this), // + "LayerCount", layer_cache_count, // + "LayerMBytes", layer_cache_bytes * 1e-6, // + "PictureCount", picture_cache_count, // + "PictureMBytes", picture_cache_bytes * 1e-6 // + ); + +#endif // FLUTTER_RUNTIME_MODE != FLUTTER_RUNTIME_MODE_RELEASE +} + } // namespace flow diff --git a/flow/raster_cache.h b/flow/raster_cache.h index 74ce010b07c8c115c1a8efca94988615a048219e..f0382c9c928727688692762e591b49f6e546827f 100644 --- a/flow/raster_cache.h +++ b/flow/raster_cache.h @@ -33,6 +33,10 @@ class RasterCacheResult { void draw(SkCanvas& canvas, const SkPaint* paint = nullptr) const; + SkISize image_dimensions() const { + return image_ ? image_->dimensions() : SkISize::Make(0, 0); + }; + private: sk_sp image_; SkRect logical_rect_; @@ -87,6 +91,7 @@ class RasterCache { void Prepare(PrerollContext* context, Layer* layer, const SkMatrix& ctm); RasterCacheResult Get(const SkPicture& picture, const SkMatrix& ctm) const; + RasterCacheResult Get(Layer* layer, const SkMatrix& ctm) const; void SweepAfterFrame(); @@ -127,6 +132,8 @@ class RasterCache { bool checkerboard_images_; fml::WeakPtrFactory weak_factory_; + void TraceStatsToTimeline() const; + FML_DISALLOW_COPY_AND_ASSIGN(RasterCache); }; diff --git a/fml/trace_event.cc b/fml/trace_event.cc index 69ed8b2216486ba5ed41426cd310f46262988d3e..86ba90dd423cef7976f4e0c28d92bcf9ed759732 100644 --- a/fml/trace_event.cc +++ b/fml/trace_event.cc @@ -4,22 +4,34 @@ #include "flutter/fml/trace_event.h" -#include "third_party/dart/runtime/include/dart_tools_api.h" +#include "flutter/fml/logging.h" namespace fml { namespace tracing { -void TraceCounter(TraceArg category_group, TraceArg name, TraceIDArg count) { - auto count_string = std::to_string(count); - const char* arg_names[] = {name}; - const char* arg_values[] = {count_string.c_str()}; - Dart_TimelineEvent(name, // label - Dart_TimelineGetMicros(), // timestamp0 - 0, // timestamp1_or_async_id - Dart_Timeline_Event_Counter, // event type - 1, // argument_count - arg_names, // argument_names - arg_values // argument_values +void TraceTimelineEvent(TraceArg category_group, + TraceArg name, + TraceIDArg identifier, + Dart_Timeline_Event_Type type, + const std::vector& names, + const std::vector& values) { + const auto argument_count = std::min(names.size(), values.size()); + + std::vector c_values; + c_values.resize(argument_count, nullptr); + + for (size_t i = 0; i < argument_count; i++) { + c_values[i] = values[i].c_str(); + } + + Dart_TimelineEvent( + name, // label + Dart_TimelineGetMicros(), // timestamp0 + identifier, // timestamp1_or_async_id + type, // event type + argument_count, // argument_count + const_cast(names.data()), // argument_names + const_cast(c_values.data()) // argument_values ); } diff --git a/fml/trace_event.h b/fml/trace_event.h index b3bba9b281f612229e09f3f5fb27093daf6cd9ed..c61fbc1efa3646d6fb8dbbf9c5e7094e956b2099 100644 --- a/fml/trace_event.h +++ b/fml/trace_event.h @@ -13,8 +13,6 @@ #include -#define FML_TRACE_COUNTER(category_group, name, count) \ - TRACE_COUNTER(category_group, name, 0u, name, count) #define TRACE_EVENT0(a, b) TRACE_DURATION(a, b) #define TRACE_EVENT1(a, b, c, d) TRACE_DURATION(a, b, c, d) #define TRACE_EVENT2(a, b, c, d, e, f) TRACE_DURATION(a, b, c, d, e, f) @@ -28,8 +26,11 @@ #include #include #include +#include +#include #include "flutter/fml/macros.h" +#include "third_party/dart/runtime/include/dart_tools_api.h" #if !defined(OS_FUCHSIA) @@ -45,8 +46,8 @@ // from trace/event.h on Fuchsia. // // TODO(chinmaygarde): All macros here should have the FML prefix. -#define FML_TRACE_COUNTER(category_group, name, count) \ - ::fml::tracing::TraceCounter(category_group, name, count); +#define FML_TRACE_COUNTER(category_group, name, counter_id, arg1, args...) \ + ::fml::tracing::TraceCounter(category_group, name, counter_id, arg1, ##args); #define TRACE_EVENT0(category_group, name) \ ::fml::tracing::TraceEvent0(category_group, name); \ @@ -99,7 +100,63 @@ namespace tracing { using TraceArg = const char*; using TraceIDArg = int64_t; -void TraceCounter(TraceArg category_group, TraceArg name, TraceIDArg count); +void TraceTimelineEvent(TraceArg category_group, + TraceArg name, + TraceIDArg id, + Dart_Timeline_Event_Type type, + const std::vector& names, + const std::vector& values); + +inline std::string TraceToString(const char* string) { + return std::string{string}; +} + +inline std::string TraceToString(std::string string) { + return string; +} + +template ::value>> +std::string TraceToString(T string) { + return std::to_string(string); +} + +inline void SplitArgumentsCollect(std::vector& keys, + std::vector& values) {} + +template +void SplitArgumentsCollect(std::vector& keys, + std::vector& values, + Key key, + Value value, + Args... args) { + keys.emplace_back(key); + values.emplace_back(TraceToString(value)); + SplitArgumentsCollect(keys, values, args...); +} + +inline std::pair, std::vector> +SplitArguments() { + return {}; +} + +template +std::pair, std::vector> +SplitArguments(Key key, Value value, Args... args) { + std::vector keys; + std::vector values; + SplitArgumentsCollect(keys, values, key, value, args...); + return std::make_pair(std::move(keys), std::move(values)); +} + +template +void TraceCounter(TraceArg category, + TraceArg name, + TraceIDArg identifier, + Args... args) { + auto split = SplitArguments(args...); + TraceTimelineEvent(category, name, identifier, Dart_Timeline_Event_Counter, + split.first, split.second); +} void TraceEvent0(TraceArg category_group, TraceArg name);