Performance Notes
Four performance issues were identified and documented in RAM.md. All are located in src/WindowsPhoneSpeedyBlupi/Decor.cpp. None are blocking ā the game runs correctly ā but they represent unnecessary CPU overhead per frame.
Performance Analysis Source
The analysis is documented in RAM.md at the repository root. All four issues are in Decor.cpp in the ByeByeObject particle system and the MoveObject sort routine.
make_shared / make_unique calls are all one-time
initialization (LoadContent, constructors). There are no per-frame allocations.
Issue 1 ā ByeByeDraw (Decor.cpp:9252)
Severity: Low ā copies a 72-byte struct every iteration of the per-frame draw loop.
// Current ā copies 72-byte ByeByeObject struct each iteration:
for (ByeByeObject obj : m_byeByeObjects) {
DrawByeByeObject(obj);
}
// Fix ā use const reference:
for (const ByeByeObject& obj : m_byeByeObjects) {
DrawByeByeObject(obj);
}
Issue 2 ā ByeByeAdd (Decor.cpp:9187ā9206)
Severity: Low ā double-copy before vector insertion (construct on stack, then copy into vector).
// Current ā constructs on stack then copies:
ByeByeObject obj;
obj.x = x;
obj.y = y;
obj.icon = icon;
// ... more fields ...
m_byeByeObjects.push_back(obj); // copy
// Fix ā use emplace_back with direct field initialization:
m_byeByeObjects.emplace_back(x, y, icon, ...);
Issue 3 ā ByeByeStep (Decor.cpp:9241)
Severity: Medium ā vector::erase() called in the middle of a vector during iteration is O(n) per removal. With many short-lived particles, this becomes O(n²).
// Current ā O(n) erase during iteration:
for (auto it = m_byeByeObjects.begin(); it != m_byeByeObjects.end(); ) {
it->time--;
if (it->time <= 0) {
it = m_byeByeObjects.erase(it); // O(n) shift
} else {
++it;
}
}
// Fix ā erase-remove idiom (single O(n) pass):
for (auto& obj : m_byeByeObjects) obj.time--;
m_byeByeObjects.erase(
std::remove_if(m_byeByeObjects.begin(), m_byeByeObjects.end(),
[](const ByeByeObject& o){ return o.time <= 0; }),
m_byeByeObjects.end()
);
Issue 4 ā MoveObjectSort (Decor.cpp:9074ā9108)
Severity: Medium ā manual bubble sort with manual struct copying for the MoveObject array. This is O(n²) with a very large constant factor (each swap copies the whole struct).
// Current ā manual bubble sort:
for (int i = 0; i < m_moveObjectCount - 1; i++) {
for (int j = i + 1; j < m_moveObjectCount; j++) {
if (m_moveObject[i].z > m_moveObject[j].z) {
MoveObject temp = m_moveObject[i]; // full struct copy
m_moveObject[i] = m_moveObject[j];
m_moveObject[j] = temp;
}
}
}
// Fix ā std::sort with lambda comparator:
std::sort(m_moveObject, m_moveObject + m_moveObjectCount,
[](const MoveObject& a, const MoveObject& b){
return a.z < b.z;
});
Heap Allocation Status
The analysis scanned for per-frame heap allocations and found none. All make_shared and make_unique calls are in one-time initialization paths:
Game1::LoadContent()ā createsPixmapandSoundinstances onceGame1::Initialize()ā other one-time allocations- Constructors ā class member initialization
No heap allocations were found in Update() or Draw() hot paths.