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