mirror of
https://github.com/MaSzyna-EU07/maszyna.git
synced 2026-07-18 01:59:19 +02:00
Skip pure-visual leaf includes in the infrastructure pass
On a million-instance scenery (tomaszewo) the infra pass was spending ~24s reopening pure-visual leaf twins (grass.incb etc.) just to skip their content -- ~200k cParser constructions, because every flora include reopens the same leaf. Twin header now flags whether a file has any infrastructure node or include (format bumped to v10). A pure-visual leaf (flora .incb: triangles + transform directives only) has it clear, so the infra pass skips opening it: the first open of each file caches the verdict, later opens are dropped before construction. Result on tomaszewo: infra 55s -> 31s, getToken 1.06M -> 89k. Also adds a load profiler (per-type build time, dispatch time, getToken count) behind WriteLog so the next bottleneck is measured, not guessed (it's now the 25s of decorative vehicle media loading).
This commit is contained in:
@@ -621,6 +621,14 @@ void cParser::processInclude(cParser& srcParser, bool ToLower) {
|
||||
startIncludeDirect(std::move(pick), std::move(params));
|
||||
}
|
||||
|
||||
std::map<std::string, bool> cParser::s_infraskip;
|
||||
|
||||
bool cParser::infraRelevant() const {
|
||||
return (m_replay && m_reader) ? m_reader->infra_relevant() : true;
|
||||
}
|
||||
|
||||
void cParser::clearInfraSkipCache() { s_infraskip.clear(); }
|
||||
|
||||
void cParser::startIncludeDirect(std::string includefile, std::vector<std::string> Params) {
|
||||
|
||||
const bool allowTraction =
|
||||
@@ -632,6 +640,19 @@ void cParser::startIncludeDirect(std::string includefile, std::vector<std::strin
|
||||
return;
|
||||
}
|
||||
|
||||
// infrastructure pass: don't open a pure-visual leaf (e.g. a flora .incb) just to skip its
|
||||
// content -- on a million-instance scenery that was ~200k wasted reopens. the first open of
|
||||
// each file records whether it's infra-relevant; later opens of the same file are skipped.
|
||||
bool const infrapass = (m_replaypass == scene::scenery_load_pass::infrastructure);
|
||||
std::string skipkey;
|
||||
if (infrapass) {
|
||||
skipkey = mPath + includefile;
|
||||
auto const it = s_infraskip.find(skipkey);
|
||||
if ((it != s_infraskip.end()) && (true == it->second)) {
|
||||
return; // known pure-visual leaf
|
||||
}
|
||||
}
|
||||
|
||||
if (Global.ParserLogIncludes) {
|
||||
// WriteLog("including: " + includefile);
|
||||
}
|
||||
@@ -645,6 +666,17 @@ void cParser::startIncludeDirect(std::string includefile, std::vector<std::strin
|
||||
// consistently (e.g. visuals-only on the second pass)
|
||||
mIncludeParser->setReplayPass(m_replaypass);
|
||||
|
||||
// infrastructure pass: a pure-visual leaf twin has nothing to do here. record it (so the next
|
||||
// of its thousands of reopens is skipped before even opening) and drop it now.
|
||||
if (infrapass && mIncludeParser->m_replay) {
|
||||
bool const relevant = mIncludeParser->infraRelevant();
|
||||
s_infraskip[skipkey] = (false == relevant);
|
||||
if (false == relevant) {
|
||||
mIncludeParser = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// pass filtering (infra eager / visual deferred) relies on the per-node markers that
|
||||
// only a binary twin carries. an un-baked (text) include has no markers, so it can't
|
||||
// be split: it is loaded in full during the infrastructure pass. on the visual pass we
|
||||
|
||||
Reference in New Issue
Block a user