0

I have a class that have multiple instance variables. I want to achieve two purposes with the class. It's possible that I may only use some variables for one purpose and sometime use both.

Here's a more concrete example. I want to create a class that every time the user tap the screen, a dog sprite and cat sprite appear with an animation. If tapped again, they continue to perform different animation. However, sometime I only want the dog sprite to appear and update. And some other rare times, I want the cat sprite to appear after a couple of taps after the dog sprite appeared.

The question is: does instance variable allocate too much memory? I'm highly concerned with performance, because I'm planning to make a memory-intensive game. Since it's hard to predict when I actually use all the instance variable, should I divide them into two classes? Let's divide the possible scenarios to get a better idea.

  1. Only the Dog Sprite is used and the cat sprite never appears : The cat's instance variable is left untouched if left in one class.

  2. The dog sprite appear first, then the cat sprite appear later : Both sprite will eventually appear. It's possible to divide it into two classes, but some methods are duplicated since methods such as the touch advance logic and animation are similar. But if we leave it in once class, scenario 1 could occur, which could possibly be solve without a lot of duplicate code being reproduced.

Other things could occur, but the problems is already discussed above. These are the pro and con from my point of view:

  1. One Class Approach

    • Pro
    • Avoid some duplicate logic
    • No need to import multiple header that leads to some similar instance variable

    • Con

    • Possibly leave half of instance variables unused (including NSString, CCSprite, a lot of integers and floats, CCAnimation, CCLabelBMFont)
  2. Two Class Approach

    • Pro
    • Less instance variables
    • Possibly inherit from the class without inheriting some unnecessary variables in the future

    • Con

    • Some logic are reproduced

It's difficult to decide which option I should use. Any suggestions would be great! Thank you in advance!

if (didHelp) 
   for (int x = 0; x < 100; x++)
      NSLog(@"Thanks!");
  • If you think iVars are a throttle in performance, try writing some SQL queries. Heap and Stack memory for objects and primitives are by no means a bottleneck in any program, it's all in how you use them. – CodaFi Mar 22 '13 at 23:39
  • 1
    Unless you have thousands of instances of this class, a few unused instance variables will be of no concern at all. A single icon image will use more memory than the unused ivars of hundreds of instances of this class. You are worrying about an optimization long before you know there is an actual issue. – rmaddy Mar 22 '13 at 23:39
  • @rmaddy I have exactly 22 iVar that is left unused if I only use it for one purpose. So ultimately, should I divide it into two classes for the sake of organization? And why is there a NSArray and NSMutable Array? Isn't it for organization purposes and it has less instance variable? – EmbodiedDarkness Mar 22 '13 at 23:44
  • 1
    Split your class into two because it is a better, more logical design. Don't do it because you feel that a few bytes of memory are being wasted. Please read the docs for `NSArray` and `NSMutableArray`. It will become quite clear what the difference is. – rmaddy Mar 22 '13 at 23:48
  • 1
    @rmaddy (**if you really want to do it** but for few hundred bytes I don't think it's the case) you should put all variables inside **two separated classes** used as _entities_ (data only). Inside your _main_ class you'll create an instance only of what you'll use (and when you'll need it). You'll _waste_ just few bytes if one of them will be unused. By the way...why don't you put everything in common inside a **base class** and you instance ClassA for case A and ClassB for case B? That's what inheritance is for. – Adriano Repetti Mar 22 '13 at 23:48
  • @Adriano Why did you reply to me? I would think your comment should be addressed to the OP. – rmaddy Mar 22 '13 at 23:50
  • @Adriano I considered a base class at one point, but only the logic relates. I'm not sure if it falls under IT-HAS or IT-IS relationship at this point. Perhaps I should use delegation? Whenever the dog sprite finish a certain requirement, it let the cat sprite know? – EmbodiedDarkness Mar 22 '13 at 23:52
  • @rmaddy sorry, message was for OP :) – Adriano Repetti Mar 22 '13 at 23:53
  • @rmaddy According to this post: http://stackoverflow.com/questions/1746204/disadvantage-of-using-nsmutablearray-vs-nsarray, there certainly is a performance difference. Please correct me I'm wrong. – EmbodiedDarkness Mar 22 '13 at 23:55
  • @EmbodiedDarkness one base class for sprites, one class for dog (IS sprite) and one for cat (IS sprite). One more class for "coordinator" (HAS one dog and/or one cat). In case one of them doesn't exist...you _waste_ 4/8 bytes. What's better to use for communication depends on real algorithm/code. Maybe a _plain_ Observer is enough (but no code so I just guess). Another point: thinking about performance of NSArray and NSMutableArray is little bit premature... – Adriano Repetti Mar 22 '13 at 23:56
  • @Adriano I like this approach, but there's one dangling problem left for me: my current class's super class is CCLayer due to various reasons. If the dog and cat inherit from the base class, that's two entirely different layers. It's no longer IT-IS, but rather IT-HAS. – EmbodiedDarkness Mar 23 '13 at 00:01
  • @EmbodiedDarkness You have two separate topics going on here. Your discussion about 1 or 2 classes and lots of ivars is one. A possible performance issue with populating a mutable array is another (and quite unrelated to the first). Please stick to one of the two for this question. – rmaddy Mar 23 '13 at 00:03
  • 1
    @EmbodiedDarkness if you want to be _formal_ just separate them: sprite and derivated classes ARE NOT CCLayer. Then you have two CCLayer (two instances of the same class) and they HAVE one sprite each one (layer delegates to them for drawing and animation your controller observes them - it doesn't know layers directly). – Adriano Repetti Mar 23 '13 at 00:07

3 Answers3

6

I'm highly concerned with performance

You and thousands of other inexperienced developers. Seriously, there are two things you're most likely going to experience:

  1. your idea is way out of proportion and no amount of performance optimization will make it work -> change your idea
  2. performance won't matter the least bit and you simply wasted time

Performance is among the least important things a game developer needs to consider at the start of a project.

Why?

Case #2 is self evident.

Assessing case #1 with reasonable accuracy before you even get started requires experience. Even then it's difficult. Simply have a backup plan if feature X proves to be too technically challenging (or impossible). If you can't assess performance, and your idea won't work with any backup plan, again you have two options:

  1. implement a different idea
  2. create a quick prototype to find out the peak performance parameters: memory usage, CPU & GPU utilization, loading times, and whatever other fitness tests seem appropriate to find out if your idea is feasible within a few days, if not hours.

does instance variable allocate too much memory?

No, and allocated memory has very little to do with performance.

You can use class_getInstanceSize to see how much memory a class instance uses. Rarely ever will a class instance use more than 500 Bytes. However, this only counts memory allocated for instance variables - not the memory the instance variables may point to. In a cocos2d app it's fair to say that 95% of your memory usage will come from textures.

It's difficult to decide which option I should use

Always strive to:

  • write readable code
  • write maintainable code
  • write less code
  • write safer code
  • write code only once (avoid duplication)
Community
  • 1
  • 1
CodeSmile
  • 64,284
  • 20
  • 132
  • 217
  • Actually I've been programming for iPhone since iOS 3.0 (or rather it was called iPhone OS 3.0 back then). This is just the BIGGEST project I've ever done. And it's just not about performance, but readability and I ALWAYS strive to maintain a class that would make it reusable -- for ease of usage. Hard code is one of my biggest pet peeve! I appreciate the for the in-depth write-up, but I can't completely accept this answer as the best. This question is too open ended, so I'll let the community choose. – EmbodiedDarkness Mar 23 '13 at 00:50
  • 1
    Programming != computer science. Btw you asked about the memory used by ivars: it's 4 bytes for 32-bit types (int, float, NSString*, id). This of course does not count the size of the object pointed to, for non-nil objects you have to add the onstance size too. – CodeSmile Mar 23 '13 at 09:59
  • Computer science is not ONLY about programming. It does not rule out the fact that it does covers it. I really have feeling you are trying to belittle me judging from your tone. Please do avoid this. – EmbodiedDarkness Mar 26 '13 at 22:31
0

EmbodiedD, You are certainly worried about too much here. The heap is going to get quite large in most applications. One simple class will be irrelevant. When you have 1000 instances of a data intensive class then you might have to start thinking about profiling. If you are worried about organization, that's another thing altogether. If you are loading classA with var1 and var2 or loading classA with var1 and class2 with var2, its more a matter of how you were taught to do abstraction.

mike628
  • 45,873
  • 18
  • 40
  • 57
0

This is a somewhat open-ended question, and there are indefinitely many ways to approach this question. Therefore, this is my approach and may or may not fit in every scenarios.

There are cases when an instance variable could be replace -- however this should not affect your decision if necessarily needed. Instance variable should be used when needed. Do not perform endless calculation just to substitute a single instance variable. Do try to limit your instance variables into variables when it is not needed outside a certain scope. Thanks to the informative users that posted on here, instance variable left unused impact performance at such a microscopic scale that you should not worry.

From my point of view, a class should only have one focus -- on function and and should pass on any other information to other class that need it. Information should remain encapsulated -- with one function to maintain reusability in other projects.

One should focus on the relationship of the function. IT-IS is the relationship that say one object should inherit another. In reality, it's like a Sienna-IS a car. A boat-IS a vehicle. Therefore, these objects should inherit any information from it's superclass. On contrast, IT-HAS say that these class contain something, usually of a quality or component, that cannot be inherited. A sienna-IS a car, but a tire-IS-NOT a sienna. Rather, a sienna-HAS a tire.

Another important relationship is delegation. The fancy definition say it perform a task on behalf of another, much like how delegates in the US represent the people of their states. Basically, it pass a certain information saying to the other class, who should in good practice, not affect the other former class. The class should not know exactly who it pass on to, but know enough to pass on certain information. This process of not knowing the exact identity of the delegate is called coupling.

In my case, of cats and dogs, delegation along with IT-IS is subjectively the best answer. Your opinion may differ. A base class should contain all the information that the Cat and Dog share. And any other information that is needed, such as the sprite's position, should be passed on as a delegate to the other class. And based on what I wrote, a class should not, in normal circumstances, programmed to do two function; for a class do one function and pass on all other dutiful needs to another.

  • it's called *de*coupling. And a car HAS tires. – CodeSmile Mar 23 '13 at 10:03
  • This is a typo. I meant sienna HAS tires. And you are correct. Just for future readers, here's a snippet from another website: "In computer science coupling is the term used to describe how much one piece of code relies on another piece of code and knowledge about the inner workings of that code to be able to use it. Decoupling is the process of separating them so that their functionality will be more self contained." – EmbodiedDarkness Mar 26 '13 at 22:28