This question already has answers here:
Objective-C. Property for C array
(4 answers)
Closed 8 years ago.
I have a custom struct for a world tile in an iOS game. I want to store multiple WorldTiles in an array but am not sure what the most efficient way is. It's an infinite-map style game and I'm loading only chunks around the player, so I want the fastest way of storing the data.
I could store this in a c-based multidimensional array (WorldTile tiles[16][16]) but I don't see a way to make it an #property for easier access outside the class, or I could wrap this using NSValue and store in an NSArray but that seems like overhead I don't need.
typedef struct {
b2Vec2 coord;
float height;
float temperature;
} WorldTile;
How can I either store the multi-dimensional array as an #property, or is the performance cost of wrapping it with an NSValue not a big deal?
I think the issue is with "overhead I don't need". Try using objects first, determine performance issues empirically, then tune your objects, then resort to C (then become surprised that the object overhead you were concerned about is not nearly as big of a deal as one would have thought in the last century).
The OO way is that the World is singular, but has a collection of things in it. That's an NSArray of Things. Those things in turn probably consist of a collection of other things, so Thing has an NSArray property of OtherThings. Multidimensionality achieved, but more importantly, object orientation achieved.
Is the world huge? It should only be built based on proximity to the player? That's fine. Things can be designed to be just stub-Things, which only know location, but initialize themselves when the user becomes proximal. You'll be much more able to understand and therefore optimize this code. In this way, the object oriented system is going to be faster because it allows you the expressive power to make a faster design without doing mental gymnastics.
Related
I am trying to squeeze every bit of efficiency out of my application I am working on.
I have a couple arrays that follow the following conditions:
They are NEVER appended to, I always calculate the index myself
The are allocated once and never change size
It would be nice if they were thread safe as long as it doesn't cost performance
Some hold primitives like floats, or unsigned ints. One of them does hold a class.
Most of these arrays at some point are passed into a glBuffer
Never cleared just overwritten
Some of the arrays individual elements are changed entirely by = others are changed by +=
I currently am using swift native arrays and am allocating them like var arr = [GLfloat](count: 999, repeatedValue: 0) however I have been reading a lot of documentation and it sounds like Swift arrays are much more abstract then a traditional C-style array. I am not even sure if they are allocated in a block or more like a linked list with bits and pieces thrown all over the place. I believe by doing the code above you cause it to allocate in a continuous block but i'm not sure.
I worry that the abstract nature of Swift arrays is something that is wasting a lot of precious processing time. As you can see by my above conditions I dont need any of the fancy appending, or safety features of Swift arrays. I just need it simple and fast.
My question is: In this scenario should I be using some other form of array? NSArray, somehow get a C-style array going, create my own data type?
Im looking into thread safety, would a different array type that was more thread safe such as NSArray be any slower?
Note that your requirements are contradictory, particularly #2 and #7. You can't operate on them with += and also say they will never change size. "I always calculate the index myself" also doesn't make sense. What else would calculate it? The requirements for things you will hand to glBuffer are radically different than the requirements for things that will hold objects.
If you construct the Array the way you say, you'll get contiguous memory. If you want to be absolutely certain that you have contiguous memory, use a ContiguousArray (but in the vast majority of cases this will give you little to no benefit while costing you complexity; there appear to be some corner cases in the current compiler that give a small advantage to ContinguousArray, but you must benchmark before assuming that's true). It's not clear what kind of "abstractness" you have in mind, but there's no secrets about how Array works. All of stdlib is open source. Go look and see if it does things you want to avoid.
For certain kinds of operations, it is possible for other types of data structures to be faster. For instance, there are cases where a dispatch_data is better and cases where a regular Data would be better and cases where you should use a ManagedBuffer to gain more control. But in general, unless you deeply know what you're doing, you can easily make things dramatically worse. There is no "is always faster" data structure that works correctly for all the kinds of uses you describe. If there were, that would just be the implementation of Array.
None of this makes sense to pursue until you've built some code and started profiling it in optimized builds to understand what's going on. It is very likely that different uses would be optimized by different kinds of data structures.
It's very strange that you ask whether you should use NSArray, since that would be wildly (orders of magnitude) slower than Array for dealing with very large collections of numbers. You definitely need to experiment with these types a bit to get a sense of their characteristics. NSArray is brilliant and extremely fast for certain problems, but not for that one.
But again, write a little code. Profile it. Look at the generated assembler. See what's happening. Watch particularly for any undesired copying or retain counting. If you see that in a specific case, then you have something to think about changing data structures over. But there's no "use this to go fast." All the trade-offs to achieve that in the general case are already in Array.
I am currently working on a Conway's Game of Life simulator for the iPhone and I had a few questions about memory management. Note that I am using ARC.
For my application, I am going to need a large amount of either C style structs or Objective-C objects to represent cells. There may be a couple thousand of these, so obviously, memory management came to mind.
Structs My argument for structs is that the cells do not need typical OO properties. The only thing that they will be holding is two BOOL values, so there will not be huge amount of memory chewed up by these cells. Also, I need to utilize a two-dimensional array. With structs, I can use the C-style 2d arrays. As far as I know, there is no replacement for this in Objective-C. I feel that it is overkill to create an object for just two boolean values.
Objective-C objects My argument (and most other people's) is that the memory management around Objective-C objects is very easy and efficient with ARC. Also, I have seen arguments that a struct is not such a big memory reduction to an object.
So, my question. Should I go with the old-school, lean, and compatible with two-dimensional array structs? Or should I stick with the typical Objective-C objects and risk the extra memory used.
Afterthoughts: If you recommend Objective-C objects, provide an alternate storage method that represents a two-dimensional array. This is critical and is one of the biggest downsides of going with Objective-C objects.
Thankyou.
"Premature optimization is the root of all evil"... If you are trying to build a Game of Life server with 100,000 users playing concurrently, memory footprint might matter. For a single-person implementation on any modern device, even a mobile one, memory size is pretty academic.
Therefore, do whatever either gets the game up and running fastest or (better) makes the code most readable and maintainable. Human cycles cost more than computer cycles. Suppose you needed a third boolean for each cell of the game... wouldn't an object you could extend save a ton of time rather than hardcoded array indices? (A struct is a lot better than an array of primitives for this reason...)
I've certainly used denser representations of data when I need to, but the overhead in programmer time has to be worth it. Just my $.02...
If it is just 2 BOOL values that you are going to store for every cell, then you could just use an array of integers to do the job. For example:
Let us assume that the two bool values are boolX and boolY, we could combine them into an int as:
int combinedBool = boolY + (10*boolX);
So you can retrieve the two bool values like:
BOOL boolX, boolY;
boolX = combinedBool/10;
boolY = combinedBool%10;
And then you can store the whole board in the form a single dimension array of integers with the index of each cell represented by ((yIndex*width)+xIndex) where width is the number of cells left-to-right on your board and, xIndex and yIndex represent the X and Y coordinates of the cell on your board.
Hope this helps with your memory management and cell organisation.
You could build one and test it's size with malloc_size(myObject). Thousands of pairs of bools will be small enough. In fact, you'll be able to make the objects larger and enjoy the benefits of the OO design. For example, what if the cells also kept pointers to their neighboring cells. The cells could compute their own t+1 state with cached access to their neighbors.
I’m working on iOS app that performs some calculations with an array of thousand objects. The objects have properties with x and y coordinates, velocity for x and y axises and couple other x-y properties. There is some math to calculate an interaction between physical objects represented by objects in the array. The math is pretty straight forward, basically it is calculation of the forces applied to the objects, speed and change in position (x,y) for each objects. I wrote a code using regular scalar math in Objective C, it worked fine on iPhone 5s, however too slow on other devices like iPhone 4, 4s, 5 and iPad mini. I found that the most time consuming operations were the calculations of the distance between 2 points and calculations of the length of a vector like shown below which involves taking a square root:
float speed = sqrtf(self.dynamic.speed_x,2)+pow(self.dynamic.speed_y,2));
So, I had to do something to make the calculations quicker. I re-wrote the code to make the properties with the coordinates of the objects and such properties as velocity which were presented by X and Y components to be vectors of GLKVector2 type. I was hoping that it would make the calculations of the variables like the distance between 2 vectors (or points, as per my understanding), addition and subtraction of vectors significantly faster due to using special vector functions like GLKVector2Distance, GLKVector2Normalize,GLKVector2Add etc. However, it didn’t help too much in terms of performance, because, as I believe, to put the object with properties of GLKVector2 type to the array I had to use NSValue, as well as to decode the GLKVector2 values back from the object in the array to perform vector calculations. Below is the code from calculation method in object’s implementation:
GLKVector2 currentPosition;
[self.currentPosition getValue:¤tPosition];
GLKVector2 newPosition;
// calculations with vectors. Result is in newPosition.
self.currentPosition = [NSValue value:&newPosition withObjCType:#encode(GLKVector2)];
Moreover, when I rewrote the code to use GLKVector2, I got memory warnings and after some time of running the applications sometimes crashes.
I spend several days trying to find a better way to do the calculations faster, I looked at vecLib, openGL, but have not found a solution that would be understandable for me. I have a feeling that I might have to look at writing code in C and integrate it somehow into objective C, but I don’t understand how to integrate it with the array of objects without using NSValue thousands times.
I would greatly appreciate it if anyone could help with advise on what direction should I look at? Maybe there is some library available that can be easily used in Objective C with group of objects stored in arrays?
Learn how to use Instruments. Any performance optimisation is totally pointless unless you measure speed before and after your changes. An array of 1000 objects is nothing, so you might be worrying about nothing. Or slowdowns are in a totally different place. Use Instruments.
x * x is a multiplication. powf (x, 2.0) is an expensive function call that probably takes anywhere between 20 and 100 times longer.
GLKVector2 is a primitive (it is a union). Trying to stash it into an NSValue is totally pointless and wastes probably 100 times more time than just storing it directly.
Here an answer to you question about integrating physics calculations in C with your current Objective-C class. If you have a fragment of C code in your .m file which may look like
static CGPoint point[MAX_OBJ];
static int n_points = 0;
with a corresponding function in plain C as you suggested for simulating physical interactions that acts on point to update object positions, as in
void tick_world() {
for (int k = 0; k < n_points; k ++) {
float speed = sqrtf((point[k].x*point[k].x) + (point[k].y*point[k].y));
...
}
}
then, your Objective-C class Moving for the moving object could contain a pointer to a particular CGPoint in point that you would define in the interface (probably the corresponding *.h file):
#interface Moving : NSObject {
...
CGPoint *pos;
}
When handling the init message, you can then grab and initialize the next available element in point. If your objects persist throughout run time, this could be done very simply simply by
#implementation
...
-(id)initAtX:(float)x0 Y:(float)y0 {
self = [super init];
if (self) {
if (n_points == MAX_OBJ) {
[self release];
return nil;
}
pos = point + n_points ++;
pos->x = x0;
pos->y = y0;
}
return self;
}
If your Moving objects do not persist, you might want to think of a smart way to recycle slots after destruction. For example, you could initialize all x of point with NAN, and use this as a way to locate a free slot. In your dealloc, you would then pos->x = NAN.
It sounds like you're up against a couple common problems: 1) fast math in a high-level language, and 2) a meta-problem: whether to get the benefit of others' work (OpenGL, and several ideas listed here) in exchange for a steep learning curve as the developer.
Especially for this subject matter, I think the trade is pretty good in favor of using a library. For many (e.g. Eigen), most of the learning curve is about integration of Objective C and C++, which you can quickly put behind you.
(As an aside, often times, computing the square of the distance between objects is sufficient for making comparisons. If that works in your app, you can save cycles by replacing distance(a,b) with distnaceSquared(a,b)
I'm wondering what the most applicable kind of buffer implementation is for audio data in objective-c. I'm working with audio data on the iPhone, where I do some direct data manipulation/DSP of the audio data while recording or playing, so performance matters. I do iPhone development since some months now. Currently I'm dealing with c-arrays of element type SInt16 or Float32, but I'm looking for something better.
AFAIK, the performance of pointer-iterated c-arrays is unbeatable in an objective-c environment. However, pointer arithmetic and c-arrays are error prone. You always have to make sure that you do not access the arrays out of their bounds. You will not get a runtime error immediately if you do. And you have to make sure manually that you alloc and dealloc the arrays correctly.
Thus, I'm looking for alternatives. What high performance alternatives are there? Is there anything in objective-c similar to the c++ style std::vector?
With similar I mean:
good performance
iteratable with pointer-/iterator-based loop
no overhead of boxing/unboxing basic data types like Float32 or SInt16 into objective-c objects (btw, what's the correct word for 'basic data types' in objective-c?)
bounds-checking
possibility to copy/read/write chunks of other lists or arrays into and out of my searched-for list implementation
memory management included
I've searched and read quite a bit and of course NSData and NSMutableArray are among the mentioned solutions. However don't they double processing cost because of the overhead for the boxing/unboxing of basic data types? That the code looks outright ugly like a simple 'set'-operation becoming some dinosaur named replaceObjectAtIndex:withObject: isn't of my concern, but still it subtly makes me think that this class is not made for me.
NSMutableData hits one of your requirements in that it brings Objective-C memory management semantics to plain C buffers. You can do something like this:
NSMutableData* data = [NSMutableData dataWithLength: sizeof(Float32) * numberOfFloats];
Float32* cFloatArray = (Float32*)[data mutableBytes];
And you can then treat cFloatArray as a standard C array and use pointer iteration. When the NSMutableData object is dealloc'ed the memory backing it will be freed. It doesn't give you bounds checking, but it delivers memory management help while preserving the performance of C arrays.
Also, if you want some help from the tools in ironing out bounds-checking issues read up on Xcode's Malloc Scribble, Malloc Guard Edges and Guard Malloc options. These will make the runtime much more sensitive to bounds problems. Not useful in production, but can be helpful in ironing out issues during development.
The containers provided in the Foundation framework have little to offer for audio processing, being on the whole rather heavy-weight, nor providing extrinsic iterators.
Furthermore, none of the audio APIs in iOS or MacOSX that interact with buffers of samples are Objective-C - based, or take any parameters of Foundation framework containers.
Most likely, you would want to make use of the Accelerate Framework for DSP operations, and its APIs all work on arrays of floats or int16s.
Whilst all of the APIs are C-style, C++ and STL is the obvious weapon of choice for your requirements, and interworks cleanly with the rest of an application in the guise of Objective-C++. STL frequently compiles down to code which is about as efficient as hand-crafted C.
To memory-manage your buffers, perhaps use std::array - if you want bounds checking or std::shared_ptr or std::unique_ptr with a custom deleter if you're not worried.
Places where an iterator is expected - for instance algorithm functions in <algorithm> - can usually also take pointers to basic types - such as your sample buffers.
I am writing an application that I'd like to speed up. One way I have thought to do this is by switching from using NSArray and NSMutableArray to using straight c-style arrays of pointers.
I had tried naively to just do:
MyObject** objects = (MyObject**) malloc(N/2*sizeof(MyObject*))
This reports a compiler error when using ARC as it doesn't know what to do with a ** object;
this can be fixed by adding a bridge directive.
My question is how is this memory being handled and how to do memory management mixing C and Objective-C objects.
Two solutions are
MyObject* __weak* objects = (MyObject* __weak*) malloc(N/2*sizeof(MyObject*));
MyObject* __strong* objects = (MyObject* __strong*) malloc(N/2*sizeof(MyObject*));
What are the differences between those two arrays and how do I go about freeing/releasing them when done. Are NSArrays optimized to the point where this wouldn't result it much of a speed up?
Are NSArrays optimized to the point where this wouldn't result it much of a speed up?
Yes.
You should profile your code in Instruments -- chances are that even if you make heavy use of arrays, you're going to find that your code spends most of its time in places other than NSArray methods like -objectAtIndex:.
Taking that a step further, you should really be able to tell us whether NSArray is optimized sufficiently that you don't need to improve it. If you're looking to speed up your code by replacing NSArray, you should have already profiled your code and identified the expensive parts. Don't just guess at what needs to be improved; measure it.