Skip to content

Commit c5df26d

Browse files
committed
Fixed broken Timing::Timer due to inconsistent timing function usage.
Added some basic profiling timers for processors, which can be seen in the world inspector.
1 parent c1a0e47 commit c5df26d

File tree

4 files changed

+146
-92
lines changed

4 files changed

+146
-92
lines changed

code/application/game/frameevent.cc

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,7 @@ FrameEvent::AddProcessor(Processor* processor)
7575
// try to insert into existing batches
7676
for (i = 0; i < this->batches.Size(); i++)
7777
{
78-
if (this->batches[i]->async == processor->async &&
79-
this->batches[i]->order == processor->order)
78+
if (this->batches[i]->async == processor->async && this->batches[i]->order == processor->order)
8079
{
8180
accepted = this->batches[i]->TryInsert(processor);
8281
if (accepted)
@@ -224,7 +223,8 @@ FrameEvent::Batch::Prefilter(World* world, bool force)
224223
Processor* processor = this->processors[i];
225224
if (!processor->cacheValid || force)
226225
{
227-
processor->cache = world->GetDatabase()->Query(GetInclusiveTableMask(processor->filter), GetExclusiveTableMask(processor->filter));
226+
processor->cache =
227+
world->GetDatabase()->Query(GetInclusiveTableMask(processor->filter), GetExclusiveTableMask(processor->filter));
228228
processor->cacheValid = true;
229229
}
230230
}
@@ -284,6 +284,15 @@ FrameEvent::Batch::ExecuteAsync(World* world)
284284
{
285285
Processor* processor = this->processors[i];
286286

287+
if (!processor->active)
288+
continue;
289+
290+
#ifdef NEBULA_ENABLE_PROFILING
291+
// TODO: Async batch processors will have the same timings for now. We should figure out some good way of measuring their elapsed time.
292+
processor->timer.Reset();
293+
processor->timer.Start();
294+
#endif
295+
287296
#ifdef WITH_NEBULA_EDITOR
288297
if (Game::EditorState::HasInstance())
289298
{
@@ -294,11 +303,22 @@ FrameEvent::Batch::ExecuteAsync(World* world)
294303
#endif
295304
datasets[i] = world->Query(processor->filter, processor->cache);
296305
numJobs += datasets[i].numViews;
297-
298306
}
299307

300308
if (numJobs == 0)
309+
{
310+
#ifdef NEBULA_ENABLE_PROFILING
311+
for (IndexT i = 0; i < this->processors.Size(); i++)
312+
{
313+
Processor* processor = this->processors[i];
314+
if (!processor->active)
315+
continue;
316+
317+
processor->timer.Stop();
318+
}
319+
#endif
301320
return;
321+
}
302322

303323
ProcessorJobContext context;
304324
context.world = world;
@@ -318,6 +338,17 @@ FrameEvent::Batch::ExecuteAsync(World* world)
318338
Jobs2::JobDispatch(FrameBatchJob, numJobs, 1, context, nullptr, nullptr, &event);
319339
event.Wait();
320340

341+
#ifdef NEBULA_ENABLE_PROFILING
342+
for (IndexT i = 0; i < this->processors.Size(); i++)
343+
{
344+
Processor* processor = this->processors[i];
345+
if (!processor->active)
346+
continue;
347+
348+
processor->timer.Stop();
349+
}
350+
#endif
351+
321352
delete[] context.inputs;
322353
}
323354

@@ -343,11 +374,20 @@ FrameEvent::Batch::ExecuteSequential(World* world)
343374
}
344375
#endif
345376

377+
#ifdef NEBULA_ENABLE_PROFILING
378+
processor->timer.Reset();
379+
processor->timer.Start();
380+
#endif
381+
346382
Dataset data = world->Query(processor->filter, processor->cache);
347383
for (int v = 0; v < data.numViews; v++)
348384
{
349385
processor->callback(world, data.views[v]);
350386
}
387+
388+
#ifdef NEBULA_ENABLE_PROFILING
389+
processor->timer.Stop();
390+
#endif
351391
}
352392
}
353393

@@ -529,4 +569,3 @@ FramePipeline::GetFrameEvents() const
529569
}
530570

531571
} // namespace Game
532-

code/application/game/processor.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
(C) 2022 Individual contributors, see AUTHORS file
88
*/
99
//------------------------------------------------------------------------------
10+
#include "timing/timer.h"
1011
#include "util/stringatom.h"
1112
#include "filter.h"
1213
#include "processorid.h"
@@ -37,6 +38,10 @@ class Processor
3738
bool cacheValid = false;
3839
/// set to false if the processor shouldn't execute in the frame.
3940
bool active = true;
41+
#ifdef NEBULA_ENABLE_PROFILING
42+
/// Profiling timer, handled by the frame pipeline.
43+
Timing::Timer timer;
44+
#endif
4045
#ifdef WITH_NEBULA_EDITOR
4146
/// set to true if you want this processor to always run in editor
4247
bool runInEditor = false;

code/application/game/world.cc

Lines changed: 94 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,6 @@ World::ManageEntities()
527527

528528
// Delete all remaining invalid instances
529529
Ptr<MemDb::Database> const& db = this->db;
530-
531530
if (db.isvalid())
532531
{
533532
db->ForEachTable(
@@ -1544,6 +1543,10 @@ World::RenderDebug()
15441543
}
15451544
ImGui::Unindent();
15461545
}
1546+
#ifdef NEBULA_ENABLE_PROFILING
1547+
ImGui::SameLine();
1548+
ImGui::Text(" | [ %0.3fms ]", (float)(processor->timer.GetTime() * 1000.0));
1549+
#endif
15471550
}
15481551
ImGui::Unindent();
15491552
}
@@ -1589,105 +1592,110 @@ World::RenderDebug()
15891592

15901593
static bool listInactive = false;
15911594
ImGui::Checkbox("List inactive instances", &listInactive);
1592-
ImGui::Text("Entity map:");
1593-
ImGui::BeginChild(
1594-
"ScrollingRegion", ImVec2(0, -ImGui::GetFrameHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar
1595-
);
1595+
static bool showEntities = false;
1596+
ImGui::Checkbox("Show Entity List", &showEntities);
1597+
if (showEntities)
15961598
{
1597-
for (uint entityIndex = 0; entityIndex < this->entityMap.Size(); entityIndex++)
1599+
ImGui::Text("Entity map:");
1600+
ImGui::BeginChild(
1601+
"ScrollingRegion", ImVec2(0, -ImGui::GetFrameHeightWithSpacing()), false, ImGuiWindowFlags_HorizontalScrollbar
1602+
);
15981603
{
1599-
Game::EntityMapping entityMapping = this->entityMap[entityIndex];
1600-
1601-
if (!listInactive && (entityMapping.table == MemDb::InvalidTableId || entityMapping.instance == MemDb::InvalidRow))
1602-
continue;
1603-
1604-
ImGui::BeginGroup();
1605-
ImGui::Text("[%i] ", entityIndex);
1606-
ImGui::SameLine();
1607-
ImGui::TextColored(
1608-
{1, 0.3f, 0, 1},
1609-
"tid:%i, partition: %i, index: %i",
1610-
entityMapping.table,
1611-
entityMapping.instance.partition,
1612-
entityMapping.instance.index
1613-
);
1614-
if (entityMapping.table != MemDb::TableId::Invalid())
1604+
for (uint entityIndex = 0; entityIndex < this->entityMap.Size(); entityIndex++)
16151605
{
1616-
ImGui::TextDisabled("- %s", this->db->GetTable(entityMapping.table).name.Value());
1617-
ImGui::EndGroup();
1618-
if (ImGui::IsItemHovered())
1606+
Game::EntityMapping entityMapping = this->entityMap[entityIndex];
1607+
1608+
if (!listInactive && (entityMapping.table == MemDb::InvalidTableId || entityMapping.instance == MemDb::InvalidRow))
1609+
continue;
1610+
1611+
ImGui::BeginGroup();
1612+
ImGui::Text("[%i] ", entityIndex);
1613+
ImGui::SameLine();
1614+
ImGui::TextColored(
1615+
{1, 0.3f, 0, 1},
1616+
"tid:%i, partition: %i, index: %i",
1617+
entityMapping.table,
1618+
entityMapping.instance.partition,
1619+
entityMapping.instance.index
1620+
);
1621+
if (entityMapping.table != MemDb::TableId::Invalid())
16191622
{
1620-
ImGui::BeginTooltip();
16211623
ImGui::TextDisabled("- %s", this->db->GetTable(entityMapping.table).name.Value());
1622-
MemDb::TableId const table = entityMapping.table;
1623-
MemDb::RowId const row = entityMapping.instance;
1624-
1625-
void* ownerBuffer = this->GetInstanceBuffer(table, row.partition, Game::Entity::Traits::fixed_column_index);
1626-
ownerBuffer = (byte*)ownerBuffer + (row.index * sizeof(Game::Entity));
1627-
Game::Entity owner = *(Game::Entity*)ownerBuffer;
1628-
1629-
ImGui::TextDisabled("Entity: %llu", (uint64_t)owner);
1630-
ImGui::TextDisabled("Entity.world: %llu", (uint64_t)owner.world);
1631-
ImGui::TextDisabled("Entity.reserved: %llu", (uint64_t)owner.reserved);
1632-
ImGui::TextDisabled("Entity.generation: %llu", (uint64_t)owner.generation);
1633-
ImGui::TextDisabled("Entity.index: %llu", (uint64_t)owner.index);
1634-
1635-
bool prevDebugState = Game::ComponentInspection::Instance()->debug;
1636-
Game::ComponentInspection::Instance()->debug = true;
1637-
auto const& components = this->db->GetTable(table).GetAttributes();
1638-
for (auto component : components)
1624+
ImGui::EndGroup();
1625+
if (ImGui::IsItemHovered())
16391626
{
1640-
Game::ComponentInterface* cInterface =
1641-
(Game::ComponentInterface*)MemDb::AttributeRegistry::GetAttribute(component);
1642-
if (cInterface->GetNumFields() == 0)
1627+
ImGui::BeginTooltip();
1628+
ImGui::TextDisabled("- %s", this->db->GetTable(entityMapping.table).name.Value());
1629+
MemDb::TableId const table = entityMapping.table;
1630+
MemDb::RowId const row = entityMapping.instance;
1631+
1632+
void* ownerBuffer = this->GetInstanceBuffer(table, row.partition, Game::Entity::Traits::fixed_column_index);
1633+
ownerBuffer = (byte*)ownerBuffer + (row.index * sizeof(Game::Entity));
1634+
Game::Entity owner = *(Game::Entity*)ownerBuffer;
1635+
1636+
ImGui::TextDisabled("Entity: %llu", (uint64_t)owner);
1637+
ImGui::TextDisabled("Entity.world: %llu", (uint64_t)owner.world);
1638+
ImGui::TextDisabled("Entity.reserved: %llu", (uint64_t)owner.reserved);
1639+
ImGui::TextDisabled("Entity.generation: %llu", (uint64_t)owner.generation);
1640+
ImGui::TextDisabled("Entity.index: %llu", (uint64_t)owner.index);
1641+
1642+
bool prevDebugState = Game::ComponentInspection::Instance()->debug;
1643+
Game::ComponentInspection::Instance()->debug = true;
1644+
auto const& components = this->db->GetTable(table).GetAttributes();
1645+
for (auto component : components)
16431646
{
1644-
// Type is flag type, just print the name, and then continue
1645-
ImGui::Text("_flag_: %s", MemDb::AttributeRegistry::GetAttribute(component)->name.Value());
1647+
Game::ComponentInterface* cInterface =
1648+
(Game::ComponentInterface*)MemDb::AttributeRegistry::GetAttribute(component);
1649+
if (cInterface->GetNumFields() == 0)
1650+
{
1651+
// Type is flag type, just print the name, and then continue
1652+
ImGui::Text("_flag_: %s", MemDb::AttributeRegistry::GetAttribute(component)->name.Value());
1653+
ImGui::Separator();
1654+
continue;
1655+
}
1656+
else
1657+
{
1658+
ImGui::Text(MemDb::AttributeRegistry::GetAttribute(component)->name.Value());
1659+
}
1660+
SizeT const typeSize = MemDb::AttributeRegistry::TypeSize(component);
1661+
void* data = this->GetInstanceBuffer(table, row.partition, component);
1662+
data = (byte*)data + (row.index * typeSize);
1663+
1664+
const ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Borders |
1665+
ImGuiTableFlags_RowBg | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
1666+
ImGui::PushID(row.index + 0xF23);
1667+
if (ImGui::BeginTable(MemDb::AttributeRegistry::GetAttribute(component)->name.Value(), 2, flags))
1668+
{
1669+
ImGui::TableSetupColumn("FieldName", ImGuiTableColumnFlags_WidthFixed);
1670+
ImGui::TableSetupColumn("FieldValue", ImGuiTableColumnFlags_WidthStretch);
1671+
1672+
ImGui::TableNextRow();
1673+
bool commitChange = false;
1674+
1675+
Game::ComponentInspection::DrawInspector(owner, component, data, &commitChange);
1676+
ImGui::EndTable();
1677+
ImGui::Spacing();
1678+
ImGui::Spacing();
1679+
ImGui::Spacing();
1680+
}
1681+
ImGui::PopID();
1682+
16461683
ImGui::Separator();
1647-
continue;
1648-
}
1649-
else
1650-
{
1651-
ImGui::Text(MemDb::AttributeRegistry::GetAttribute(component)->name.Value());
1652-
}
1653-
SizeT const typeSize = MemDb::AttributeRegistry::TypeSize(component);
1654-
void* data = this->GetInstanceBuffer(table, row.partition, component);
1655-
data = (byte*)data + (row.index * typeSize);
1656-
1657-
const ImGuiTableFlags flags = ImGuiTableFlags_SizingFixedFit | ImGuiTableFlags_Borders |
1658-
ImGuiTableFlags_RowBg | ImGuiTableFlags_Reorderable | ImGuiTableFlags_Hideable;
1659-
ImGui::PushID(row.index + 0xF23);
1660-
if (ImGui::BeginTable(MemDb::AttributeRegistry::GetAttribute(component)->name.Value(), 2, flags))
1661-
{
1662-
ImGui::TableSetupColumn("FieldName", ImGuiTableColumnFlags_WidthFixed);
1663-
ImGui::TableSetupColumn("FieldValue", ImGuiTableColumnFlags_WidthStretch);
1664-
1665-
ImGui::TableNextRow();
1666-
bool commitChange = false;
1667-
1668-
Game::ComponentInspection::DrawInspector(owner, component, data, &commitChange);
1669-
ImGui::EndTable();
1670-
ImGui::Spacing();
1671-
ImGui::Spacing();
1672-
ImGui::Spacing();
16731684
}
1674-
ImGui::PopID();
1675-
1676-
ImGui::Separator();
1685+
Game::ComponentInspection::Instance()->debug = prevDebugState;
1686+
ImGui::EndTooltip();
16771687
}
1678-
Game::ComponentInspection::Instance()->debug = prevDebugState;
1679-
ImGui::EndTooltip();
16801688
}
1689+
else
1690+
{
1691+
ImGui::EndGroup();
1692+
ImGui::TextDisabled("- ");
1693+
}
1694+
ImGui::Separator();
16811695
}
1682-
else
1683-
{
1684-
ImGui::EndGroup();
1685-
ImGui::TextDisabled("- ");
1686-
}
1687-
ImGui::Separator();
16881696
}
1697+
ImGui::EndChild();
16891698
}
1690-
ImGui::EndChild();
16911699
}
16921700

16931701
//------------------------------------------------------------------------------

code/foundation/timing/posix/posixtimer.cc

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,9 @@ void
5656
PosixTimer::Stop()
5757
{
5858
n_assert(this->running);
59-
this->stopTime = clock();
59+
timespec times;
60+
n_assert(clock_gettime(CLOCK_MONOTONIC,&times) == 0);
61+
this->stopTime = ToTime(times);
6062
this->running = false;
6163
}
6264

0 commit comments

Comments
 (0)