Out of memory

  • 17 Antworten
  • Letztes Antwortdatum
Jaiel

Jaiel

Dauer-User
235
hey ich lade neben anderen bitmaps eine 1440x2560 bitmap in den speicher um diese daraufhin zu skalieren in 1440x2560 in meinem fall(note 4)

kriege aber ein out of memory sind wohl zu viele bitmaps im speicher


er läuft über und da steht ca 14 mb sind es wohl weswegen er meckert.


ich wollte mal fragen kann ich irgendwie das um,gehen ohne die resource zu verkleiner(bei ca 25% kleinerem bild geht es ok hab jetzt nmciht die grenzen ausgetestet da es ja von device zu device unterschiedlich ist)

ich hatte jetzt die idee es nciht hintereinander laufen zu lassen sondern erst die eine bitmap laden und dann skalieren dann die nächste und so weiter...zur zeit ist es so: lade erst mal alle bitmaps ind den speicher und dann kommt erst das skalieren.


aber ich frag mich wie lange es jetzt dauern würde bis der speicher geleert wird und keine out of memory ex kommt


zum beispiel hätte ich daran gedacht:

bitmap=BF.decoderessource(...,r.draable.homebutton);
homebutton=B.createScaledBitmap(bitmap,...);
bitmap=null;

bitmap=...



wie ihr seht befreie ich (vllt unnötierweise) die bitmap wieder damit es der GC aufsaugen kann

so jetzt kenn ich natürlich die recycle() methode die jedoch so wie finish nciht garantiert das sofort etwas passiert udn auch unnötig ist...


wie soll ich vorgehen damit speicher befreit wird oder kann ich das überhaupt(hach das sind die momente wo man C++ vermisst);
 
Das würde in C++ auch zu ein Out Of Memory führen. ;)

Du muss die Bilder außerhalb des MainThread laden und skalieren. Spricht du muss dies alles in Threads auslagern. Und die Bilder erst ganz am Schluß in den MainThread laden. Dann kann man die VM bis zum Maximum aufblähen (bis zu 500MB).
 
Mmmh okay

Zur Zeit lade ich ja die Bilder aus meiner view klasse heraus läuft das auf dem Main thread etwa?

Die bitmaps selber lade ich ja wiederum in Objekt meines worker threads also die befinden sich dort

Also laufen alle Methoden meiner view auf dem uithread wenn es als content der activity gesetzt wurde?!

Der ursprüngliche Beitrag von 09:44 Uhr wurde um 09:49 Uhr ergänzt:

PS das mit c++ meinte ich in dem Zusammenhang dass ich volle Kontrolle (und Verantwortung ) über den Speicher habe und nicht diesen Mist sag ich jetzt mal mich auf eine Müllabfuhr zu verlassen.

Die Bilder werden ja ausgelagert in Objekte meines threads


Ich probiere mal dein Vorschlag
 
Jaiel schrieb:


PS das mit c++ meinte ich in dem Zusammenhang dass ich volle Kontrolle (und Verantwortung ) über den Speicher habe und nicht diesen Mist sag ich jetzt mal mich auf eine Müllabfuhr zu verlassen.

Wie kommst du auf die seltsame Idee. Selbst mit C++ ist die Kontrolle über den Speicher rudimentär. ;) Ist eben auch nur eine höhere Programmiersprache. Waren nur nicht in der Lage eine vernünftige Speicherverwaltung zu schreiben.
 
vllt verwechsele ich das mit C bin auch nciht on the top zur zeit mit c++/11 und deren veränderungen....egalk sit ja jetzt nciht so wichtig.

hab jetzt ausgelagert...scheinbare perofrmance zunahme jedoch nciht so signifikant dass ich es darauf zurückschließen kann und die workload hat sich vergrößert sprich im ram ist jetzt mehr speciher alloziert für meine app GLAUBE ich leider hab ich kein "Logbuch" geführt.

Und das wichtigste natürlich : OutofMemory ist damit nciht behoben leider....

ich hab dir schon ne pm geschrieben aber ich stell die frage heir nochmal für alle anderen:

da ich trotzdem auf die ressourcen der view zugreifen muss habe ich jetzt eine variable : Resources res eingeführt in meinem thread und lade mti hilfe eben dieser meine bilder und skaliere die

bin ich jetzt raus aus dem UIThread oder immer ncoh drin wenn ich diese variable benuzte denn anders geht das ja nciht oder?
 
ich hab schnell mal ein schaubild gemacht wie ungefähr meine vorgehensweise ist:


ich rufe einfach vom thread die methode zum zeichnen auf


der thread und die view halten jeweils eine referenz des anderen um bei touch ereignissen zu reagieren und um die zeichenmethode der view regelmäßig aufzurufen.

mach ich irgendwas verkehrt so dass alles von der logik bis zur alloziierung auf dem uithread landet möglicherweise?
 

Anhänge

  • jaiel.png
    jaiel.png
    5,5 KB · Aufrufe: 165
zur info es handelt sich immer noch um ein 1440x2560 pixel großes bild


ich krieg eine outofmemory weil ich 235.929.616 byte allocation mache(1440x2560x64 bytes=235.929.600 bytes für die pixeldaten+16 bytes anderer kram)


PHP:
04-01 04:11:06.237: E/dalvikvm-heap(23782): Out of memory on a 235929616-byte allocation.
04-01 04:11:06.247: E/AndroidRuntime(23782): FATAL EXCEPTION: Thread-4971
04-01 04:11:06.247: E/AndroidRuntime(23782): Process: de.jaielsoft.activities, PID: 23782
04-01 04:11:06.247: E/AndroidRuntime(23782): java.lang.OutOfMemoryError
04-01 04:11:06.247: E/AndroidRuntime(23782): 	at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
04-01 04:11:06.247: E/AndroidRuntime(23782): 	at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:706)
04-01 04:11:06.247: E/AndroidRuntime(23782): 	at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:531)
04-01 04:11:06.247: E/AndroidRuntime(23782): 	at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:559)
04-01 04:11:06.247: E/AndroidRuntime(23782): 	at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:589)
04-01 04:11:06.247: E/AndroidRuntime(23782): 	at de.jaielsoft.threads.MainThread.scaleBitmaps(MainThread.java:419)
04-01 04:11:06.247: E/AndroidRuntime(23782): 	at de.jaielsoft.threads.MainThread.run(MainThread.java:56)


vielleicht ist es erwähnenswert dass ich das so amche(???):

PHP:
background=Bitmap.createScaledBitmap(
					BitmapFactory.decodeResource(res,R.drawable.background),
					screenWidth,screenHeight,true);
 
Ich hab noch eine lösungsidee gefunden die ich aber noch ausprobieren muss

Möglicherweise reizen ich die 500 MB(hab das irgendwo gelesen) ja schon aus da ich für kurze Zeit 2 Bitmaps mit jeweils 235 MB und die anderen noch im Speicher habe
ich werde einfach mein hintergrund mit options laden so dass ich es mir zum Anfang sparen werde erst das ganze Bitmap zu laden nur um es dann zu skalieren
ich decodieren es einfach sofort in die gewünschte Größe so hoffe ich erspare ich mir die outofmemory und muss nicht dazu übergehen den heap zu vergrößern mit largeheap=True im Manifest

Melde mich später nochmal


Nachtrag: kann aber auch nicht sein...Da ich den Fehler abgefangen habe und dieser entsteht beim Decoder. ..Werde trotzdem die Variante oben versuchen ansonsten muss ich wohl dann doch erst ein kleineres Bitmap laden und dann hochskalieren (das ist natürlich iwie kein Problem nur beim Decoder geht es halt schief)
 
Zuletzt bearbeitet:
Mir schlackern die Ohren.

1440x2560x64 bytes=235.929.600 bytes
Was sind denn die 64 Bytes? Gibt man Farbtiefen nicht in Bit an? Und wieso 64? Ist ja irre, 235Mb für eine Bitmap...
 
Und was ich mich noch fragen würde ist: Brauchst du die Auflösung wirklich? =)
Aber ich bin auf ne Antwort gespannt... weil ich schon bei fullHD immer in OOM gelandet bin =) Hab iwann die Bilder skaliert ^^ also wäre ich an deiner Lösung auch interessiert =)

lg. Dagobert
 
Thyrion schrieb:
Mal als Tipp: Loading Large Bitmaps Efficiently | Android Developers

Wie kommst du auf 64Byte(!) pro Pixel? Das ist unglaublich viel.

Das ist ja genau das was ich vorhabe. Ich decodieren einfach auf die gewünschte Größe.


Ich weiß auch nicht wo die 64 Byte herkommen
Es ist ja eine raw png vllt davon es wurde ja noch nicht in eine Bitmap umgewandelt denke ich mal

Sonst ist ja jeder Pixel 4 Byte groß und beide Chanel alpha und rgb 8 bit jeweils....Keine Ahnung also


Ich glaube auch das Android in Wirklichkeit Bits meint obwohl da byte steht das haut auch hin denn der fehler kommt bie 14.745 MB nicht bei 235 MB jedes Pixel hat bei ARGB_8888 eine Auflösung von 4 byte....das mal 2 Bilder + 8 bit RGB Channel + 8 Bit Alpha Channel(16 Bit extra)

so würde ich auch auf die 235 mBit kommen ob es richtig ist wie ich mir das denke ist ne andere sache

Der ursprüngliche Beitrag von 18:44 Uhr wurde um 19:46 Uhr ergänzt:

Hab es ausprobiert....leider keine Besserung krieg trotzdem ncoh OOM.....da kann man ncihts machen leider...große Bitmaps hat Android nciht lieb...

Tja Dagobert es bleibt wohl doch nur die Möglichkeit ein kleineres png zur Verfügung zu stellen oder large heap beantragen

mit largeHeap klapptr es und die Performance scheint auch die gleiche zu sein aber ich habe gehofft es geht auch anders


mit Large Heap habe ich es geschafft sogar 17 mal so ein Bild in den Speicher zu laden bevor die OOM beim 18. mal angeschlagen hat
 
Zuletzt bearbeitet:
Hi Jail, wie kommst du auf die Größe?
Ich hantiere mit Bilder mit den Maßen 1200x1200 pixel. Die Bilder sind wesentlich kleiner als 256MB. Auf die Zahl komme ich, wenn ich über 40 Bilder an einen Stück herunterlade. Das hört sich mehr nach einer falschen Speicherzuweisung an.

Wenn du die Methode BitmapFactory.decodeResource() benutzt, solltest du vorher angeben, wie viel Speicher du brauchst. Loading Large Bitmaps Efficiently | Android Developers
Der Speicher einer VM ist begrenzt, bei den neuen Devices können es 500MB sein. Android heap size on different phones/devices and OS versions - Stack Overflow
Um die maximale Heapsize zu nutzen, muss im Manifest unter dem Tag android:largeHeap eingetragen werden. <application> | Android Developers
Du solltest aber trotzdem sparsam mit den Speicher umgehen. Auch der HeapSize ist schnell ausgeschöpft. Und du solltest wirklich nur die Bilder laden, die du wirklich brauchst. Das Skalieren würde ich in einen AsyncTask auslagern, und erst das fertig skalierte Bild den betreffenden View zuweisen.

Mit den Methoden getLargeMemoryClass() und getMemoryClass() bekommst du den Speicher der VM heraus. https://developer.android.com/reference/android/app/ActivityManager.html#getLargeMemoryClass%28%29
https://developer.android.com/reference/android/app/ActivityManager.html#getMemoryClass()

Der ursprüngliche Beitrag von 20:39 Uhr wurde um 21:02 Uhr ergänzt:

--
Nachtrag: Deine Bilder dürften ungefähr 16MB groß sein.
Die Werte für dein Gerät sind (Galaxy Note 4)

dalvik.vm.heapstartsize=8m
dalvik.vm.heapgrowthlimit=256m
dalvik.vm.heapsize=512m

235.929.600 bytes ≈ 256m
 
OK danke für die werte

Das Problem tritt schon beim Decoden auf der kommt gar nicht erst zum skalieren. Aber Mut large heap wird wohl gehen...Werde es so implementieren dass falls auf anderen Geräten ein oom kommt dass ich den heap manuell vergrößern werde
 
Du kannst den Heap nicht manuell vergrößern. Das macht das System.

Am einfachsten nimmst du einfach passend skalierte Bilder. Mit den Versuch, die Bilder selber zu skalieren, machst du Dir mehr Probleme als nötig. ;)

Keep it simple. ;)
 
oh okay ich glaube das wird wohl nciht mehr unterstützt von android

PHP:
public synchronized long setMinimumHeapSize(long size)

aus dalvik.VMRuntime



hab in den docs auch ncihts gefunden die runtime klasse hat diese methode nciht mehr
da hatte man wohl noch mehr kontrolle damals zu Anfangszeiten ->https://www.cs.cmu.edu/~srini/15-44...2/docs/reference/dalvik/system/VMRuntime.html


naja ok muss ich wohl sehen wie ich das amche....stichwort verschiedene ressourcen für verschiedene display auflösungen


aber finde es irgendwie komisch dass ein handy mit dem normalen heap mit 1440x2560 kein bild in genau der Auflösung laden kann ohne OOM zu triggern


der heap sollte vergrößert werden finde ich für solche Auflösungen
 
Zuletzt bearbeitet:
Hey, da du ja speicherintensive Sachen machst, schau dir mal leakcanary von square an:
https://github.com/square/leakcanary

Das ist eine Bilbiothek, die dir memory leaks im Debug Build deiner App anzeigt und woher sie kommen.
Die Sachen von square sind immer extrem gut programmiert und machen im Normalfall keine Probleme. Vielleicht hilft es dir.
 
hey danke hört sich gut an...ich hatte mir zwar kaum sorgen über memory leaks gemacht bisher aber ist bestimmt nützlich bei größeren applikationen
 
Zurück
Oben Unten