ChuyingHe / osmdroid

Automatically exported from code.google.com/p/osmdroid
0 stars 0 forks source link

Loading Tiles : VM won't let us allocate 262144 bytes #27

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
What steps will reproduce the problem?
1. Zoom in
2. Loading new tiles
3. Exception Ocurred

What is the expected output? What do you see instead?

The new tiles in the new zoom view, but an exception ocurrus. In logcat i 
see this:

D/OPENSTREETMAP( 1209): MapTileCache succeeded for: 7/0/0/0
D/OPENSTREETMAP( 1209): MapTileCache succeeded for: 7/0/0/0
E/dalvikvm-heap( 1209): 262144-byte external allocation too large for this 
process.
E/        ( 1209): VM won't let us allocate 262144 bytes
D/skia    ( 1209): --- decoder->decode returned false
E/OPENSTREETMAP( 1209): OutOfMemoryError putting tile in cache: 
7/4/9/5
D/OPENSTREETMAP( 1209): MapTile request complete: 7/4/9/5
D/OSM_FS_PROVIDER( 1215): Next tile: 7/4/6/4
D/OPENSTREETMAP( 1209): MapTileCache succeeded for: 7/0/0/0
D/OPENSTREETMAP( 1209): MapTileCache succeeded for: 7/0/0/0
D/OPENSTREETMAP( 1209): Rendering overall: 66ms
V/OPENSTREETMAP( 1209): onDraw
D/OSM_FS_PROVIDER( 1215): Loaded tile: 7/4/9/3
E/dalvikvm-heap( 1209): 262144-byte external allocation too large for this 
process.
E/        ( 1209): VM won't let us allocate 262144 bytes
D/skia    ( 1209): --- decoder->decode returned false
E/OPENSTREETMAP( 1209): OutOfMemoryError putting tile in cache: 
7/4/9/3

What version of the product are you using? On what operating system?

I'm using a emulator tool with Android 2.0.1

Please provide any additional information below.

Original issue reported on code.google.com by gefe...@gmail.com on 25 Mar 2010 at 11:50

GoogleCodeExporter commented 9 years ago
This is the default out of memory error.

Haven't encountered any using osmdroid. Maybe fixed?

Original comment by viesturz on 7 Apr 2010 at 4:55

GoogleCodeExporter commented 9 years ago
i will check if i have the last version and if it fixed this problem. 

Original comment by gefe...@gmail.com on 7 Apr 2010 at 6:52

GoogleCodeExporter commented 9 years ago
I do have the same problem with a Nexus One device.
But till now I didn't get an OutOfMemoryException on a G1. Of course I'm using 
the 
latest version of osmdroid.

So this is kind of strange. I'm going to try to fix this when I get back my 
Nexus One.

Original comment by d.sc...@gmail.com on 8 Apr 2010 at 2:24

GoogleCodeExporter commented 9 years ago
I found a workaround, which helps but is not the final solution.

1. I exposed a method to clear the entire stack in OpenStreetMapTileCache: 
--------------------------------------------------------------------------
public void clear(){
        mCachedTiles.clear();
    }
2. I changed OpenStreetMapTileProvider to clear the entire cache and call the 
gc:
--------------------------------------------------------------------------------
-

IOpenStreetMapTileProviderCallback mServiceCallback = new
IOpenStreetMapTileProviderCallback.Stub() {

        @Override
        public void mapTileRequestCompleted(int rendererID, int zoomLevel, int tileX, int
tileY, String aTilePath) throws RemoteException {
...
                        } catch (Throwable e) {
                            Log.e(DEBUGTAG, "Error deleting invalid file: " + aTilePath, e);
                        }
                    }
                } catch (OutOfMemoryError e) {
!!!!!                   mTileCache.clear();
!!!!!                   System.gc();
                    Log.e(DEBUGTAG, "OutOfMemoryError putting tile in cache: " + tile,e);
                }
            }
            mDownloadFinishedHandler.sendEmptyMessage(OpenStreetMapTile.MAPTILE_SUCCESS_ID);
            if (DEBUGMODE)
                Log.d(DEBUGTAG, "MapTile request complete: " + tile);
        }
    };

Now it usable on my Nexus One. However, there should be a more precise method of
removing bitmaps.

For me, it seems that on the Nexus, the number of Bitmaps is more restricted. 
Some
people think, it is a bug...

Original comment by thomas.f...@gmail.com on 10 Apr 2010 at 5:50

GoogleCodeExporter commented 9 years ago
The following changes seem to fix the problem for me:

1. in OpenStreetMapViewConstants reduce the number of tiles to 50 (was 75)
public static final int CACHE_MAPTILECOUNT_DEFAULT = 50;

2. in OpenStreetMapServiceConstants introduce new constant
public static final int FS_CACHE_SIZE=16 * 1024 * 1024; // 16 MB

3. in OpenStreetMapTileProviderService refer the new constant instead of 
computing
here directly

        @Override
    public void onCreate() {
        super.onCreate();
        mFileSystemProvider = new OpenStreetMapTileFilesystemProvider(
                this.getBaseContext(), FS_CACHE_SIZE); 
    }

My quick fix above is not necessary now, however, it does not disturb. Perhaps 
the
caches need to be adjusted more precise depending on the hardware or need to be 
made
configurable. I have lots of MB available on my disk, however, 2.1 seems to be
ungenerous on the number of Bitmaps for an app.

Original comment by thomas.f...@gmail.com on 11 Apr 2010 at 9:13

GoogleCodeExporter commented 9 years ago
Playing with the constants I increased the number of parallel threads to 8 and 
the
disc cache to 64MB shows a drastic (i.e. Google Maps like) improvement of 
usability.

It would be nice, if the app would be configurable or could detect if it could 
run in
lean or fat mode in terms of memory and disc usage.

It is really fun now! Will watch the memory and energy consumption...

Original comment by thomas.f...@gmail.com on 11 Apr 2010 at 10:29

GoogleCodeExporter commented 9 years ago
Issue 33 has been merged into this issue.

Original comment by neilboyd on 13 Apr 2010 at 1:05

GoogleCodeExporter commented 9 years ago
I added the constant as suggested in comment 5, but didn't change the value.

Original comment by neilboyd on 13 Apr 2010 at 7:01

GoogleCodeExporter commented 9 years ago
the problem still remains...

Original comment by gefe...@gmail.com on 13 Apr 2010 at 10:01

GoogleCodeExporter commented 9 years ago
Revision 131 uses the suggested values.

Original comment by neilboyd on 15 Apr 2010 at 7:11

GoogleCodeExporter commented 9 years ago
Reprodced the error on latest version #133 .
Android emulator 2.1.

Just browsed around for about 1 min.

Original comment by viesturz on 15 Apr 2010 at 9:55

GoogleCodeExporter commented 9 years ago
Also added the clear as suggested in comment 4 in revision r134

Original comment by neilboyd on 15 Apr 2010 at 8:10

GoogleCodeExporter commented 9 years ago
i have tried the clear and it is a bad solutions because the tiles are shown 
and then disappear when "clear" is 
called. This happens all the time and there is not posible to fix it

Original comment by gefe...@gmail.com on 15 Apr 2010 at 10:30

GoogleCodeExporter commented 9 years ago
Definetely clear is to aggressive because it removes everything.

I am testing a better version and hopefully can post something at the weekend.

Original comment by thomas.f...@gmail.com on 16 Apr 2010 at 8:30

GoogleCodeExporter commented 9 years ago
The attached code of OpenStreetMapTileCache mitigated the problem. Now it runs 
stable
for a while, however, then there are ConcurrentModificationExceptions later on. 
Hard
to reproduce...

I also run into a NullPointerException later on in 
OpenStreetMapAsyncTileProvider.
Catching like

private OpenStreetMapTile nextTile() {
            while(true) {
                if (mIterator == null) {
                    mIterator = mPending.keySet().iterator();
                }
                if (!mIterator.hasNext()) {
                    return null;
                }
                try {
                    synchronized (mPending) {
                        final OpenStreetMapTile tile = mIterator.next();
                        try {
                            mIterator.remove();
                        } catch(ConcurrentModificationException e) {
                            // couldn't remove this request
                            // never mind, we'll process it again
                        }
                        catch(NoSuchElementException e) {
                            // we shouldn't get this, but just in case
                            return null;
                        }
                        catch(NullPointerException e){
                            // TODO clean this exceptions
                        }
                        return tile;
                    }
                } catch(ConcurrentModificationException e) {
                    // get a new iterator and try again
                    mIterator = null;
                }
            }
        }

rose another ConcurrentModificationException later. The synchronization in the 
code
seems to be incomplete, and catching these Exceptions is no solution. We have 
sync
all the stuff carefully

This is no problem for me, except time. However, I would like to fix this in 
another
branch because I need to touch a lot of classes...

Original comment by thomas.f...@gmail.com on 18 Apr 2010 at 9:13

Attachments:

GoogleCodeExporter commented 9 years ago
You can see the discussion about synchronization in issue 35.

In my opinion it's not worth the overhead of extra synchronization. As it is 
now it 
occassionally catches a ConcurrentModificationException and returns the "wrong" 
item. 
To me that seems like a reasonable compromise.

Original comment by neilboyd on 18 Apr 2010 at 6:19

GoogleCodeExporter commented 9 years ago
My opinion is that this is not a tight loop (executes max some 10 times a 
second and
most of the time is not executing at all) and the overhead of extra sync is far 
lower
than all the fuss of making it work without one.

Original comment by viesturz on 19 Apr 2010 at 7:26

GoogleCodeExporter commented 9 years ago
Patch for the following issues:

I attached a working (Nexus One tested) patch to address the following issues:

1. Useful constants
2. Careful sync without any ConcurrentModificationExceptions
@neilboyd:
I think, catching the exceptions is good in normal java environments, however, 
on the 
android you could loose a Bitmap, and not recycling the internal memory creates 
a 
memory leak which hurts later.

3. Download from several servers in parallel, generally possible for all,
implemented for the CYCLEMAP

    CYCLEMAP(R.string.cyclemap, ".png", 0, 17, 8, CodeScheme.X_Y,
            "http://a.andy.sandbox.cloudmade.com/tiles/cycle/",
            "http://b.andy.sandbox.cloudmade.com/tiles/cycle/",
            "http://c.andy.sandbox.cloudmade.com/tiles/cycle/"),

You can use the OpenStreetMapRendererInfo with several servers now, and the 
implementation picks randomly one of the servers. This seems to improve the 
download 
speed enormously. Checking the URLs in parallel with a Firefox sometimes shows 
a 404 
on some tiles, indicating a server problem which is harmless, if you can try 
lots of 
servers.

Room for improvement, choose the servers according to their response time... 

The cyclemap now feels better than the Google maps!

4. Another issue I could not solve: if you turn the display from horizontal to 
vertical or vice versa, the cache seems unnecessarily to fetch everything again.

Is anyone solving this issue?

Have fun,
Thomas

Original comment by thomas.f...@gmail.com on 2 May 2010 at 10:00

Attachments:

GoogleCodeExporter commented 9 years ago
Hi Thomas

1. Committed in revision 150.
2. I'm still not convinced about synchronization. See also issue 35. That 
doesn't 
mean I disagree, just that I'm standing on the fence.
3. Copied to issue 48.
4. Please make a new issue for this, with more information.

Regards

Neil

PS. Your patch includes the upgrade to API 7 and the 
MultiTouchOpenStreetMapView 
attached to issue 25. I don't think that was intended, and it's not necessary 
following the fix I made for issue 25.

Original comment by neilboyd on 3 May 2010 at 7:54

GoogleCodeExporter commented 9 years ago
Regarding not recycling the bitmaps, the docs says that recycle should be 
unnecessary 
and it will happen by itself. Doing it explicitly just makes it happen a bit 
sooner.

Original comment by neilboyd on 3 May 2010 at 8:35

GoogleCodeExporter commented 9 years ago
Hi Neil,

@comment 19 I had to send the patches, because my codebase became to different.
Unfortunately, you discovered my guerilla attempt do commit the
MultiTouchOpenStreetMapView :-) 
If nobody else is working on it, I will try to do a reflection patch testing on 
the
existence of the right api next time.

@comment 22
This is true, however, the time until the next garbage collector cleanup is 
performed
might be to long because the native memory comes from another pool, as I 
understood
the case.

Original comment by thomas.f...@gmail.com on 3 May 2010 at 12:53

GoogleCodeExporter commented 9 years ago
The reflection version is already committed in revision 143 / issue 25.

Original comment by neilboyd on 3 May 2010 at 3:24

GoogleCodeExporter commented 9 years ago
anyone can tell me what is the last patch to solve this issue? Because i can't 
solve this problem yet

Original comment by gefe...@gmail.com on 5 May 2010 at 4:47

GoogleCodeExporter commented 9 years ago
Is anybody looking into the rotation issue mentioned in comment 18, point 4 ?
I'm using the OpenStreetMapView in my app, but I'm still having memory issues.
I can reproduce the OutOfMemory error very easily by rotating my screen about 
10 times.

It seems after a screen rotation all the tiles are reloaded into memory, but the
garbage collector hasn't freed the memory from the old tiles yet, which 
eventually
leads to an OutOfMemory error.

Original comment by h...@navitell.com on 27 May 2010 at 8:20

GoogleCodeExporter commented 9 years ago
I'm not looking at it, but I made issue 54 for it.

Original comment by neilboyd on 27 May 2010 at 8:52

GoogleCodeExporter commented 9 years ago
See also issue 73

Original comment by neilboyd on 21 Jul 2010 at 8:29

GoogleCodeExporter commented 9 years ago

Original comment by neilboyd on 10 Sep 2010 at 2:33

GoogleCodeExporter commented 9 years ago
[deleted comment]
GoogleCodeExporter commented 9 years ago
Im fetching the images url and tring to display it in listview but its giving 
me the following error. If a get 1 or 2 images its giving me the result but the 
following occurs when i get more images. Can u plz help me im not getting it 
since 1 week.
Thanks in advance!

01-02 13:50:16.183: E/AndroidRuntime(1942): FATAL EXCEPTION: pool-1-thread-2
01-02 13:50:16.183: E/AndroidRuntime(1942): java.lang.OutOfMemoryError: bitmap 
size exceeds VM budget
01-02 13:50:16.183: E/AndroidRuntime(1942):     at 
android.graphics.BitmapFactory.nativeDecodeStream(Native Method)
01-02 13:50:16.183: E/AndroidRuntime(1942):     at 
android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:470)
01-02 13:50:16.183: E/AndroidRuntime(1942):     at 
android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:525)
01-02 13:50:16.183: E/AndroidRuntime(1942):     at 
com.loopj.android.image.WebImage.getBitmapFromUrl(Unknown Source)
01-02 13:50:16.183: E/AndroidRuntime(1942):     at 
com.loopj.android.image.WebImage.getBitmap(Unknown Source)
01-02 13:50:16.183: E/AndroidRuntime(1942):     at 
com.loopj.android.image.SmartImageTask.run(Unknown Source)
01-02 13:50:16.183: E/AndroidRuntime(1942):     at 
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1088)
01-02 13:50:16.183: E/AndroidRuntime(1942):     at 
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:581)
01-02 13:50:16.183: E/AndroidRuntime(1942):     at 
java.lang.Thread.run(Thread.java:1019)

Original comment by prashant...@gmail.com on 2 Jan 2013 at 8:22