Results 1 to 8 of 8
  1. #1
    Skiller is offline Member
    Join Date
    Jan 2011
    Posts
    67
    Rep Power
    0

    Default Avoiding allocations

    I've come from a c++ game development background so I'm used to writing extremely efficient code with no heap allocations outside of load times but am having trouble avoiding heap allocations in an Android game I'm working on that's being written in Java.

    Basically it comes down to this, I have a Vector class:
    Java Code:
    public class Vector2D
    {
        public float x = 0.0f;
        public float y = 0.0f;
    }
    And some function that requires a temporary instance of the class, something like the following:
    Java Code:
    public void Swaparoo(Vector2D v1, Vector2D v2)
    {
        Vector2D tempVector = new Vector2D();
        tempVector.x = v1.x;
        tempVector.y = v1.y;
        v1.x = v2.y;
        v1.y = v2.x;
        v2.x = tempVector.y;
        v2.y = tempVector.x;
    }
    In C++ I can just use a local variable allocated from the stack but is there a way in Java to use an instance of a class without needing to allocate from the heap? Or at least a way to create it in a way that the GC wont need to free it.

    If not classes then what about fixed size arrays of primitive types like float or int?


    Also is there a way to return an instance of a class without allocating from the heap for something like the following:
    Java Code:
    public static Vector2D Add(Vector2D v1, Vector2D v2)
    {
    	return new Vector2D(v1.x + v2.x, v1.y + v2.y);
    }
    Though obviously this isn't as important as I could just pass in a third Vector2D that receives the new values, but it'd be much cleaner and more easily understood if I was able to use the return value.

  2. #2
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,651
    Blog Entries
    7
    Rep Power
    21

    Default

    Quote Originally Posted by Skiller View Post
    I've come from a c++ game development background so I'm used to writing extremely efficient code with no heap allocations outside of load times but am having trouble avoiding heap allocations in an Android game I'm working on that's being written in Java.
    Java (unlike C++) stores all objects on the heap and can only be created using the 'new' operator. In C++ allocating memory is quite a job: it searches lists and allocates memory using some fitting strategy (all to avoid memory fragmentation). Not so in Java: memory allocation isn't much more than a pointer addition. The garbage collector takes care of the rest.

    In general trying to avoid the creation of new objects obfuscates and complicates your code: don't do it, i.e. create new objects whenever you need them. On a small device you can use public data members (so you don't need methods to get/set them) but, as always, beware of premature optimizations.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  3. #3
    Skiller is offline Member
    Join Date
    Jan 2011
    Posts
    67
    Rep Power
    0

    Default

    Quote Originally Posted by JosAH View Post
    Java (unlike C++) stores all objects on the heap and can only be created using the 'new' operator.
    Bugger, might have to ignore thread safety and add a couple of private static variables to use then :(. Or use additional member variables on classes with fewer instances, though it's annoying as I've already had a few memory issues due to Java class bloat, though fortunately not in this app (yet).

    Quote Originally Posted by JosAH View Post
    In C++ allocating memory is quite a job: it searches lists and allocates memory using some fitting strategy (all to avoid memory fragmentation). Not so in Java: memory allocation isn't much more than a pointer addition. The garbage collector takes care of the rest.
    I noticed the allocations were quite quick and was quite pleased with that until I noticed the much more problematic downside of the garbage collection hit. GC is quite slow, seems more so than C++ allocations, and worse it does a lot at once rather than spreading the load more evenly so you can get big "hiccups" when GC happens, as opposed to C++ where it's still a smooth frame rate but just a lower rate than without the allocations.

    Quote Originally Posted by JosAH View Post
    In general trying to avoid the creation of new objects obfuscates and complicates your code: don't do it, i.e. create new objects whenever you need them. On a small device you can use public data members (so you don't need methods to get/set them) but, as always, beware of premature optimizations.
    Yer I've been using a lot of public members instead of getters and setters already because of that, and I do try to write easy to read code, but the main problem is that sometimes I need to create a new instance of a class for use only during a single instance of a function, a function that more often than not needs to be run as much as 100-500 times per frame (so many thousands of times per second), but if I allocate it from the heap I know that at some point a little later I'm going to get a small frame rate hiccup when the GC runs :(. I miss stack variables :(

  4. #4
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,651
    Blog Entries
    7
    Rep Power
    21

    Default

    Quote Originally Posted by Skiller View Post
    Yer I've been using a lot of public members instead of getters and setters already because of that, and I do try to write easy to read code, but the main problem is that sometimes I need to create a new instance of a class for use only during a single instance of a function, a function that more often than not needs to be run as much as 100-500 times per frame (so many thousands of times per second), but if I allocate it from the heap I know that at some point a little later I'm going to get a small frame rate hiccup when the GC runs :(. I miss stack variables :(
    For those situations you can pre-allocate the objects and reuse them over and over again; Java does have 'stack variables' but they have to be primitives (e.g. int or double). Your original swap example could be coded like this:

    Java Code:
    void swap(Vector2D v1, Vector2D v2) {
       float t;
       t= v1.x; v1.x= v2.x; v2.x= t;
       t= v1.y; v1.y= v2.y; v2.y= t;
    }
    The local variable t only exists on the stack; no heap allocation was necessary. b.t.w. I don't understand your remark about thread safety; heap allocations (i.e. object creations) are thread safe.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  5. #5
    Skiller is offline Member
    Join Date
    Jan 2011
    Posts
    67
    Rep Power
    0

    Default

    Quote Originally Posted by JosAH View Post
    For those situations you can pre-allocate the objects and reuse them over and over again; Java does have 'stack variables' but they have to be primitives (e.g. int or double). Your original swap example could be coded like this:

    *snip*

    The local variable t only exists on the stack; no heap allocation was necessary. b.t.w. I don't understand your remark about thread safety; heap allocations (i.e. object creations) are thread safe.
    Yer I figured I'd be able to do that in simple situations like that, but in my matrix class there are functions that require the 16 temporary floats, used in the function to represent a temporary matrix, be an actual matrix so it can then be passed to the multiply function of the matrix (which also need 16 temporary floats) to get the final result. So short of copy/pasting the multiply function code into each of those functions and having 32 temporary floats in each of those functions or changing the multiply function to accept 16 individual float parameters, pre-allocating the objects into static variables is really the only option as it could get quite unreadable with so many temporary variables.

    The problem with that is that it isn't thread safe because if 2 threads are both in the same function they will both use the exact same variables and mess up each others results as they could be changed when they are not expected to be changed.

    Just to be sure, there's no way to have an array of primitives on the stack is there? Or is an array considered an object too?

  6. #6
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,651
    Blog Entries
    7
    Rep Power
    21

    Default

    Quote Originally Posted by Skiller View Post
    Yer I figured I'd be able to do that in simple situations like that, but in my matrix class there are functions that require the 16 temporary floats, used in the function to represent a temporary matrix, be an actual matrix so it can then be passed to the multiply function of the matrix (which also need 16 temporary floats) to get the final result. So short of copy/pasting the multiply function code into each of those functions and having 32 temporary floats in each of those functions or changing the multiply function to accept 16 individual float parameters, pre-allocating the objects into static variables is really the only option as it could get quite unreadable with so many temporary variables.

    The problem with that is that it isn't thread safe because if 2 threads are both in the same function they will both use the exact same variables and mess up each others results as they could be changed when they are not expected to be changed.

    Just to be sure, there's no way to have an array of primitives on the stack is there? Or is an array considered an object too?
    There's also the ThreadLocal class (read the API documentation); such an object only exists in a single Thread. That's where you can store your pre-allocated objects. And yes, an aray is considered an object too and so it lives on the heap.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

  7. #7
    Skiller is offline Member
    Join Date
    Jan 2011
    Posts
    67
    Rep Power
    0

    Default

    Quote Originally Posted by JosAH View Post
    There's also the ThreadLocal class (read the API documentation); such an object only exists in a single Thread. That's where you can store your pre-allocated objects. And yes, an aray is considered an object too and so it lives on the heap.
    Ahh awesome, I'll look into that as it sounds like it'll prevent the thread safety issues I thought I'd have, thanks :)

  8. #8
    JosAH's Avatar
    JosAH is online now Moderator
    Join Date
    Sep 2008
    Location
    Voorschoten, the Netherlands
    Posts
    13,651
    Blog Entries
    7
    Rep Power
    21

    Default

    Quote Originally Posted by Skiller View Post
    Ahh awesome, I'll look into that as it sounds like it'll prevent the thread safety issues I thought I'd have, thanks :)
    Yep, it's a fun little object but skip the example in the API documentation though; it is convoluted and especially confusing.

    kind regards,

    Jos
    cenosillicaphobia: the fear for an empty beer glass

Similar Threads

  1. Replies: 9
    Last Post: 01-24-2011, 12:17 PM
  2. avoiding memory over-consuming
    By itaipee in forum New To Java
    Replies: 4
    Last Post: 12-14-2009, 11:59 AM
  3. Avoiding system.exit()
    By swati.jyoti in forum New To Java
    Replies: 5
    Last Post: 07-01-2009, 10:17 AM
  4. Avoiding refresh
    By java_srinivasan in forum JavaServer Pages (JSP) and JSTL
    Replies: 0
    Last Post: 06-25-2008, 09:01 AM
  5. avoiding if statements
    By valoyivd in forum New To Java
    Replies: 1
    Last Post: 04-02-2008, 09:08 AM

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •