yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
canvas_performance_integration.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <chrono>
5#include <iomanip>
6#include <sstream>
7
10#include "imgui/imgui.h"
11#include "util/log.h"
12
13namespace yaze {
14namespace gui {
15
16void CanvasPerformanceIntegration::Initialize(const std::string& canvas_id) {
17 canvas_id_ = canvas_id;
20
21 // Initialize performance profiler integration
23
24 LOG_DEBUG("CanvasPerformance",
25 "Initialized performance integration for canvas: %s",
26 canvas_id_.c_str());
27}
28
31 return;
32
33 // Start frame timer
36 std::make_unique<gfx::ScopedTimer>("canvas_frame_" + canvas_id_);
37
38 LOG_DEBUG("CanvasPerformance",
39 "Started performance monitoring for canvas: %s",
40 canvas_id_.c_str());
41}
42
44 // Release timers in reverse order of creation to ensure clean shutdown
46 modal_timer_.reset();
47 modal_timer_active_ = false;
48 }
50 interaction_timer_.reset();
52 }
54 draw_timer_.reset();
55 draw_timer_active_ = false;
56 }
58 frame_timer_.reset();
59 frame_timer_active_ = false;
60 }
61
62 LOG_DEBUG("CanvasPerformance",
63 "Stopped performance monitoring for canvas: %s",
64 canvas_id_.c_str());
65}
66
69 return;
70
71 // Update frame time
73
74 // Update draw time
76
77 // Update interaction time
79
80 // Update modal time
82
83 // Calculate cache hit ratio
85
86 // Save current metrics periodically
87 static auto last_save = std::chrono::steady_clock::now();
88 auto now = std::chrono::steady_clock::now();
89 if (std::chrono::duration_cast<std::chrono::seconds>(now - last_save)
90 .count() >= 5) {
92 last_save = now;
93 }
94}
95
97 const std::string& operation_name, double time_ms, CanvasUsage usage_mode) {
99 return;
100
101 // Update operation counts based on usage mode
102 switch (usage_mode) {
105 break;
108 break;
111 break;
114 break;
117 break;
118 default:
119 break;
120 }
121
122 // Record operation timing in internal metrics
123 // Note: PerformanceProfiler uses StartTimer/EndTimer pattern, not
124 // RecordOperation
125
126 // Update usage tracker if available
127 if (usage_tracker_) {
128 usage_tracker_->RecordOperation(operation_name, time_ms);
129 }
130}
131
133 size_t bitmap_memory,
134 size_t palette_memory) {
135 current_metrics_.texture_memory_mb = texture_memory / (1024 * 1024);
136 current_metrics_.bitmap_memory_mb = bitmap_memory / (1024 * 1024);
137 current_metrics_.palette_memory_mb = palette_memory / (1024 * 1024);
138}
139
146
147// These methods are already defined in the header as inline, removing
148// duplicates
149
151 std::ostringstream summary;
152
153 summary << "Canvas Performance Summary (" << canvas_id_ << ")\n";
154 summary << "=====================================\n\n";
155
156 summary << "Timing Metrics:\n";
157 summary << " Frame Time: " << FormatTime(current_metrics_.frame_time_ms)
158 << "\n";
159 summary << " Draw Time: " << FormatTime(current_metrics_.draw_time_ms)
160 << "\n";
161 summary << " Interaction Time: "
163 summary << " Modal Time: " << FormatTime(current_metrics_.modal_time_ms)
164 << "\n\n";
165
166 summary << "Operation Counts:\n";
167 summary << " Draw Calls: " << current_metrics_.draw_calls << "\n";
168 summary << " Texture Updates: " << current_metrics_.texture_updates << "\n";
169 summary << " Palette Lookups: " << current_metrics_.palette_lookups << "\n";
170 summary << " Bitmap Operations: " << current_metrics_.bitmap_operations
171 << "\n\n";
172
173 summary << "Canvas Operations:\n";
174 summary << " Tile Paint: " << current_metrics_.tile_paint_operations << "\n";
175 summary << " Tile Select: " << current_metrics_.tile_select_operations
176 << "\n";
177 summary << " Rectangle Select: "
179 summary << " Color Paint: " << current_metrics_.color_paint_operations
180 << "\n";
181 summary << " BPP Conversion: " << current_metrics_.bpp_conversion_operations
182 << "\n\n";
183
184 summary << "Memory Usage:\n";
185 summary << " Texture Memory: "
187 << "\n";
188 summary << " Bitmap Memory: "
190 << "\n";
191 summary << " Palette Memory: "
193 << "\n\n";
194
195 summary << "Cache Performance:\n";
196 summary << " Hit Ratio: " << std::fixed << std::setprecision(1)
197 << (current_metrics_.cache_hit_ratio * 100.0) << "%\n";
198 summary << " Hits: " << current_metrics_.cache_hits << "\n";
199 summary << " Misses: " << current_metrics_.cache_misses << "\n";
200
201 return summary.str();
202}
203
204std::vector<std::string>
206 std::vector<std::string> recommendations;
207
208 // Frame time recommendations
209 if (current_metrics_.frame_time_ms > 16.67) { // 60 FPS threshold
210 recommendations.push_back(
211 "Frame time is high - consider reducing draw calls or optimizing "
212 "rendering");
213 }
214
215 // Draw time recommendations
216 if (current_metrics_.draw_time_ms > 10.0) {
217 recommendations.push_back(
218 "Draw time is high - consider using texture atlases or reducing "
219 "texture switches");
220 }
221
222 // Memory recommendations
223 size_t total_memory = current_metrics_.texture_memory_mb +
226 if (total_memory > 100) { // 100MB threshold
227 recommendations.push_back(
228 "Memory usage is high - consider implementing texture streaming or "
229 "compression");
230 }
231
232 // Cache recommendations
234 recommendations.push_back(
235 "Cache hit ratio is low - consider increasing cache size or improving "
236 "cache strategy");
237 }
238
239 // Operation count recommendations
240 if (current_metrics_.draw_calls > 1000) {
241 recommendations.push_back(
242 "High draw call count - consider batching operations or using "
243 "instanced rendering");
244 }
245
247 recommendations.push_back(
248 "Frequent texture updates - consider using texture arrays or atlases");
249 }
250
251 return recommendations;
252}
253
255 std::ostringstream report;
256
257 report << "Canvas Performance Report\n";
258 report << "========================\n\n";
259
260 report << "Canvas ID: " << canvas_id_ << "\n";
261 report << "Monitoring Enabled: " << (monitoring_enabled_ ? "Yes" : "No")
262 << "\n\n";
263
264 report << GetPerformanceSummary() << "\n";
265
266 // Performance history
267 if (!performance_history_.empty()) {
268 report << "Performance History:\n";
269 report << "===================\n\n";
270
271 for (size_t i = 0; i < performance_history_.size(); ++i) {
272 const auto& metrics = performance_history_[i];
273 report << "Sample " << (i + 1) << ":\n";
274 report << " Frame Time: " << FormatTime(metrics.frame_time_ms) << "\n";
275 report << " Draw Calls: " << metrics.draw_calls << "\n";
276 report << " Memory: "
277 << FormatMemory((metrics.texture_memory_mb +
278 metrics.bitmap_memory_mb +
279 metrics.palette_memory_mb) *
280 1024 * 1024)
281 << "\n\n";
282 }
283 }
284
285 // Recommendations
286 auto recommendations = GetPerformanceRecommendations();
287 if (!recommendations.empty()) {
288 report << "Recommendations:\n";
289 report << "===============\n\n";
290 for (const auto& rec : recommendations) {
291 report << "• " << rec << "\n";
292 }
293 }
294
295 return report.str();
296}
297
300 return;
301
302 if (ImGui::Begin("Canvas Performance", &show_performance_ui_)) {
303 // Performance overview
305
307 ImGui::Separator();
309 }
310
312 ImGui::Separator();
314 }
315
316 // Control buttons
317 ImGui::Separator();
318 if (ImGui::Button("Toggle Detailed Metrics")) {
320 }
321 ImGui::SameLine();
322 if (ImGui::Button("Toggle Recommendations")) {
324 }
325 ImGui::SameLine();
326 if (ImGui::Button("Export Report")) {
327 std::string report = ExportPerformanceReport();
328 // Could save to file or show in modal
329 }
330 }
331 ImGui::End();
332}
333
335 std::shared_ptr<CanvasUsageTracker> tracker) {
336 usage_tracker_ = tracker;
337}
338
340 if (frame_timer_) {
341 // Frame time would be calculated by the timer
342 current_metrics_.frame_time_ms = 16.67; // Placeholder
343 }
344}
345
347 if (draw_timer_) {
348 // Draw time would be calculated by the timer
349 current_metrics_.draw_time_ms = 5.0; // Placeholder
350 }
351}
352
354 if (interaction_timer_) {
355 // Interaction time would be calculated by the timer
356 current_metrics_.interaction_time_ms = 1.0; // Placeholder
357 }
358}
359
361 if (modal_timer_) {
362 // Modal time would be calculated by the timer
363 current_metrics_.modal_time_ms = 0.5; // Placeholder
364 }
365}
366
368 int total_requests =
370 if (total_requests > 0) {
372 static_cast<double>(current_metrics_.cache_hits) / total_requests;
373 } else {
375 }
376}
377
380
381 // Keep only last 100 samples
382 if (performance_history_.size() > 100) {
384 }
385}
386
388 // Analyze performance trends and patterns
389 if (performance_history_.size() < 2)
390 return;
391
392 // Calculate trends
393 double frame_time_trend = 0.0;
394 double memory_trend = 0.0;
395
396 for (size_t i = 1; i < performance_history_.size(); ++i) {
397 const auto& prev = performance_history_[i - 1];
398 const auto& curr = performance_history_[i];
399
400 frame_time_trend += (curr.frame_time_ms - prev.frame_time_ms);
401 memory_trend += ((curr.texture_memory_mb + curr.bitmap_memory_mb +
402 curr.palette_memory_mb) -
403 (prev.texture_memory_mb + prev.bitmap_memory_mb +
404 prev.palette_memory_mb));
405 }
406
407 frame_time_trend /= (performance_history_.size() - 1);
408 memory_trend /= (performance_history_.size() - 1);
409
410 // Log trends
411 if (std::abs(frame_time_trend) > 1.0) {
412 LOG_DEBUG("CanvasPerformance",
413 "Canvas %s: Frame time trend: %.2f ms/sample", canvas_id_.c_str(),
414 frame_time_trend);
415 }
416
417 if (std::abs(memory_trend) > 1.0) {
418 LOG_DEBUG("CanvasPerformance", "Canvas %s: Memory trend: %.2f MB/sample",
419 canvas_id_.c_str(), memory_trend);
420 }
421}
422
424 ImGui::Text("Performance Overview");
425 ImGui::Separator();
426
427 // Frame time
428 ImVec4 frame_color =
430 ImGui::TextColored(frame_color, "Frame Time: %s",
432
433 // Draw time
434 ImVec4 draw_color =
436 ImGui::TextColored(draw_color, "Draw Time: %s",
438
439 // Memory usage
440 size_t total_memory = current_metrics_.texture_memory_mb +
443 ImVec4 memory_color = GetPerformanceColor(total_memory, 50.0, 100.0);
444 ImGui::TextColored(memory_color, "Memory: %s",
445 FormatMemory(total_memory * 1024 * 1024).c_str());
446
447 // Cache performance
448 ImVec4 cache_color =
450 ImGui::TextColored(cache_color, "Cache Hit Ratio: %.1f%%",
452}
453
455 ImGui::Text("Detailed Metrics");
456 ImGui::Separator();
457
458 // Operation counts
460
461 // Memory breakdown
463
464 // Cache performance
466}
467
469 if (ImGui::CollapsingHeader("Memory Usage")) {
470 ImGui::Text(
471 "Texture Memory: %s",
472 FormatMemory(current_metrics_.texture_memory_mb * 1024 * 1024).c_str());
473 ImGui::Text(
474 "Bitmap Memory: %s",
475 FormatMemory(current_metrics_.bitmap_memory_mb * 1024 * 1024).c_str());
476 ImGui::Text(
477 "Palette Memory: %s",
478 FormatMemory(current_metrics_.palette_memory_mb * 1024 * 1024).c_str());
479
480 size_t total = current_metrics_.texture_memory_mb +
483 ImGui::Text("Total Memory: %s", FormatMemory(total * 1024 * 1024).c_str());
484 }
485}
486
488 if (ImGui::CollapsingHeader("Operation Counts")) {
489 ImGui::Text("Draw Calls: %d", current_metrics_.draw_calls);
490 ImGui::Text("Texture Updates: %d", current_metrics_.texture_updates);
491 ImGui::Text("Palette Lookups: %d", current_metrics_.palette_lookups);
492 ImGui::Text("Bitmap Operations: %d", current_metrics_.bitmap_operations);
493
494 ImGui::Separator();
495 ImGui::Text("Canvas Operations:");
496 ImGui::Text(" Tile Paint: %d", current_metrics_.tile_paint_operations);
497 ImGui::Text(" Tile Select: %d", current_metrics_.tile_select_operations);
498 ImGui::Text(" Rectangle Select: %d",
500 ImGui::Text(" Color Paint: %d", current_metrics_.color_paint_operations);
501 ImGui::Text(" BPP Conversion: %d",
503 }
504}
505
507 if (ImGui::CollapsingHeader("Cache Performance")) {
508 ImGui::Text("Cache Hits: %d", current_metrics_.cache_hits);
509 ImGui::Text("Cache Misses: %d", current_metrics_.cache_misses);
510 ImGui::Text("Hit Ratio: %.1f%%", current_metrics_.cache_hit_ratio * 100.0);
511
512 // Cache hit ratio bar
513 ImGui::ProgressBar(current_metrics_.cache_hit_ratio, ImVec2(0, 0));
514 }
515}
516
518 ImGui::Text("Performance Recommendations");
519 ImGui::Separator();
520
521 auto recommendations = GetPerformanceRecommendations();
522 if (recommendations.empty()) {
523 ImGui::TextColored(ImVec4(0.2F, 1.0F, 0.2F, 1.0F),
524 "✓ Performance looks good!");
525 } else {
526 for (const auto& rec : recommendations) {
527 ImGui::TextColored(ImVec4(1.0F, 0.8F, 0.2F, 1.0F), "⚠ %s", rec.c_str());
528 }
529 }
530}
531
533 if (ImGui::CollapsingHeader("Performance Graph")) {
534 // Simple performance graph using ImGui plot lines
535 static std::vector<float> frame_times;
536 static std::vector<float> draw_times;
537
538 // Add current values
539 frame_times.push_back(static_cast<float>(current_metrics_.frame_time_ms));
540 draw_times.push_back(static_cast<float>(current_metrics_.draw_time_ms));
541
542 // Keep only last 100 samples
543 if (frame_times.size() > 100) {
544 frame_times.erase(frame_times.begin());
545 draw_times.erase(draw_times.begin());
546 }
547
548 if (!frame_times.empty()) {
549 ImGui::PlotLines("Frame Time (ms)", frame_times.data(),
550 static_cast<int>(frame_times.size()), 0, nullptr, 0.0F,
551 50.0F, ImVec2(0, 100));
552 ImGui::PlotLines("Draw Time (ms)", draw_times.data(),
553 static_cast<int>(draw_times.size()), 0, nullptr, 0.0F,
554 30.0F, ImVec2(0, 100));
555 }
556 }
557}
558
559std::string CanvasPerformanceIntegration::FormatTime(double time_ms) const {
560 if (time_ms < 1.0) {
561 return std::to_string(static_cast<int>(time_ms * 1000)) + " μs";
562 } else if (time_ms < 1000.0) {
563 return std::to_string(static_cast<int>(time_ms * 10) / 10.0) + " ms";
564 } else {
565 return std::to_string(static_cast<int>(time_ms / 1000)) + " s";
566 }
567}
568
569std::string CanvasPerformanceIntegration::FormatMemory(size_t bytes) const {
570 if (bytes < 1024) {
571 return std::to_string(bytes) + " B";
572 } else if (bytes < 1024 * 1024) {
573 return std::to_string(bytes / 1024) + " KB";
574 } else {
575 return std::to_string(bytes / (1024 * 1024)) + " MB";
576 }
577}
578
580 double value, double threshold_good, double threshold_warning) const {
581 if (value <= threshold_good) {
582 return ImVec4(0.2F, 1.0F, 0.2F, 1.0F); // Green
583 } else if (value <= threshold_warning) {
584 return ImVec4(1.0F, 1.0F, 0.2F, 1.0F); // Yellow
585 } else {
586 return ImVec4(1.0F, 0.2F, 0.2F, 1.0F); // Red
587 }
588}
589
590// CanvasPerformanceManager implementation
591
593 static CanvasPerformanceManager instance;
594 return instance;
595}
596
598 const std::string& canvas_id,
599 std::shared_ptr<CanvasPerformanceIntegration> integration) {
600 integrations_[canvas_id] = integration;
601 LOG_DEBUG("CanvasPerformance",
602 "Registered performance integration for canvas: %s",
603 canvas_id.c_str());
604}
605
606std::shared_ptr<CanvasPerformanceIntegration>
607CanvasPerformanceManager::GetIntegration(const std::string& canvas_id) {
608 auto it = integrations_.find(canvas_id);
609 if (it != integrations_.end()) {
610 return it->second;
611 }
612 return nullptr;
613}
614
616 for (auto& [id, integration] : integrations_) {
617 integration->UpdateMetrics();
618 }
619}
620
622 std::ostringstream summary;
623
624 summary << "Global Canvas Performance Summary\n";
625 summary << "=================================\n\n";
626
627 summary << "Registered Canvases: " << integrations_.size() << "\n\n";
628
629 for (const auto& [id, integration] : integrations_) {
630 summary << "Canvas: " << id << "\n";
631 summary << "----------------------------------------\n";
632 summary << integration->GetPerformanceSummary() << "\n\n";
633 }
634
635 return summary.str();
636}
637
639 std::ostringstream report;
640
641 report << "Global Canvas Performance Report\n";
642 report << "================================\n\n";
643
644 report << GetGlobalPerformanceSummary();
645
646 // Global recommendations
647 report << "Global Recommendations:\n";
648 report << "=======================\n\n";
649
650 for (const auto& [id, integration] : integrations_) {
651 auto recommendations = integration->GetPerformanceRecommendations();
652 if (!recommendations.empty()) {
653 report << "Canvas " << id << ":\n";
654 for (const auto& rec : recommendations) {
655 report << " • " << rec << "\n";
656 }
657 report << "\n";
658 }
659 }
660
661 return report.str();
662}
663
665 for (auto& [id, integration] : integrations_) {
666 integration->StopMonitoring();
667 }
668 integrations_.clear();
669 LOG_DEBUG("CanvasPerformance", "Cleared all canvas performance integrations");
670}
671
672} // namespace gui
673} // namespace yaze
static PerformanceDashboard & Get()
void StartMonitoring()
Start performance monitoring.
std::vector< std::string > GetPerformanceRecommendations() const
Get performance recommendations.
std::string ExportPerformanceReport() const
Export performance report.
std::vector< CanvasPerformanceMetrics > performance_history_
std::shared_ptr< CanvasUsageTracker > usage_tracker_
std::string GetPerformanceSummary() const
Get performance summary.
void SetUsageTracker(std::shared_ptr< CanvasUsageTracker > tracker)
Set usage tracker integration.
void RecordMemoryUsage(size_t texture_memory, size_t bitmap_memory, size_t palette_memory)
Record memory usage.
void RecordOperation(const std::string &operation_name, double time_ms, CanvasUsage usage_mode=CanvasUsage::kUnknown)
Record canvas operation.
void Initialize(const std::string &canvas_id)
Initialize performance integration.
ImVec4 GetPerformanceColor(double value, double threshold_good, double threshold_warning) const
void RecordCachePerformance(int hits, int misses)
Record cache performance.
std::unique_ptr< gfx::ScopedTimer > interaction_timer_
std::string GetGlobalPerformanceSummary() const
Get global performance summary.
std::unordered_map< std::string, std::shared_ptr< CanvasPerformanceIntegration > > integrations_
std::string ExportGlobalPerformanceReport() const
Export global performance report.
std::shared_ptr< CanvasPerformanceIntegration > GetIntegration(const std::string &canvas_id)
Get integration for canvas.
void RegisterIntegration(const std::string &canvas_id, std::shared_ptr< CanvasPerformanceIntegration > integration)
Register a canvas performance integration.
#define LOG_DEBUG(category, format,...)
Definition log.h:103
CanvasUsage
Canvas usage patterns and tracking.