Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Optims found while profiling, and dumb benchmark tool #1825

Closed
wants to merge 4 commits into from

5 participants

@theuni
Owner

This is just some hacking I did while profiling AE, looking for wasted cpu cycles. In the meantime I needed a way to test small changes and their impact on the CPU in some measurable way, this was the result. It's not particularly pretty, and only useful for internal testing, but it's better than nothing.

The 3 optims address the top 3 cpu consumers on their own. The result of some optimizing was a 5.8% decrease in average frame-time, excluding gpu operations as this was done with d-r+noflip on a static scene.

Just putting this out there for discussion, not for Frodo.

Cory Fields added some commits
Cory Fields profile: Add a very dumb benchmark tool for profiling
At most, this lets us measure before/after frame-times when tweaking small but
busy parts of the codebase.
19082aa
Cory Fields profile: MULTI_INFO is hit ~75% of the time, make it the first check dd07646
Cory Fields profile: Cache controls' render regions to avoid the costly generateAABB eb20746
Cory Fields profile: stack.size() can be O(n) and these are done hundreds of time…
…s per frame. Keep track of the size instead.
d505fd0
@elupus
Collaborator
@theuni
Owner

@elupus Yup, my first thought was to just use .empty() instead, but since we need to be able to return the size in 2 places (including RemoveTransform(), which gets the most traffic) I opted for local storage. I'm happy to do that though if there's an issue with caching it, other than it being ugly and non-obvious.

@jmarshallnz
Owner

You can probably kill the returning of the stack size in RemoveTransform. It's used only for debugging stuff, which has long been fixed. Instead, adding a function wrapped in _DEBUG to check the stack size might be a better way to go.

@elupus
Collaborator

@theuni merge?

@jmarshallnz
Owner

I've forced a rebase by fixing up the .empty/size stuff above in master.

@davilla
Collaborator
@MartijnKaijser

closing for now as it's semi merged already

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Nov 21, 2012
  1. profile: Add a very dumb benchmark tool for profiling

    Cory Fields authored
    At most, this lets us measure before/after frame-times when tweaking small but
    busy parts of the codebase.
  2. profile: stack.size() can be O(n) and these are done hundreds of time…

    Cory Fields authored
    …s per frame. Keep track of the size instead.
This page is out of date. Refresh to see the latest.
View
8 xbmc/Application.cpp
@@ -2333,7 +2333,7 @@ void CApplication::Render()
flip = true;
//fps limiter, make sure each frame lasts at least singleFrameTime milliseconds
- if (limitFrames || !flip)
+ if ((limitFrames || !flip) && !m_benchmarkTimer)
{
if (!limitFrames)
singleFrameTime = 40; //if not flipping, loop at 25 fps
@@ -5036,7 +5036,11 @@ bool CApplication::ExecuteXBMCAction(std::string actionStr)
void CApplication::Process()
{
MEASURE_FUNCTION;
-
+ if (m_benchmarkTimer && XbmcThreads::SystemClockMillis() >= m_benchmarkTimer)
+ {
+ Stop(0);
+ return;
+ }
// dispatch the messages generated by python or other threads to the current window
g_windowManager.DispatchThreadMessages();
View
5 xbmc/Application.h
@@ -348,6 +348,11 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs
return m_bTestMode;
}
+ void SetBenchmarkTimer(unsigned int timer)
+ {
+ m_benchmarkTimer = timer;
+ }
+
bool IsPresentFrame();
void Minimize();
View
6 xbmc/GUIInfoManager.cpp
@@ -2045,6 +2045,8 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI
bool bReturn = false;
int condition = abs(condition1);
+ if (condition >= MULTI_INFO_START && condition <= MULTI_INFO_END)
+ return GetMultiInfoBool(m_multiInfo[condition - MULTI_INFO_START], contextWindow, item);
if (item && condition >= LISTITEM_START && condition < LISTITEM_END)
bReturn = GetItemBool(item, condition);
// Ethernet Link state checking
@@ -2145,10 +2147,6 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI
bReturn = m_playerShowInfo;
else if (condition == PLAYER_SHOWCODEC)
bReturn = m_playerShowCodec;
- else if (condition >= MULTI_INFO_START && condition <= MULTI_INFO_END)
- {
- return GetMultiInfoBool(m_multiInfo[condition - MULTI_INFO_START], contextWindow, item);
- }
else if (condition == SYSTEM_HASLOCKS)
bReturn = g_settings.GetMasterProfile().getLockMode() != LOCK_MODE_EVERYONE;
else if (condition == SYSTEM_HAS_PVR)
View
13 xbmc/XBApplicationEx.cpp
@@ -42,6 +42,7 @@ CXBApplicationEx::CXBApplicationEx()
m_AppFocused = true;
m_ExitCode = EXITCODE_QUIT;
m_renderGUI = false;
+ m_benchmarkTimer = 0;
}
CXBApplicationEx::~CXBApplicationEx()
@@ -91,6 +92,10 @@ INT CXBApplicationEx::Run()
const BYTE MAX_EXCEPTION_COUNT = 10;
#endif
+ m_firstFrameTime = XbmcThreads::SystemClockMillis();
+ if (m_benchmarkTimer)
+ m_benchmarkTimer += m_firstFrameTime;
+
// Run xbmc
while (!m_bStop)
{
@@ -209,9 +214,17 @@ INT CXBApplicationEx::Run()
}
}
#endif
+ m_totalFrames++;
} // while (!m_bStop)
+ unsigned int uptime = lastFrameTime - m_firstFrameTime;
Destroy();
CLog::Log(LOGNOTICE, "application stopped..." );
+
+ if (m_benchmarkTimer)
+ {
+ printf("Processed %llu Frames in %i msec.\n",m_totalFrames, uptime);
+ }
+
return m_ExitCode;
}
View
3  xbmc/XBApplicationEx.h
@@ -55,6 +55,9 @@ class CXBApplicationEx : public IWindowManagerCallback
INT Run();
VOID Destroy();
+ unsigned long long m_totalFrames;
+ unsigned int m_benchmarkTimer;
+ unsigned int m_firstFrameTime;
private:
};
View
11 xbmc/guilib/GUIControl.cpp
@@ -58,7 +58,8 @@ CGUIControl::CGUIControl()
}
CGUIControl::CGUIControl(int parentID, int controlID, float posX, float posY, float width, float height)
-: m_hitRect(posX, posY, posX + width, posY + height)
+: m_hitRect(posX, posY, posX + width, posY + height),
+ m_cachedRenderRegion(0,0,0,0)
{
m_posX = posX;
m_posY = posY;
@@ -161,9 +162,13 @@ void CGUIControl::DoProcess(unsigned int currentTime, CDirtyRegionList &dirtyreg
void CGUIControl::Process(unsigned int currentTime, CDirtyRegionList &dirtyregions)
{
// update our render region
- m_renderRegion = g_graphicsContext.generateAABB(CalcRenderRegion());
+ CRect region(CalcRenderRegion());
+ if (region != m_cachedRenderRegion)
+ {
+ m_cachedRenderRegion = region;
+ m_renderRegion = g_graphicsContext.generateAABB(m_cachedRenderRegion);
+ }
}
-
// the main render routine.
// 1. set the animation transform
// 2. if visible, paint
View
1  xbmc/guilib/GUIControl.h
@@ -357,6 +357,7 @@ class CGUIControl
bool m_controlIsDirty;
CRect m_renderRegion; // In screen coordinates
+ CRect m_cachedRenderRegion;
};
#endif
View
3  xbmc/guilib/GraphicContext.cpp
@@ -52,7 +52,8 @@ CGraphicContext::CGraphicContext(void) :
m_Resolution(RES_INVALID),
/*m_windowResolution,*/
m_guiScaleX(1.0f),
- m_guiScaleY(1.0f)
+ m_guiScaleY(1.0f),
+ m_groupTransformSize(0)
/*,m_cameras, */
/*m_origins, */
/*m_clipRegions,*/
View
27 xbmc/guilib/GraphicContext.h
@@ -171,16 +171,17 @@ class CGraphicContext : public CCriticalSection
void ClipRect(CRect &vertex, CRect &texture, CRect *diffuse = NULL);
inline unsigned int AddGUITransform()
{
- unsigned int size = m_groupTransform.size();
m_groupTransform.push(m_guiTransform);
- UpdateFinalTransform(m_groupTransform.top());
- return size;
+ m_groupTransformSize++;
+ UpdateFinalTransform(m_guiTransform);
+ return m_groupTransformSize - 1;
}
inline TransformMatrix AddTransform(const TransformMatrix &matrix)
{
- ASSERT(m_groupTransform.size());
- TransformMatrix absoluteMatrix = m_groupTransform.size() ? m_groupTransform.top() * matrix : matrix;
+ ASSERT(m_groupTransformSize);
+ TransformMatrix absoluteMatrix = m_groupTransformSize ? m_groupTransform.top() * matrix : matrix;
m_groupTransform.push(absoluteMatrix);
+ m_groupTransformSize++;
UpdateFinalTransform(absoluteMatrix);
return absoluteMatrix;
}
@@ -188,20 +189,24 @@ class CGraphicContext : public CCriticalSection
{
// TODO: We only need to add it to the group transform as other transforms may be added on top of this one later on
// Once all transforms are cached then this can be removed and UpdateFinalTransform can be called directly
- ASSERT(m_groupTransform.size());
+ ASSERT(m_groupTransformSize);
m_groupTransform.push(matrix);
+ m_groupTransformSize++;
UpdateFinalTransform(m_groupTransform.top());
}
inline unsigned int RemoveTransform()
{
- ASSERT(m_groupTransform.size());
- if (m_groupTransform.size())
+ ASSERT(m_groupTransformSize);
+ if (m_groupTransformSize)
+ {
m_groupTransform.pop();
- if (m_groupTransform.size())
+ m_groupTransformSize--;
+ }
+ if (m_groupTransformSize)
UpdateFinalTransform(m_groupTransform.top());
else
UpdateFinalTransform(TransformMatrix());
- return m_groupTransform.size();
+ return m_groupTransformSize;
}
CRect generateAABB(const CRect &rect) const;
@@ -232,7 +237,7 @@ class CGraphicContext : public CCriticalSection
TransformMatrix m_guiTransform;
TransformMatrix m_finalTransform;
std::stack<TransformMatrix> m_groupTransform;
-
+ unsigned int m_groupTransformSize;
CRect m_scissors;
};
View
8 xbmc/settings/AppParamParser.cpp
@@ -92,6 +92,7 @@ void CAppParamParser::DisplayHelp()
printf("Usage: xbmc [OPTION]... [FILE]...\n\n");
printf("Arguments:\n");
printf(" -d <n>\t\tdelay <n> seconds before starting\n");
+ printf(" --benchmark=n\t\tEnable meaningless benchmark mode. Run for <n> msec then display the number of frames rendered\n");
printf(" -fs\t\t\tRuns XBMC in full screen\n");
printf(" --standalone\t\tXBMC runs in a stand alone environment without a window \n");
printf("\t\t\tmanager and supporting applications. For example, that\n");
@@ -137,6 +138,13 @@ void CAppParamParser::ParseArg(const CStdString &arg)
m_testmode = true;
else if (arg.substr(0, 11) == "--settings=")
g_advancedSettings.AddSettingsFile(arg.substr(11));
+ else if (arg.substr(0, 12) == "--benchmark=")
+ {
+ unsigned int benchmark_time = atoi(arg.substr(12).c_str());
+ if (benchmark_time)
+ g_application.SetBenchmarkTimer(benchmark_time);
+ }
+
else if (arg.length() != 0 && arg[0] != '-')
{
if (m_testmode)
Something went wrong with that request. Please try again.