While corona is so slow with images ?

When I tap on screen I create 1000 images from 5 kb png file using a for loop
[lua]local function onTap( )
for i=1, 1000 do
local img = display.newImageRect( “img.png”, 90, 90)
end
end[/lua]
with 300 - 400 it almost doesn’t have slow downs

  1. I start my corona app on device.
Ram used: 14 MB
  1. I create 4700 images with the code above
Ram used: 17,80 MB

Just 3,80 MB was used.
Result -> the application responds to tap event after some seconds.
Does someone know why it is so slow. I think images don’t use CPU. Where is the problem ? [import]uid: 138389 topic_id: 30860 reply_id: 330860[/import]

PNG is a compressed format (It’s compression type is the same as a .zip, called ‘deflate’)
For each image loaded, it needs to decompress the image, which takes CPU time. This also means that a 5kb PNG is usually significantly more texture memory than it was in File Size. .BMP are a non-compressed format and should give you a better idea, but the quickest way to figure out the actual Texture Memory used is Width * Height * Bit Depth in Bytes (4 is the most common) = Memory Used in Bytes. This can get more complicated when you realize you are usually stuck with getting your texture up-sized to the nearest power of two when uploading to the GPU, but that’s probably getting too complex.

That being said, Corona has image caching, and so outside the initial load time, it should ideally be time spent setting up display objects, creating Vertex Buffers, and all the underlying information on both C and Lua sides that make up a display object. Try printing out the RAM used between each call, and then you can isolate how much memory it takes per display object, as well as how much it takes for the first one (this will be drastically different).

Making 4700 renderable objects as a blocking frame call is going to slow you down, because a rendered object is not simply a shared texture resource, but has potentially a mask, a rotation, a place in the scene graph hierarchy, a scale, a position, a color multiply, a reference point, UV coordinates, a size, 4 vertices (at least), 4-6 indices (at least), etc… [import]uid: 134101 topic_id: 30860 reply_id: 123417[/import]

@Ntero, thank you for explanations
This the test I made.
[lua]local function createImgs()
local tmp = system.getTimer()
for i=1, 1000 do
local img1 = display.newImage( “point2.png”)
end
total = total + 1000
print(“total:” … total)
print(“time:” … (system.getTimer() - tmp))
printMemUsage()
end[/lua]
I call createImgs() with a 5 sec interval.
Output:

total: 1000  
time: 242  
memUsage: 287.84  
TextMem: 0.131  
-----------------------------------  
total: 5000  
time: 147  
memUsage: 887.03  
TextMem: 0.131  
-----------------------------------  
num: 20000  
time: 156  
memUsage: 4274.91  
TextMem: 0.131  
-----------------------------------  
total: 40000 --number of images on the screen  
time: 150 --time in ms to create 1000 images  
memUsage: 8461.70  
TextMem: 0.131  

You can see that there is the same time to create 1000 images.
But the difference is on the screen.
When I create first 1000 images they appear immediately on screen.
When I create 1000 images when on screen was already 5000 images it will appear after 1-2 seconds and so on.
Why 5000 images on screen that are static and do nothing will slow down the system and the future actions.
Maybe corona updates the screen every time I create a image ? [import]uid: 138389 topic_id: 30860 reply_id: 123435[/import]

Before you do your loops, and start the clock, be sure to collect garbage (http://www.lua.org/manual/5.1/manual.html#pdf-collectgarbage)
Because the Garbage Collector in Lua runs behind the scenes, and so can conflict with measuring the time spent.

You’ll notice the time is largest on the first create, and this is due to decompressing and loading the PNG itself, which is reused later. The Texture Memory you’ll also notice is constant, showing that all 40000 images are using the same the same Texture Resource. Memory usage too, seems to scale linearly (or thereabouts) with the exception of the first file load (expected), by dividing the number of objects by memory usage, you can probably come up with a close average of memory used per-display object.

The Time measurement however seems to conflict with what you are saying (1-2 second delay). I don’t know the guts of Corona, and so can only really guess what would cause it, however it’s possible that Corona postpones some of the work to the end of the frame. Try printing out your frame-rate and see if that is causing an issue. It’s possible your framerate is plummeting (either due to Draw Calls, internal processing or some other behaviour), and so even if the images load fine, it won’t render the next frame for a long time. If you had 40 000 draw calls, your frame rate would be completely in the toilet, but again I don’t know the inner guts of Corona and so can only really guess.\

In Short, Check to see that your frame rate is not what’s causing the 1-2 second render lag, either by checking the time taken between enterFrame events, or have an animating object and see if it’s moving fluidly. If it’s your frame rate, then there are some different reasons and solutions (that arn’t going right here, since this is already a mini-essay). [import]uid: 134101 topic_id: 30860 reply_id: 123443[/import]

Ntero, you were right, frame rate is the problem.
[as] The Time measurement however seems to conflict with what you are saying (1-2 second delay).[/as]
No. The time it takes to create 1000 images is always the same ~ 156ms but corona will update the screen with 40000 images, this is the problem.
You said:
[as] If you had 40 000 draw calls, your frame rate would be completely in the toilet[/as]
Yes it is. The FPS is about 1 - 2, so it is icredible slow, almost static.
If I set .isVisible attribute of 39000 images to false it will draw just the remainig 1000 at better fps speed.
Is there a way to increase fps but with all 40000 images visible ?
Maybe it is possible to leave 39000 images where they are and redraw just the new 1000 images.
What do you think ? [import]uid: 138389 topic_id: 30860 reply_id: 123468[/import]

In that situation you may need info from someone from Corona Labs.

First, do you really need 40000 on-screen objects? That’s about 1.5 pixels per object on an iPhone 4. Could you get the same effect with less?
Take any AAA console title of any kind, and it won’t even have a tiny fraction of that many sprites on screen at any time. It may look like it, but it’s simply a well structured lie.

There are a few general, non-Corona solutions, but their applicability is going to depend on implicit details in Corona’s API, and what it is you are trying to do.

A) Batching: I have no idea the full extent of Batching rules in Corona, but essentially Batching is the idea of combining objects with the same render settings into a single Mesh. This reduces Draw Calls, which can be a major stall if done too much per frame. If Corona doesn’t do this, you could have some trouble.
B) Off-screen culling: While the engine should be doing this, sometimes if you know the way your sprites move, you can be more aggressive with it. E.g. Maybe there are larger objects on screen that can obscure major blocks of the screen. Maybe the engine is not doing this (put all sprites off screen and see if it’s the equivalent of setting .isVisible to false). If setting sprites to false is faster, then when you move these particles you may want to do a simple AABB collision test against 0, 0, screenWidth, screenHeight and set visible to false if it’s out of screen.
C) Fakery: Even if a real simulation would involve that many sprites, you only need to make it real enough to convince the user. ALL of game rendering is based on the idea that a close visual estimation is as good as the real thing, but generally MUCH faster. While Pixar can take an hour per frame, game development only gets 16ms. Reduce your sprite count, combine sprites, use audio to emphasize the effect, replace blocks of your sprites with flip-book animations, etc…

If you let me know the effect you want, maybe I can try to give you a more specific solution on how you can fake it.

You can’t simply redraw the new images and not the old each frame without writing a very customised renderer, that works very differently from what you’d find in any game engine, and which would have huge troubles moving any of those objects. [import]uid: 134101 topic_id: 30860 reply_id: 123561[/import]

@Ntero, many, many thanks for all your help.
I am making a draw game/application. Ok, maybe I don’t need 40000 objects: images o vectors but a lot of objects should be created.
I tested this simple draw eample.
http://developer.coronalabs.com/code/easy-finger-drawing-undo-functionality
It is good but after drawing some lines it is going to be more and more slow, reducing the frame rate very fast.
There is a lot of apps and games on android and ios where you can draw a lot and you will not see a lag.
I don’t thing there is a technic at this point to implement this in corona.
They don’t have even costum vector shapes. [import]uid: 138389 topic_id: 30860 reply_id: 123596[/import]

PNG is a compressed format (It’s compression type is the same as a .zip, called ‘deflate’)
For each image loaded, it needs to decompress the image, which takes CPU time. This also means that a 5kb PNG is usually significantly more texture memory than it was in File Size. .BMP are a non-compressed format and should give you a better idea, but the quickest way to figure out the actual Texture Memory used is Width * Height * Bit Depth in Bytes (4 is the most common) = Memory Used in Bytes. This can get more complicated when you realize you are usually stuck with getting your texture up-sized to the nearest power of two when uploading to the GPU, but that’s probably getting too complex.

That being said, Corona has image caching, and so outside the initial load time, it should ideally be time spent setting up display objects, creating Vertex Buffers, and all the underlying information on both C and Lua sides that make up a display object. Try printing out the RAM used between each call, and then you can isolate how much memory it takes per display object, as well as how much it takes for the first one (this will be drastically different).

Making 4700 renderable objects as a blocking frame call is going to slow you down, because a rendered object is not simply a shared texture resource, but has potentially a mask, a rotation, a place in the scene graph hierarchy, a scale, a position, a color multiply, a reference point, UV coordinates, a size, 4 vertices (at least), 4-6 indices (at least), etc… [import]uid: 134101 topic_id: 30860 reply_id: 123417[/import]

@Ntero, thank you for explanations
This the test I made.
[lua]local function createImgs()
local tmp = system.getTimer()
for i=1, 1000 do
local img1 = display.newImage( “point2.png”)
end
total = total + 1000
print(“total:” … total)
print(“time:” … (system.getTimer() - tmp))
printMemUsage()
end[/lua]
I call createImgs() with a 5 sec interval.
Output:

total: 1000  
time: 242  
memUsage: 287.84  
TextMem: 0.131  
-----------------------------------  
total: 5000  
time: 147  
memUsage: 887.03  
TextMem: 0.131  
-----------------------------------  
num: 20000  
time: 156  
memUsage: 4274.91  
TextMem: 0.131  
-----------------------------------  
total: 40000 --number of images on the screen  
time: 150 --time in ms to create 1000 images  
memUsage: 8461.70  
TextMem: 0.131  

You can see that there is the same time to create 1000 images.
But the difference is on the screen.
When I create first 1000 images they appear immediately on screen.
When I create 1000 images when on screen was already 5000 images it will appear after 1-2 seconds and so on.
Why 5000 images on screen that are static and do nothing will slow down the system and the future actions.
Maybe corona updates the screen every time I create a image ? [import]uid: 138389 topic_id: 30860 reply_id: 123435[/import]

Before you do your loops, and start the clock, be sure to collect garbage (http://www.lua.org/manual/5.1/manual.html#pdf-collectgarbage)
Because the Garbage Collector in Lua runs behind the scenes, and so can conflict with measuring the time spent.

You’ll notice the time is largest on the first create, and this is due to decompressing and loading the PNG itself, which is reused later. The Texture Memory you’ll also notice is constant, showing that all 40000 images are using the same the same Texture Resource. Memory usage too, seems to scale linearly (or thereabouts) with the exception of the first file load (expected), by dividing the number of objects by memory usage, you can probably come up with a close average of memory used per-display object.

The Time measurement however seems to conflict with what you are saying (1-2 second delay). I don’t know the guts of Corona, and so can only really guess what would cause it, however it’s possible that Corona postpones some of the work to the end of the frame. Try printing out your frame-rate and see if that is causing an issue. It’s possible your framerate is plummeting (either due to Draw Calls, internal processing or some other behaviour), and so even if the images load fine, it won’t render the next frame for a long time. If you had 40 000 draw calls, your frame rate would be completely in the toilet, but again I don’t know the inner guts of Corona and so can only really guess.\

In Short, Check to see that your frame rate is not what’s causing the 1-2 second render lag, either by checking the time taken between enterFrame events, or have an animating object and see if it’s moving fluidly. If it’s your frame rate, then there are some different reasons and solutions (that arn’t going right here, since this is already a mini-essay). [import]uid: 134101 topic_id: 30860 reply_id: 123443[/import]

Ntero, you were right, frame rate is the problem.
[as] The Time measurement however seems to conflict with what you are saying (1-2 second delay).[/as]
No. The time it takes to create 1000 images is always the same ~ 156ms but corona will update the screen with 40000 images, this is the problem.
You said:
[as] If you had 40 000 draw calls, your frame rate would be completely in the toilet[/as]
Yes it is. The FPS is about 1 - 2, so it is icredible slow, almost static.
If I set .isVisible attribute of 39000 images to false it will draw just the remainig 1000 at better fps speed.
Is there a way to increase fps but with all 40000 images visible ?
Maybe it is possible to leave 39000 images where they are and redraw just the new 1000 images.
What do you think ? [import]uid: 138389 topic_id: 30860 reply_id: 123468[/import]

In that situation you may need info from someone from Corona Labs.

First, do you really need 40000 on-screen objects? That’s about 1.5 pixels per object on an iPhone 4. Could you get the same effect with less?
Take any AAA console title of any kind, and it won’t even have a tiny fraction of that many sprites on screen at any time. It may look like it, but it’s simply a well structured lie.

There are a few general, non-Corona solutions, but their applicability is going to depend on implicit details in Corona’s API, and what it is you are trying to do.

A) Batching: I have no idea the full extent of Batching rules in Corona, but essentially Batching is the idea of combining objects with the same render settings into a single Mesh. This reduces Draw Calls, which can be a major stall if done too much per frame. If Corona doesn’t do this, you could have some trouble.
B) Off-screen culling: While the engine should be doing this, sometimes if you know the way your sprites move, you can be more aggressive with it. E.g. Maybe there are larger objects on screen that can obscure major blocks of the screen. Maybe the engine is not doing this (put all sprites off screen and see if it’s the equivalent of setting .isVisible to false). If setting sprites to false is faster, then when you move these particles you may want to do a simple AABB collision test against 0, 0, screenWidth, screenHeight and set visible to false if it’s out of screen.
C) Fakery: Even if a real simulation would involve that many sprites, you only need to make it real enough to convince the user. ALL of game rendering is based on the idea that a close visual estimation is as good as the real thing, but generally MUCH faster. While Pixar can take an hour per frame, game development only gets 16ms. Reduce your sprite count, combine sprites, use audio to emphasize the effect, replace blocks of your sprites with flip-book animations, etc…

If you let me know the effect you want, maybe I can try to give you a more specific solution on how you can fake it.

You can’t simply redraw the new images and not the old each frame without writing a very customised renderer, that works very differently from what you’d find in any game engine, and which would have huge troubles moving any of those objects. [import]uid: 134101 topic_id: 30860 reply_id: 123561[/import]

@Ntero, many, many thanks for all your help.
I am making a draw game/application. Ok, maybe I don’t need 40000 objects: images o vectors but a lot of objects should be created.
I tested this simple draw eample.
http://developer.coronalabs.com/code/easy-finger-drawing-undo-functionality
It is good but after drawing some lines it is going to be more and more slow, reducing the frame rate very fast.
There is a lot of apps and games on android and ios where you can draw a lot and you will not see a lag.
I don’t thing there is a technic at this point to implement this in corona.
They don’t have even costum vector shapes. [import]uid: 138389 topic_id: 30860 reply_id: 123596[/import]

@vova

Even paint programs don’t / can’t function with 40000+ objects on the screen at once. Programs looping trying to do 40000 anything every screen frame will choke…

I agree with ntero regarding the well crafted lies theory, and it works for paint programs too, an obvious solution to reducing the onscreen objects is to composite them into larger objects (keeping in mind the “undo” as well).

So for freehand painting, the user would select a color, and a brush size and then start swiping their finger around. An app would typically draw a colored circle wherever they moved. This could be hundreds of circles - per color - it would add up quick. The trick would be to do something like:

When they lift their finger, take everyting they just drew (the circles of that color with that touch), and composite then into one image. Then remove the hundreds of circles and just display the one composite. Undo will just remove the whole thing at this point (not every individual pixel, one at a time).

Don’t really have time to go through how that would be done in corona, but suffice it to say display.save or display.capture (likely using a group and a mask) would handle the grunt work.

Each of your 90x90 images take up 64Kbytes of texture memory.  I’m not sure why your texture memory isn’t going up.

With 40,000 images you are at 2.6 GB of memory.  While you’re in the simulator, your computer can probably yield you that much memory, but you are likely going to start paging causing your computer to seriouslly start slowing down.   On a device you’re going to run out of memory well before you get to 40,000 images and the OS will kill your app. 

Since you’re not actually doing anything with the images, the memory paging on your computer is likely the reason for any performance problems. 

@vova

Even paint programs don’t / can’t function with 40000+ objects on the screen at once. Programs looping trying to do 40000 anything every screen frame will choke…

I agree with ntero regarding the well crafted lies theory, and it works for paint programs too, an obvious solution to reducing the onscreen objects is to composite them into larger objects (keeping in mind the “undo” as well).

So for freehand painting, the user would select a color, and a brush size and then start swiping their finger around. An app would typically draw a colored circle wherever they moved. This could be hundreds of circles - per color - it would add up quick. The trick would be to do something like:

When they lift their finger, take everyting they just drew (the circles of that color with that touch), and composite then into one image. Then remove the hundreds of circles and just display the one composite. Undo will just remove the whole thing at this point (not every individual pixel, one at a time).

Don’t really have time to go through how that would be done in corona, but suffice it to say display.save or display.capture (likely using a group and a mask) would handle the grunt work.

Each of your 90x90 images take up 64Kbytes of texture memory.  I’m not sure why your texture memory isn’t going up.

With 40,000 images you are at 2.6 GB of memory.  While you’re in the simulator, your computer can probably yield you that much memory, but you are likely going to start paging causing your computer to seriouslly start slowing down.   On a device you’re going to run out of memory well before you get to 40,000 images and the OS will kill your app. 

Since you’re not actually doing anything with the images, the memory paging on your computer is likely the reason for any performance problems.