Long loading time under MacOS when multithreading
Community Forums/General Help/Long loading time under MacOS when multithreading
| ||
I am working at a new game and until now I tested only on Windows. I recently bought myself a Macbook and I wanted to give it a try. I observed I have a very long loading time for my menu. Right now the menu is made from 2-3 pictures and I stay up to 20-30 seconds.. This is my main game code: (deleted some irrelevant code) Type TGame Field imageTitleScreen:TImage Field LoadingThread:TThread Field myLogo:TLogo Global myMenu:TMainMenu Global myScene:TScene Method debugPrint(pString:String) If Globals.isDebug = 1 Print pString End If EndMethod '#region Loading and Setup Game Function threadLoadMainMenu:Object(Data:Object) myMenu.loadGraphics() End Function '#endregion Method initGame() myLogo = New TLogo myLogo.init(MilliSecs()) myMenu = New TMainMenu myMenu.init() myScene = New TScene myScene.init() imageTitleScreen = LoadImage("graphics/titleScreen.jpg") End Method Method updateGame(gameTime:Float) If Globals.appStatus = STATUS_LOGO myLogo.updateLogo(gameTime) If myLogo.status = 6 switchGameState(STATUS_TITLESCREEN) ElseIf Globals.appStatus = STATUS_TITLESCREEN If myMenu.threadSafe = 1 If MouseDown(1) switchGameState(STATUS_MENU) End If End If ElseIf Globals.appStatus = STATUS_MENU myMenu.update() checkMainMenuResponses() ElseIf Globals.appStatus = STATUS_GAME myScene.update() End If End Method Method renderGame(gameTime:Float) If Globals.appStatus = STATUS_LOGO myLogo.renderLogo() ElseIf Globals.appStatus = STATUS_TITLESCREEN If LoadingThread If ThreadRunning(LoadingThread) DrawImage(imageTitleScreen, 0, 0) DrawText "Loading Main Menu (in another thread)", 10, 10 Else LoadingThread = Null EndIf Else DrawImage(imageTitleScreen, 0, 0) DrawText "Click anywhere to continue...", 10, 10 End If ElseIf Globals.appStatus = STATUS_MENU myMenu.render() ElseIf Globals.appStatus = STATUS_GAME myScene.render() End If DrawText(gameTime, 10, 20) End Method Method switchGameState(pNewState:Int) Globals.appStatus = pNewState If pNewState = STATUS_TITLESCREEN LoadingThread = CreateThread(threadLoadMainMenu, Null) debugPrint("TGame->switchGameState: STATUS_TITLESCREEN") ElseIf pNewState = STATUS_MENU myMenu.swithMenuState(MENU_STATUS_MAIN) debugPrint("TGame->switchGameState: STATUS_MENU") ElseIf pNewState = STATUS_GAME 'myMenu.swithMenuState(MENU_STATUS_MAIN) debugPrint("TGame->switchGameState: STATUS_GAME") End If End Method Method checkMainMenuResponses() If myMenu.responseMustStartGame = 1 myScene.reset() myScene.LoadScene() myScene.loadGraphics() switchGameState(STATUS_GAME) End If End Method End Type If I am not using multithread then the loading is fast as on Windows OS. Where is my mistake? |
| ||
shouldn't be any different as far as I can see. I'm willing to compile and test here if you want? (mavericks, mac mini) |
| ||
Ok, I will share this with you guys: http://rvlgames.com/beta2/testBuild.zip When the mainmenu is loaded in the top left corner will be printed: Loading Main Menu graphics in another thread. i tested it on maverick |
| ||
no problem. Initial test runs it very fast with no pauses for loading. would you like me to do a full debug and suggest changes to make more mac friendly? |
| ||
sure, but i cannot understand why here is not working fine... |
| ||
ok first a couple of coding changes - mac doesn't use 'esc', also better to use a timer for your loop so you can multitask better. Here's the code for that with a fps of 50 :) main.bmx/main game loop: Local AppQuit:Int = False Local GameTime:Int Local AppQueue:Int Local TimeEvent:TTimer = CreateTimer(50) While Not(AppQuit) GameTime = MilliSecs() AppQueue = PollEvent() If AppQueue = 0 Then Delay(2) Else Select EventID() Case EVENT_APPTERMINATE, EVENT_WINDOWCLOSE AppQuit = True Case EVENT_TIMERTICK GameTime = MilliSecs() Cls myGame.updateGame(GameTime) myGame.renderGame(GameTime) Flip end Select End If Wend - quick mod to stop fullscreen and use a window (better for debugging) main.bmx/setupGraphics: Globals.mySettings.videoWidth = 960'DesktopWidth() Globals.mySettings.videoHeight = 640'DesktopHeight() quick scan of game code, here is a code suggestion. replace multiple if then with select game.bmx/renderloop Select status Case 0, 1, 2 DrawImage (logo1, 0, 0) Case 3, 4, 5 DrawImage (logo2, 0, 0) End Select on to the thread pause issue. work fine here, so I would suggest running in a window and putting print "start procedure name" print "end procedure name" into main parts and watch the output window - that way you can see where the code has stalled |
| ||
Thanks for the tips: I put some additional Prints in my program. You have the code so here it is what is strange: game.bmx -> Function threadLoadMainMenu this is my code here: Function threadLoadMainMenu:Object(Data:Object) Print "start 1" myMenu.loadGraphics() Print "finish 1" End Function I have a very big time here between "start 1" and "finish 1". BUT the myMenu.loadGraphics() it's starting very hard. (I also put prints there and all the graphic are loaded instantaneously) Now, in the Game.bmx: swithGameState() I have this code: Globals.appStatus = pNewState If pNewState = STATUS_TITLESCREEN LoadingThread = CreateThread(threadLoadMainMenu, Null) Print("TGame->switchGameState: STATUS_TITLESCREEN") Else If . . . If I leave that Print there in my debug window I will have: TGasmtea-rts w1tc finish 1 so instead of "start 1", my print functions are one in the other.. I think here is something wrong. o.O again, If I am not using multithread then the loading is fast as on Windows OS. |
| ||
Any new thoughts guys?? |
| ||
I'll have a look see :) mmm, first off in myMenu.loadGraphics() you have profile loading code. in the copy I have here, this is commented out. have you done the same on your machine and checked it? If so (commented out) and there is no delay, then the pause is in the profile loading (I have no pause here with just the image loading) I've uncommented the load profile code, and still no pause. ok. one thing. you have a set of loading screens that pause for a certain amount of time. And these happen only once. If you can't find a way around it, why not split the loadGraphics() amongst these. that way if there is a pause, it will be absorbed ? |
| ||
Hi again Adam, As I said earlier in the myMenu.loadGraphics() method, everything is super fast. If I put a Print at the start of the method and another one at the end of it, both debugs will be printed almost same time. The problem is that the myMenu.loadGraphics() is starting VERY HARD. the profile code is commented cause i doen some tests. runs the same because i said earlier the loadGraphcis itself is fast. also, u asked me why cant me load the graphics while in logos. well, i want to load them after these logos while a Title Screen will be shon. anyway I want to understand were is my mistake and why u ran the app with no issues and here i have all these problems. again, if i do not use multithreading the loading is super fast as on Windows. as you can see in my previous post it seems that switchGameState is called several times while starting the thread LoadMainMenu.. that;s why I have my print output combined.... |
| ||
myMenu.loadGraphics() is starting VERY HARD. I've got my stupid head on there. I don't understand what you mean? I think you mean late?? ok, here's a question for you. what spec is your processor? Mine is a dual core with hyper threading (in effect, 4 cpus) - you can check this by running Application > Utilities > Activity monitor - the amount of CPu's will be shown on the App bar If you have 2 or 1, then the pause may be to do with having too many threads? Threading is the one thing that is incredibly difficult to debug. |
| ||
"I think you mean late??" -> Yes. I have a i5 Haswell 2.4 Ghz In the Activity Monitor I have 7-8 threads Another strange thing. I put a DebugStop here: If pNewState = STATUS_TITLESCREEN LoadingThread = CreateThread(threadLoadMainMenu, Null) DebugStop Print("TGame->switchGameState: STATUS_TITLESCREEN") Else If . . Well, in this case runs smoothly. I mean, as soon as the logos disappear, the loading menu thread is starting, the app stops (but the graphics are loaded). i just click to resume and it's ok.. :| |
| ||
mmm, sounds like some form of race condition where the main threads waiting for other threads to catch up. the debugstop is interesting though. have you grid replacing it with a delay()? say delay(1000) - 1 second delay. and see what happens? delay will give some time back to the system... |
| ||
the delay trick made it run good.. :D what is happen exactly? |
| ||
Hey, brilliant :) interesting that it worked so well. Here's my thought; requesting a thread is a low level system operation, so giving some time back to the system allowed it to do its work and tell blitz it had done it. :) |