3

I'm working on an iPhone app that uses C++ and is almost at the 100 MB mark (the point at which Apple won't let people download it via WWAN). I've taken many steps to reduce the binary size, such as removing unneeded third-party dependencies. However, the app, and in particular the binary, is still large because it has a lot of features.

I've heard that disabling RTTI can reduce the binary size. Would it be possible to turn off RTTI for some files, e.g. all files without the strings "typeid" or "dynamic_cast" in them?

meisel
  • 2,151
  • 2
  • 21
  • 38
  • 1
    RTTI doesn't have a very significant memory overhead - see https://stackoverflow.com/questions/5408106/rtti-overhead-in-c –  Sep 07 '17 at 18:37
  • Have you tried changing optimization settings from "fastest code" to "smallest code"? – tadman Sep 07 '17 at 18:41
  • 1
    Ask the linker to make a map file and see where all the space is going. – Richard Critten Sep 07 '17 at 18:42
  • You would need to compile without RTTI **and** without exceptions, since exception handling implies RTTI, even for classes that are never thrown... and that's for the whole program, not just selected parts :( – Damon Sep 07 '17 at 18:44
  • It is possible to turn RTTI off for some files. But that is not a good idea because you may end up in messed up code situation. If use of third party libraries does not demand presence of RTTI you could disable it for entire executable or not touch it at all. – user7860670 Sep 07 '17 at 18:47
  • 1
    @Damon Not necessarily - https://stackoverflow.com/questions/10320072/is-there-a-relation-between-rtti-and-exceptions –  Sep 07 '17 at 18:48
  • 1
    @Damon Even though exception handling does use RTTI disabling RTTI and disabling exceptions are typically controlled separately. Using `-fno-rtti` for example won't interfere with exceptions. – user7860670 Sep 07 '17 at 18:48
  • Might be a moot question, but are you using any optimization flags? – txtechhelp Sep 07 '17 at 18:48
  • Use of typeid and dynamic_cast denotes bad design anyway in most cases, so the best would be to get rid of it completely and design the application properly (that's what polymorphism is for, to not have to know the actual type in the first place) and to disable RTTI completely. And AFAIK exceptions work without RTTI enabled just fine. – EmDroid Sep 07 '17 at 18:59
  • The space overhead is proportional to the number of classes with virtual methods, but is _very_ small per class (essentially a few pointers + a string constant for the type name). Your 100Mb binary would need to have thousand of classes - maybe tens of thousands - with virtual methods (n.b. classes not instances) before the RTTI space overhead would reach 1% of your binary size. You need to look elsewhere for your space reduction. – davidbak Sep 07 '17 at 19:07
  • Are you by any chance making every destructor `virtual`? Even if the class isn't actually used polymorphically? Only polymorphic classes have RTTI, – MSalters Sep 07 '17 at 21:41

1 Answers1

3

The space cost of RTTI is not associated with using it (via typeid or dynamic_cast), but of the type information associated with each class. Thus the benefit would be to disable RTTI for individual classes (or groups of classes).

I know no such way to do that.

You might find that if you can reduce the number of classes with virtual functions, you can reduce the amount of RTTI information. (For example, not all base classes need to have a virtual destructor - you only need that if you might call delete pBase.)

The other thing that can blow up executable size, is lots of templates. In many cases you can make template functions which just forward to non-template functions to do the real work.

  • Couldn't you disable it for a single .cpp by passing the -fno-rtti flag for compilation? – meisel Sep 07 '17 at 18:45
  • 1
    @meisel. Consider you have a.h which defines class A, and a.cpp which defines its member functions. Similarly b.h and b.cpp (which includes a.h). The problem is that firstly, I would not be surprised if the class A which a.cpp had defined members for was not compatible with the class A which b.cpp was using. Secondly, I would not be surprised to find that b.cpp caused the creation of a typeinfo object for A anyway. – Martin Bonner supports Monica Sep 07 '17 at 18:50