Jump to content
  • Advertisement
Sign in to follow this  

Compiler optimization and asMETHODPR slowdowns

This topic is 2261 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I get extreme complation times when I try to compile my .cpp files that contain the script registrations. But this only happens when Compiler Optimization is active in Visual Studio.
When bulding a Debug release the complation time for the file is around 5 seconds, with Compiler Optimization it takes 8 minutes. If I remove all the code containing asMETHODPR the compilation time goes down to 19 seconds in Release.

I am looking for any tips on what I can have done wrong or how I can reduce the compliation time. Any help is appreciated.
The only way that I have found was to turn off Optimzation locally via "#pragma optimize("", off)". This reduced the complation time to 5 seconds.

Here is how I register the classes and methods. (I tried to use ='cpp' for syntax highlight, but all the code collapsed to one line)

The file registers 25 classes with each class registering around 70 methods. All classes inheret from the base class iWidget which has 50 methods that are registered again for each class.

[source]#define kRegisterWidgetMethods(aClass) \
RegisterMethod("void Update(float afTimeStep)", asMETHODPR(aClass, Update, (float), void)); \
RegisterMethod("bool ProcessMessage(eGuiMessage aMessage, const cGuiMessageData&in aData, bool abSkipVisCheck=false, bool abSkipEnabledCheck=false)", asMETHODPR(aClass, ProcessMessage, (eGuiMessage, const cGuiMessageData&, bool, bool), bool)); \
RegisterMethod("eWidgetType GetType()", asMETHODPR(aClass, GetType, (), eWidgetType)); \
RegisterMethod("void Init()", asMETHODPR(aClass, Init, (), void)); \
RegisterMethod("cGuiGlobalShortcut@ AddShortcut(int alKeyModifiers, eKey aKey, eGuiMessage aMsg=eGuiMessage_ButtonPressed, const cGuiMessageData&in aData=cGuiMessageData(), bool abBypassVisibility=true, bool abBypassEnabled=true)", asMETHODPR(aClass, AddShortcut, (int, eKey, eGuiMessage, const cGuiMessageData&in, bool, bool), cGuiGlobalShortcut*)); \
RegisterMethod("void SetToolTip(const tWString&in asToolTip)", asMETHODPR(aClass, SetToolTip, (const tWString&), void)); \
RegisterMethod("const tWString& GetToolTip()", asMETHODPR(aClass, GetToolTip, (), const tWString&)); \
RegisterMethod("void SetToolTipEnabled(bool abX)", asMETHODPR(aClass, SetToolTipEnabled, (bool), void)); \
RegisterMethod("bool IsToolTipEnabled()", asMETHODPR(aClass, IsToolTipEnabled, (), bool)); \
RegisterMethod("bool PointIsInside(const cVector2f&in avPoint, bool abOnlyClipped)", asMETHODPR(aClass, PointIsInside, (const cVector2f&, bool), bool)); \
RegisterMethod("void AttachChild(iWidget@ apChild)", asMETHODPR(aClass, AttachChild, (iWidget*), void)); \
RegisterMethod("void RemoveChild(iWidget@ apChild)", asMETHODPR(aClass, RemoveChild, (iWidget*), void)); \
RegisterMethod("cGuiSet@ GetSet()", asMETHODPR(aClass, GetSet, (), cGuiSet*)); \
RegisterMethod("iWidget@ GetParent()", asMETHODPR(aClass, GetParent, (), iWidget*)); \
RegisterMethod("void SetEnabled(bool abX)", asMETHODPR(aClass, SetEnabled, (bool), void)); \
RegisterMethod("bool IsEnabled()", asMETHODPR(aClass, IsEnabled, (), bool)); \
RegisterMethod("void SetVisible(bool abX)", asMETHODPR(aClass, SetVisible, (bool), void)); \
RegisterMethod("bool IsVisible()", asMETHODPR(aClass, IsVisible, (), bool)); \
RegisterMethod("bool HasFocus()", asMETHODPR(aClass, HasFocus, (), bool)); \
RegisterMethod("bool IsRightUnderMouse()", asMETHODPR(aClass, IsRightUnderMouse, (), bool)); \
RegisterMethod("void SetName(const tString&in asName)", asMETHODPR(aClass, SetName, (const tString&), void)); \
RegisterMethod("const tString& GetName()", asMETHODPR(aClass, GetName, (), const tString&)); \
RegisterMethod("void SetText(const tWString&in asText)", asMETHODPR(aClass, SetText, (const tWString&), void)); \
RegisterMethod("const tWString& GetText()const", asMETHODPR(aClass, GetText, ()const, const tWString&)); \
RegisterMethod("iFontData@ GetDefaultFontType()", asMETHODPR(aClass, GetDefaultFontType, (), iFontData*)); \
RegisterMethod("void SetDefaultFontType(iFontData@ apFont)", asMETHODPR(aClass, SetDefaultFontType, (iFontData*), void)); \
RegisterMethod("const cColor& GetDefaultFontColor()", asMETHODPR(aClass, GetDefaultFontColor, (), const cColor&)); \
RegisterMethod("void SetDefaultFontColor(const cColor&in aColor)", asMETHODPR(aClass, SetDefaultFontColor, (const cColor&), void)); \
RegisterMethod("const cVector2f& GetDefaultFontSize()", asMETHODPR(aClass, GetDefaultFontSize, (), const cVector2f&)); \
RegisterMethod("void SetDefaultFontSize(const cVector2f&in avSize)", asMETHODPR(aClass, SetDefaultFontSize, (const cVector2f&), void)); \
RegisterMethod("void SetClipActive(bool abX)", asMETHODPR(aClass, SetClipActive, (bool), void)); \
RegisterMethod("bool GetClipActive()", asMETHODPR(aClass, GetClipActive, (), bool)); \
RegisterMethod("void SetPosition(const cVector3f&in avPos)", asMETHODPR(aClass, SetPosition, (const cVector3f&), void)); \
RegisterMethod("void SetGlobalPosition(const cVector3f&in avPos)", asMETHODPR(aClass, SetGlobalPosition, (const cVector3f&), void)); \
RegisterMethod("const cVector3f& GetLocalPosition()", asMETHODPR(aClass, GetLocalPosition, (), const cVector3f&)); \
RegisterMethod("const cVector3f& GetGlobalPosition()", asMETHODPR(aClass, GetGlobalPosition, (), const cVector3f&)); \
RegisterMethod("void SetChildrenOffset(const cVector3f&in)", asMETHODPR(aClass, SetChildrenOffset, (const cVector3f&), void)); \
RegisterMethod("const cVector3f& GetChildrenOffset()", asMETHODPR(aClass, GetChildrenOffset, (), const cVector3f&)); \
RegisterMethod("void SetAffectedByScroll(bool abX)", asMETHODPR(aClass, SetAffectedByScroll, (bool), void)); \
RegisterMethod("void SetScrollAmount(const cVector3f&in avX)", asMETHODPR(aClass, SetScrollAmount, (const cVector3f&), void)); \
RegisterMethod("const cVector3f& GetScrollAmount()", asMETHODPR(aClass, GetScrollAmount, (), const cVector3f&)); \
RegisterMethod("void CenterGlobalPositionInSet()", asMETHODPR(aClass, CenterGlobalPositionInSet, (), void)); \
RegisterMethod("void SetSize(const cVector2f&in avSize)", asMETHODPR(aClass, SetSize, (const cVector2f&), void)); \
RegisterMethod("cVector2f GetSize()", asMETHODPR(aClass, GetSize, (), cVector2f)); \
RegisterMethod("void SetColorMul(const cColor&in aColor)", asMETHODPR(aClass, SetColorMul, (const cColor&), void)); \
RegisterMethod("const cColor& GetColorMul()", asMETHODPR(aClass, GetColorMul, (), const cColor&)); \
RegisterMethod("bool ClipsGraphics()", asMETHODPR(aClass, ClipsGraphics, (), bool)); \
RegisterMethod("bool GetMouseIsOver()", asMETHODPR(aClass, GetMouseIsOver, (), bool)); \
RegisterMethod("bool IsConnectedTo(iWidget@ apWidget, bool abIsStartWidget=true)", asMETHODPR(aClass, IsConnectedTo, (iWidget*, bool), bool)); \
RegisterMethod("bool IsConnectedToChildren()", asMETHODPR(aClass, IsConnectedToChildren,(), bool)); \
RegisterMethod("void SetConnectedToChildren(bool abX)", asMETHODPR(aClass, SetConnectedToChildren, (bool), void)); \
RegisterMethod("cGuiGfxElement@ GetPointerGfx()", asMETHODPR(aClass, GetPointerGfx, (), cGuiGfxElement*)); \
RegisterMethod("void SetGlobalKeyPressListener(bool abX)", asMETHODPR(aClass, SetGlobalKeyPressListener, (bool), void)); \
RegisterMethod("bool IsGlobalKeyPressListener()", asMETHODPR(aClass, IsGlobalKeyPressListener, (), bool)); \
RegisterMethod("void SetUserValue(int alX)", asMETHODPR(aClass, SetUserValue, (int), void)); \
RegisterMethod("int GetUserValue()", asMETHODPR(aClass, GetUserValue, (), int)); \
RegisterMethod("void SetCallbacksDisabled(bool abX)", asMETHODPR(aClass, SetCallbacksDisabled, (bool), void)); \
RegisterMethod("bool GetCallbacksDisabled()", asMETHODPR(aClass, GetCallbacksDisabled, (), bool)); \
RegisterMethod("void SetFocusNavigation(eUIArrow aDir, iWidget@ apWidget)", asMETHODPR(aClass, SetFocusNavigation, (eUIArrow, iWidget*), void)); \
RegisterMethod("iWidget@ GetFocusNavigation(eUIArrow aDir)", asMETHODPR(aClass, GetFocusNavigation, (eUIArrow), iWidget*)); \
RegisterMethod("bool HasFocusNavigation()", asMETHODPR(aClass, HasFocusNavigation, (), bool)); \
RegisterMethod("void SetGlobalUIInputListener(bool abX)", asMETHODPR(aClass, SetGlobalUIInputListener, (bool), void)); \
RegisterMethod("bool IsGlobalUIInputListener()", asMETHODPR(aClass, IsGlobalUIInputListener, (), bool));[/source]

RegisterMethod is a wrapper that registers the method.
mpEngine is a instance of asIScriptEngine

[source]void iScriptRegisterAS::RegisterMethod(const tString& asDecl, const asSFuncPtr& aFunc)
{
int lRet = mpEngine->RegisterObjectMethod(msCurrentName.c_str(), asDecl.c_str(), aFunc, asCALL_THISCALL);
if(CheckHasErrorMessage(lRet))
{
Error("Could not register method '%s' in type '%s'. Error code: '%s'\n",asDecl.c_str(), msCurrentName.c_str(), ScriptCodeToStringAs(lRet).c_str());
mpLowLevelScript->CheckAndPrintScriptOutput();
}
else
{
if(mpCurrentClass) mpCurrentClass->AddMethod(asDecl);
}
}[/source]

Each class then registers its methods using:

[source]
///////////////////////
// Window
RegisterType("cWidgetWindow", 0, asOBJ_REF);
kRegisterScriptableSetup_EmptyRefMangers(cWidgetWindow);
kRegisterCastFunction(iWidget, cWidgetWindow);
kRegisterWidgetMethods(cWidgetWindow);
RegisterMethod("void SetStatic(bool abX)", asMETHOD(cWidgetWindow, SetStatic));
RegisterMethod("bool GetStatic()", asMETHOD(cWidgetWindow, GetStatic));
RegisterMethod("void SetDrawLabel(bool abX)", asMETHOD(cWidgetWindow, SetDrawLabel));
RegisterMethod("void SetCloseButtonDisablesWindow(bool abX)", asMETHOD(cWidgetWindow, SetCloseButtonDisablesWindow));
RegisterMethod("bool GetCloseButtonDisablesWindow()", asMETHOD(cWidgetWindow, GetCloseButtonDisablesWindow));
RegisterMethod("void SetEscapeKeyClosesWindow(bool abX)", asMETHOD(cWidgetWindow, SetEscapeKeyClosesWindow));
RegisterMethod("bool GetEscapeKeyClosesWindow()", asMETHOD(cWidgetWindow, GetEscapeKeyClosesWindow));[/source]

kRegisterCastFunction just sets up type casting and kRegisterScriptableSetup_EmptyRefMangers handles AddRef

[source]#define kRegisterScriptableSetup_EmptyRefMangers(aClass) \
RegisterRefMangersFunc(aClass::aClass##_Scriptable_EmptyAddRef, aClass::aClass##_Scriptable_EmptyRelease); \
RegisterGetScriptableBaseClass(ScriptReferenceToScriptableBaseClass<aClass>); \

//--------------------------------------------------------------------------------

void iScriptRegisterAS::RegisterRefMangersFunc(void *apFuncAddRef, void *apFuncRelease)
{
int lRet = mpEngine->RegisterObjectBehaviour(msCurrentName.c_str(), asBEHAVE_ADDREF,"void f()", asFUNCTION(apFuncAddRef), asCALL_CDECL_OBJFIRST);
if(CheckHasErrorMessage(lRet))
{
Error("Could not register AddRef function for type '%s'. Error code: '%s'\n", msCurrentName.c_str(), ScriptCodeToStringAs(lRet).c_str());
mpLowLevelScript->CheckAndPrintScriptOutput();
}
lRet = mpEngine->RegisterObjectBehaviour(msCurrentName.c_str(), asBEHAVE_RELEASE,"void f()", asFUNCTION(apFuncRelease), asCALL_CDECL_OBJFIRST);
if(CheckHasErrorMessage(lRet))
{
Error("Could not register Release function for type '%s'. Error code: '%s'\n", msCurrentName.c_str(), ScriptCodeToStringAs(lRet).c_str());
mpLowLevelScript->CheckAndPrintScriptOutput();
}
}

//--------------------------------------------------------------------------------

void iScriptRegisterAS::RegisterGetScriptableBaseClass(tScriptableBaseClassFromRawDataFunc apFunction)
{
mpCurrentClass->SetScriptableBaseClassFromRawDataFunc(apFunction);
}[/source]

Share this post


Link to post
Share on other sites
Advertisement
This is a classic case where templates cause a problem. Each asMETHODPR will produce a unique template instance with a tiny function to build the asSFuncPtr structure properly for that specific class and method.

In your case I counted around 1750 such functions (70 methods * 25 classes), although all the functions are small and practically identical the compiler still needs to optimize each of them individually.

My suggestion is that you disable optimizations for this specific file. There is not much use in optimizing this code anyway, since it will probably only be executed once at startup.

Regards,
Andreas

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

Participate in the game development conversation and more when you create an account on GameDev.net!

Sign me up!