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 <sstream>
5#include <iomanip>
6#include <chrono>
7
10#include "util/log.h"
11#include "imgui/imgui.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
30 if (!monitoring_enabled_) return;
31
32 // Start frame timer
34 frame_timer_ = std::make_unique<gfx::ScopedTimer>("canvas_frame_" + canvas_id_);
35
36 LOG_DEBUG("CanvasPerformance", "Started performance monitoring for canvas: %s",
37 canvas_id_.c_str());
38}
39
41 // Release timers in reverse order of creation to ensure clean shutdown
43 modal_timer_.reset();
44 modal_timer_active_ = false;
45 }
47 interaction_timer_.reset();
49 }
51 draw_timer_.reset();
52 draw_timer_active_ = false;
53 }
55 frame_timer_.reset();
56 frame_timer_active_ = false;
57 }
58
59 LOG_DEBUG("CanvasPerformance", "Stopped performance monitoring for canvas: %s",
60 canvas_id_.c_str());
61}
62
64 if (!monitoring_enabled_) return;
65
66 // Update frame time
68
69 // Update draw time
71
72 // Update interaction time
74
75 // Update modal time
77
78 // Calculate cache hit ratio
80
81 // Save current metrics periodically
82 static auto last_save = std::chrono::steady_clock::now();
83 auto now = std::chrono::steady_clock::now();
84 if (std::chrono::duration_cast<std::chrono::seconds>(now - last_save).count() >= 5) {
86 last_save = now;
87 }
88}
89
90void CanvasPerformanceIntegration::RecordOperation(const std::string& operation_name,
91 double time_ms,
92 CanvasUsage usage_mode) {
93 if (!monitoring_enabled_) return;
94
95 // Update operation counts based on usage mode
96 switch (usage_mode) {
99 break;
102 break;
105 break;
108 break;
111 break;
112 default:
113 break;
114 }
115
116 // Record operation timing in internal metrics
117 // Note: PerformanceProfiler uses StartTimer/EndTimer pattern, not RecordOperation
118
119 // Update usage tracker if available
120 if (usage_tracker_) {
121 usage_tracker_->RecordOperation(operation_name, time_ms);
122 }
123}
124
126 size_t bitmap_memory,
127 size_t palette_memory) {
128 current_metrics_.texture_memory_mb = texture_memory / (1024 * 1024);
129 current_metrics_.bitmap_memory_mb = bitmap_memory / (1024 * 1024);
130 current_metrics_.palette_memory_mb = palette_memory / (1024 * 1024);
131}
132
138
139// These methods are already defined in the header as inline, removing duplicates
140
142 std::ostringstream summary;
143
144 summary << "Canvas Performance Summary (" << canvas_id_ << ")\n";
145 summary << "=====================================\n\n";
146
147 summary << "Timing Metrics:\n";
148 summary << " Frame Time: " << FormatTime(current_metrics_.frame_time_ms) << "\n";
149 summary << " Draw Time: " << FormatTime(current_metrics_.draw_time_ms) << "\n";
150 summary << " Interaction Time: " << FormatTime(current_metrics_.interaction_time_ms) << "\n";
151 summary << " Modal Time: " << FormatTime(current_metrics_.modal_time_ms) << "\n\n";
152
153 summary << "Operation Counts:\n";
154 summary << " Draw Calls: " << current_metrics_.draw_calls << "\n";
155 summary << " Texture Updates: " << current_metrics_.texture_updates << "\n";
156 summary << " Palette Lookups: " << current_metrics_.palette_lookups << "\n";
157 summary << " Bitmap Operations: " << current_metrics_.bitmap_operations << "\n\n";
158
159 summary << "Canvas Operations:\n";
160 summary << " Tile Paint: " << current_metrics_.tile_paint_operations << "\n";
161 summary << " Tile Select: " << current_metrics_.tile_select_operations << "\n";
162 summary << " Rectangle Select: " << current_metrics_.rectangle_select_operations << "\n";
163 summary << " Color Paint: " << current_metrics_.color_paint_operations << "\n";
164 summary << " BPP Conversion: " << current_metrics_.bpp_conversion_operations << "\n\n";
165
166 summary << "Memory Usage:\n";
167 summary << " Texture Memory: " << FormatMemory(current_metrics_.texture_memory_mb * 1024 * 1024) << "\n";
168 summary << " Bitmap Memory: " << FormatMemory(current_metrics_.bitmap_memory_mb * 1024 * 1024) << "\n";
169 summary << " Palette Memory: " << FormatMemory(current_metrics_.palette_memory_mb * 1024 * 1024) << "\n\n";
170
171 summary << "Cache Performance:\n";
172 summary << " Hit Ratio: " << std::fixed << std::setprecision(1)
173 << (current_metrics_.cache_hit_ratio * 100.0) << "%\n";
174 summary << " Hits: " << current_metrics_.cache_hits << "\n";
175 summary << " Misses: " << current_metrics_.cache_misses << "\n";
176
177 return summary.str();
178}
179
181 std::vector<std::string> recommendations;
182
183 // Frame time recommendations
184 if (current_metrics_.frame_time_ms > 16.67) { // 60 FPS threshold
185 recommendations.push_back("Frame time is high - consider reducing draw calls or optimizing rendering");
186 }
187
188 // Draw time recommendations
189 if (current_metrics_.draw_time_ms > 10.0) {
190 recommendations.push_back("Draw time is high - consider using texture atlases or reducing texture switches");
191 }
192
193 // Memory recommendations
194 size_t total_memory = current_metrics_.texture_memory_mb +
197 if (total_memory > 100) { // 100MB threshold
198 recommendations.push_back("Memory usage is high - consider implementing texture streaming or compression");
199 }
200
201 // Cache recommendations
203 recommendations.push_back("Cache hit ratio is low - consider increasing cache size or improving cache strategy");
204 }
205
206 // Operation count recommendations
207 if (current_metrics_.draw_calls > 1000) {
208 recommendations.push_back("High draw call count - consider batching operations or using instanced rendering");
209 }
210
212 recommendations.push_back("Frequent texture updates - consider using texture arrays or atlases");
213 }
214
215 return recommendations;
216}
217
219 std::ostringstream report;
220
221 report << "Canvas Performance Report\n";
222 report << "========================\n\n";
223
224 report << "Canvas ID: " << canvas_id_ << "\n";
225 report << "Monitoring Enabled: " << (monitoring_enabled_ ? "Yes" : "No") << "\n\n";
226
227 report << GetPerformanceSummary() << "\n";
228
229 // Performance history
230 if (!performance_history_.empty()) {
231 report << "Performance History:\n";
232 report << "===================\n\n";
233
234 for (size_t i = 0; i < performance_history_.size(); ++i) {
235 const auto& metrics = performance_history_[i];
236 report << "Sample " << (i + 1) << ":\n";
237 report << " Frame Time: " << FormatTime(metrics.frame_time_ms) << "\n";
238 report << " Draw Calls: " << metrics.draw_calls << "\n";
239 report << " Memory: " << FormatMemory((metrics.texture_memory_mb +
240 metrics.bitmap_memory_mb +
241 metrics.palette_memory_mb) * 1024 * 1024) << "\n\n";
242 }
243 }
244
245 // Recommendations
246 auto recommendations = GetPerformanceRecommendations();
247 if (!recommendations.empty()) {
248 report << "Recommendations:\n";
249 report << "===============\n\n";
250 for (const auto& rec : recommendations) {
251 report << "• " << rec << "\n";
252 }
253 }
254
255 return report.str();
256}
257
259 if (!monitoring_enabled_) return;
260
261 if (ImGui::Begin("Canvas Performance", &show_performance_ui_)) {
262 // Performance overview
264
266 ImGui::Separator();
268 }
269
271 ImGui::Separator();
273 }
274
275 // Control buttons
276 ImGui::Separator();
277 if (ImGui::Button("Toggle Detailed Metrics")) {
279 }
280 ImGui::SameLine();
281 if (ImGui::Button("Toggle Recommendations")) {
283 }
284 ImGui::SameLine();
285 if (ImGui::Button("Export Report")) {
286 std::string report = ExportPerformanceReport();
287 // Could save to file or show in modal
288 }
289 }
290 ImGui::End();
291}
292
293void CanvasPerformanceIntegration::SetUsageTracker(std::shared_ptr<CanvasUsageTracker> tracker) {
294 usage_tracker_ = tracker;
295}
296
298 if (frame_timer_) {
299 // Frame time would be calculated by the timer
300 current_metrics_.frame_time_ms = 16.67; // Placeholder
301 }
302}
303
305 if (draw_timer_) {
306 // Draw time would be calculated by the timer
307 current_metrics_.draw_time_ms = 5.0; // Placeholder
308 }
309}
310
312 if (interaction_timer_) {
313 // Interaction time would be calculated by the timer
314 current_metrics_.interaction_time_ms = 1.0; // Placeholder
315 }
316}
317
319 if (modal_timer_) {
320 // Modal time would be calculated by the timer
321 current_metrics_.modal_time_ms = 0.5; // Placeholder
322 }
323}
324
327 if (total_requests > 0) {
328 current_metrics_.cache_hit_ratio = static_cast<double>(current_metrics_.cache_hits) / total_requests;
329 } else {
331 }
332}
333
336
337 // Keep only last 100 samples
338 if (performance_history_.size() > 100) {
340 }
341}
342
344 // Analyze performance trends and patterns
345 if (performance_history_.size() < 2) return;
346
347 // Calculate trends
348 double frame_time_trend = 0.0;
349 double memory_trend = 0.0;
350
351 for (size_t i = 1; i < performance_history_.size(); ++i) {
352 const auto& prev = performance_history_[i - 1];
353 const auto& curr = performance_history_[i];
354
355 frame_time_trend += (curr.frame_time_ms - prev.frame_time_ms);
356 memory_trend += ((curr.texture_memory_mb + curr.bitmap_memory_mb + curr.palette_memory_mb) -
357 (prev.texture_memory_mb + prev.bitmap_memory_mb + prev.palette_memory_mb));
358 }
359
360 frame_time_trend /= (performance_history_.size() - 1);
361 memory_trend /= (performance_history_.size() - 1);
362
363 // Log trends
364 if (std::abs(frame_time_trend) > 1.0) {
365 LOG_DEBUG("CanvasPerformance", "Canvas %s: Frame time trend: %.2f ms/sample",
366 canvas_id_.c_str(), frame_time_trend);
367 }
368
369 if (std::abs(memory_trend) > 1.0) {
370 LOG_DEBUG("CanvasPerformance", "Canvas %s: Memory trend: %.2f MB/sample",
371 canvas_id_.c_str(), memory_trend);
372 }
373}
374
376 ImGui::Text("Performance Overview");
377 ImGui::Separator();
378
379 // Frame time
380 ImVec4 frame_color = GetPerformanceColor(current_metrics_.frame_time_ms, 16.67, 33.33);
381 ImGui::TextColored(frame_color, "Frame Time: %s", FormatTime(current_metrics_.frame_time_ms).c_str());
382
383 // Draw time
384 ImVec4 draw_color = GetPerformanceColor(current_metrics_.draw_time_ms, 10.0, 20.0);
385 ImGui::TextColored(draw_color, "Draw Time: %s", FormatTime(current_metrics_.draw_time_ms).c_str());
386
387 // Memory usage
388 size_t total_memory = current_metrics_.texture_memory_mb +
391 ImVec4 memory_color = GetPerformanceColor(total_memory, 50.0, 100.0);
392 ImGui::TextColored(memory_color, "Memory: %s", FormatMemory(total_memory * 1024 * 1024).c_str());
393
394 // Cache performance
395 ImVec4 cache_color = GetPerformanceColor(current_metrics_.cache_hit_ratio * 100.0, 80.0, 60.0);
396 ImGui::TextColored(cache_color, "Cache Hit Ratio: %.1f%%", current_metrics_.cache_hit_ratio * 100.0);
397}
398
400 ImGui::Text("Detailed Metrics");
401 ImGui::Separator();
402
403 // Operation counts
405
406 // Memory breakdown
408
409 // Cache performance
411}
412
414 if (ImGui::CollapsingHeader("Memory Usage")) {
415 ImGui::Text("Texture Memory: %s", FormatMemory(current_metrics_.texture_memory_mb * 1024 * 1024).c_str());
416 ImGui::Text("Bitmap Memory: %s", FormatMemory(current_metrics_.bitmap_memory_mb * 1024 * 1024).c_str());
417 ImGui::Text("Palette Memory: %s", FormatMemory(current_metrics_.palette_memory_mb * 1024 * 1024).c_str());
418
419 size_t total = current_metrics_.texture_memory_mb +
422 ImGui::Text("Total Memory: %s", FormatMemory(total * 1024 * 1024).c_str());
423 }
424}
425
427 if (ImGui::CollapsingHeader("Operation Counts")) {
428 ImGui::Text("Draw Calls: %d", current_metrics_.draw_calls);
429 ImGui::Text("Texture Updates: %d", current_metrics_.texture_updates);
430 ImGui::Text("Palette Lookups: %d", current_metrics_.palette_lookups);
431 ImGui::Text("Bitmap Operations: %d", current_metrics_.bitmap_operations);
432
433 ImGui::Separator();
434 ImGui::Text("Canvas Operations:");
435 ImGui::Text(" Tile Paint: %d", current_metrics_.tile_paint_operations);
436 ImGui::Text(" Tile Select: %d", current_metrics_.tile_select_operations);
437 ImGui::Text(" Rectangle Select: %d", current_metrics_.rectangle_select_operations);
438 ImGui::Text(" Color Paint: %d", current_metrics_.color_paint_operations);
439 ImGui::Text(" BPP Conversion: %d", current_metrics_.bpp_conversion_operations);
440 }
441}
442
444 if (ImGui::CollapsingHeader("Cache Performance")) {
445 ImGui::Text("Cache Hits: %d", current_metrics_.cache_hits);
446 ImGui::Text("Cache Misses: %d", current_metrics_.cache_misses);
447 ImGui::Text("Hit Ratio: %.1f%%", current_metrics_.cache_hit_ratio * 100.0);
448
449 // Cache hit ratio bar
450 ImGui::ProgressBar(current_metrics_.cache_hit_ratio, ImVec2(0, 0));
451 }
452}
453
455 ImGui::Text("Performance Recommendations");
456 ImGui::Separator();
457
458 auto recommendations = GetPerformanceRecommendations();
459 if (recommendations.empty()) {
460 ImGui::TextColored(ImVec4(0.2F, 1.0F, 0.2F, 1.0F), "✓ Performance looks good!");
461 } else {
462 for (const auto& rec : recommendations) {
463 ImGui::TextColored(ImVec4(1.0F, 0.8F, 0.2F, 1.0F), "⚠ %s", rec.c_str());
464 }
465 }
466}
467
469 if (ImGui::CollapsingHeader("Performance Graph")) {
470 // Simple performance graph using ImGui plot lines
471 static std::vector<float> frame_times;
472 static std::vector<float> draw_times;
473
474 // Add current values
475 frame_times.push_back(static_cast<float>(current_metrics_.frame_time_ms));
476 draw_times.push_back(static_cast<float>(current_metrics_.draw_time_ms));
477
478 // Keep only last 100 samples
479 if (frame_times.size() > 100) {
480 frame_times.erase(frame_times.begin());
481 draw_times.erase(draw_times.begin());
482 }
483
484 if (!frame_times.empty()) {
485 ImGui::PlotLines("Frame Time (ms)", frame_times.data(),
486 static_cast<int>(frame_times.size()), 0, nullptr, 0.0F, 50.0F,
487 ImVec2(0, 100));
488 ImGui::PlotLines("Draw Time (ms)", draw_times.data(),
489 static_cast<int>(draw_times.size()), 0, nullptr, 0.0F, 30.0F,
490 ImVec2(0, 100));
491 }
492 }
493}
494
495std::string CanvasPerformanceIntegration::FormatTime(double time_ms) const {
496 if (time_ms < 1.0) {
497 return std::to_string(static_cast<int>(time_ms * 1000)) + " μs";
498 } else if (time_ms < 1000.0) {
499 return std::to_string(static_cast<int>(time_ms * 10) / 10.0) + " ms";
500 } else {
501 return std::to_string(static_cast<int>(time_ms / 1000)) + " s";
502 }
503}
504
505std::string CanvasPerformanceIntegration::FormatMemory(size_t bytes) const {
506 if (bytes < 1024) {
507 return std::to_string(bytes) + " B";
508 } else if (bytes < 1024 * 1024) {
509 return std::to_string(bytes / 1024) + " KB";
510 } else {
511 return std::to_string(bytes / (1024 * 1024)) + " MB";
512 }
513}
514
516 double threshold_good,
517 double threshold_warning) const {
518 if (value <= threshold_good) {
519 return ImVec4(0.2F, 1.0F, 0.2F, 1.0F); // Green
520 } else if (value <= threshold_warning) {
521 return ImVec4(1.0F, 1.0F, 0.2F, 1.0F); // Yellow
522 } else {
523 return ImVec4(1.0F, 0.2F, 0.2F, 1.0F); // Red
524 }
525}
526
527// CanvasPerformanceManager implementation
528
530 static CanvasPerformanceManager instance;
531 return instance;
532}
533
535 const std::string& canvas_id,
536 std::shared_ptr<CanvasPerformanceIntegration> integration) {
537 integrations_[canvas_id] = integration;
538 LOG_DEBUG("CanvasPerformance",
539 "Registered performance integration for canvas: %s",
540 canvas_id.c_str());
541}
542
543std::shared_ptr<CanvasPerformanceIntegration>
544CanvasPerformanceManager::GetIntegration(const std::string& canvas_id) {
545 auto it = integrations_.find(canvas_id);
546 if (it != integrations_.end()) {
547 return it->second;
548 }
549 return nullptr;
550}
551
553 for (auto& [id, integration] : integrations_) {
554 integration->UpdateMetrics();
555 }
556}
557
559 std::ostringstream summary;
560
561 summary << "Global Canvas Performance Summary\n";
562 summary << "=================================\n\n";
563
564 summary << "Registered Canvases: " << integrations_.size() << "\n\n";
565
566 for (const auto& [id, integration] : integrations_) {
567 summary << "Canvas: " << id << "\n";
568 summary << "----------------------------------------\n";
569 summary << integration->GetPerformanceSummary() << "\n\n";
570 }
571
572 return summary.str();
573}
574
576 std::ostringstream report;
577
578 report << "Global Canvas Performance Report\n";
579 report << "================================\n\n";
580
581 report << GetGlobalPerformanceSummary();
582
583 // Global recommendations
584 report << "Global Recommendations:\n";
585 report << "=======================\n\n";
586
587 for (const auto& [id, integration] : integrations_) {
588 auto recommendations = integration->GetPerformanceRecommendations();
589 if (!recommendations.empty()) {
590 report << "Canvas " << id << ":\n";
591 for (const auto& rec : recommendations) {
592 report << " • " << rec << "\n";
593 }
594 report << "\n";
595 }
596 }
597
598 return report.str();
599}
600
602 for (auto& [id, integration] : integrations_) {
603 integration->StopMonitoring();
604 }
605 integrations_.clear();
606 LOG_DEBUG("CanvasPerformance", "Cleared all canvas performance integrations");
607}
608
609} // namespace gui
610} // 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:104
CanvasUsage
Canvas usage patterns and tracking.
Main namespace for the application.
Definition controller.cc:20