12

Scenario: We have an XCode project for an iOS game which has about 7000+ files.

Only 1000+ files are code. Rest of them are images, sounds, level data, XIBs, plists, config files etc.

Its a universal app so, we have separate set of resources for old iPhone, retina iPhone, iPad etc. We also have PNG and PVRTC for few things like BG images etc to make the best use of different hardware.

Problem:

Right now the project takes about

42 seconds to Clean (Cmd - Shift - K)

8.3 minutes for a full rebuild (Cmd - B) (While rebuilding, half of the progress bar fills in 1 min)

aaaand... 5 mins 36 for just running (Cmd - R) ??

After that, I pressed "Stop" and clicked on "Run" again without doing absolutely anything else. and it took 2 mins 40 secs to just "Run again"

I also saw resources getting copied again, some files getting built again as shown by XCode above the progress bar.

Any solutions to reduce time in any of these phases is highly appreciated. Please ?

P.S. The project was started during the XCode 3 days, and we have been automatically updating the xcodeproj file each time a new XCode comes out.

  • I am not looking for a magic button. But as XCode doesn't give me any information during the compile/build phase, I am looking for solutions like - is there a verbose mode I can switch on?, do command line build help me troubleshoot why it takes so long? and so on – Rajavanya Subramaniyan Jan 22 '13 at 13:40
  • Do you have any update for us, regarding which build phases are the most expensive ones according to the build log? – Mecki Jan 29 '13 at 09:30
  • @Mecki thanks a lot for your direction! I did manage to figure out a few steps to reduce the build/run time by half or 1/3rd. 1) Validating the product was taking awfully long time. Someone had set validate built product 'ON' in the target settings. I switched it off. (Atleast for 'Debug' for now) 2) Found that dSYM file generation was taking a while too. So followed this question - http://stackoverflow.com/q/8454937/121067 3) Also there were way too many warnings (1000+) in the entire project due to careless coding practices. Just turned off many of them manually. – Rajavanya Subramaniyan Jan 30 '13 at 06:43
  • Right only Codesign phase takes a while when I run each time (Not during complete rebuild). But I'm guessing there isn't a way to turn it off if I have to test it on the device. – Rajavanya Subramaniyan Jan 30 '13 at 06:45
  • I know I'm being greedy here, but any ways to reduce even that 'codesigning' time ? :D – Rajavanya Subramaniyan Jan 31 '13 at 10:25

2 Answers2

7

What you are looking for is improving your compile and launch time for debug, right? So what about creating a different target for every platform? So you keep the same code but only package a subset of resources for debug purpose depending on your debug device.

To do this, go on your actual target, right click and duplicate. Keep your actual target untouched, it's the fat one! For the new target, let's say it's iPad retina, go to "build phases" -> "copy bundle resources" and remove all the resources which are not related to iPad Retina. Do the same for every platform.

Then on top left of Xcode, select the good target for the specific device. Maybe, you can define which device is accepted for a target.

If you use continuous integration, let your build machine compile the fat target at night.

Geraud.ch
  • 1,499
  • 10
  • 15
  • 1
    Why would he need a different target per platform? You can just tell Xcode to build only for your current platform when starting the target in a debugger (this is default BTW), so Xcode will not really build for all the platforms unless you do a deployment build. Also your suggestion only influences compile time and the questioner said that compile is only 1 of those 8+ minutes. Even if you could make the compile instant, he still has to wait 7 minutes. – Mecki Jan 22 '13 at 11:09
  • Nope, with a different target, you can say that you don't want iPhone retina resources in the app sent to your iPad retina device. The ipa will be smaller so quicker to upload to your iPad. The key here is **resources** – Geraud.ch Jan 22 '13 at 11:17
  • This is only the case, if there are different resources for retina and non-retina devices, which may not be the case. E.g. to save space, all images may only exist in retina quality and get downscaled on load or even when being drawn. Especially for OpenGL games, where most resources are loaded as texture, it is not uncommon to only have one set of textures for both devices (retina textures often buy you little to nothing, further OpenGL can be used to downscale textures on the GPU in almost no time). – Mecki Jan 22 '13 at 11:27
  • 1
    I agree Mecki but according to QuakeBoy:"Its a universal app so, we have separate set of resources for old iPhone, retina iPhone, iPad etc. We also have PNG and PVRTC for few things like BG images etc to make the best use of different hardware." That's the point I tried to solve – Geraud.ch Jan 22 '13 at 11:57
  • I would still not use multiple targets, because then you need to keep three resource copy phases in sync: The one of the retina target, the one of the non-retina target and the one of the old target. This can be rather troublesome with hundreds of resources. In that case I would rather throw out the copy phase completely and replace it by a shell script phase. All active resources are placed in a specific sub folder and the script figures out on its own which files it must copy from there depending on the current build variant and target device. – Mecki Jan 22 '13 at 14:25
  • 1
    Maybe the implementation is not perfect but it's worth only sending resources needed for the specific debug device. – Geraud.ch Jan 22 '13 at 14:40
  • @Geraud.ch, thanks for the answer, I appreciate it, this method would definitely be effective for universal apps in the future and I will keep it in mind to follow it. But I doubt I might be able to do this in the project right now due to its "complex" state. It was a nightmare trying to even remove unused resources. – Rajavanya Subramaniyan Jan 30 '13 at 06:50
6

It is not possible to solve a problem if the cause for the problem is unknown. "My car does not start any longer, is there a way to make it start again?"; most likely, but only if the reason why it currently refuses start is known. It sounds a bit like you hope that there is a magic switch in Xcode named "Build fast" and by enabling it, everything becomes much faster. If there was such a switch, don't you think it would be enabled by default? Don't you think it would actually always be enabled?

I also wonder why you tagged this question with "compiler" and "compiler-optimization". According to your own statement, compiling takes only one minute out of 8.3 minutes build time, so how would further reducing compile time make the overall process much faster? Even if compile time was cut down to zero, this would still leave you with 7.3 minutes build time. Don't optimize at the wrong end.

It's like optimizing code. If your code is too slow, all optimizations are pointless if you don't where in your code most of your time is spent. Optimizing a piece of code to run ten times faster will do nothing for overall performance if only 0.1% of all time is spent in that piece of code. The first step of code optimization is profiling code and finding out how much time is spent at what piece of code.

So to make your build process faster, the first and most important step is finding out why exactly the build times are slow right now. Without that knowledge, all answers people could give here are just guessing into the blue. Once you know exactly where the problem is, you can come back and ask precisely how to make this one step faster. You start by optimizing the slowest step, then the second slowest, and so on.

Take a look at the build log in Xcode

enter image description here

Make sure to select "All Messages", otherwise you will only see warnings and errors, or only errors. Now start a clean build, select the new log that pops up to the left and keep monitoring this log. You will exactly see when Xcode is starting an operation and when it approaches to the next operation. That should give you a first impression which of the tasks take rather long to complete. And once you told us which tasks those are, we can start making suggestion how you might possibly be able to make this task somewhat faster.

Mecki
  • 125,244
  • 33
  • 244
  • 253
  • Cool, thanks for the Compile log thing. I was in fact looking for ways in which I can figure out in which phases, the compiler takes more time. I will run it and let you know. – Rajavanya Subramaniyan Jan 22 '13 at 13:35
  • 2
    -1. The last two paragraphs are useful, the rest comes across to me as rude and condesending. – TarkaDaal Jan 29 '13 at 09:48
  • 2
    @TarkaDaal Yeah, it would of course be less rude if I had just closed this question, like most people do if the question does not contain enough information to even be solved. I rather prefer to educate people to ask good questions in the future, since it will help them to getter better answer and to get those faster. The OP didn't consider it rude and I rather consider your comment very rude. – Mecki Jan 29 '13 at 11:54