Smallest object size in Android/Dalvik - android

DDMS shows the smallest size of an object (i.e. an empty object) is 16 bytes in VM Heap tab. But struct Object is only 8 bytes in dalvik source code vm/oo/Object.h. Why is there a difference? How is that related to alignment issues?

Short answer: 8 bytes of overhead for any Object (class pointer + lock word), plus 4 or 8 bytes of overhead for the underlying dlmalloc-based heap allocation mechanism. All objects are aligned on 8-byte boundaries, so a 12-byte object will have 4 bytes of padding.
Longer answer.

Related

In android memory monitor, what is the different between `total count` and `heap count`?

In google docs, it said that,heap count means Number of instances in the selected heap,while total count means Total number of instances outstanding.What is the selected heap? Always, the total count is larger than heap count,so ,where is the other objects besides those in heap?
There are 3 heaps in Android:
App
Image
Zygote
Total Count is the total across all 3 heaps. Heap Count is the number of objects in the current selected heap.
See https://developer.android.com/studio/profile/am-hprof.html
total count include the instance in running stack too.
heap count is just in heap size.

What's the difference between the AUDIO_FORMAT_PCM_32_BIT and AUDIO_FORMAT_PCM_8_24_BIT in Android Lollipop?

The AUDIO_FORMAT_PCM_32_BIT and AUDIO_FORMAT_PCM_8_24_BIT are two high definition audio formats in Android Lollipop.
Seems they are all in 32 bit depth.
Who know the exactly difference between them?
You can find that information in audio.h:
/* Audio format consists of a main format field (upper 8 bits) and a sub
format field (lower 24 bits).
AUDIO_FORMAT_PCM_32_BIT and AUDIO_FORMAT_PCM_8_24_BIT are defined as:
AUDIO_FORMAT_PCM_32_BIT = (AUDIO_FORMAT_PCM |
AUDIO_FORMAT_PCM_SUB_32_BIT),
AUDIO_FORMAT_PCM_8_24_BIT = (AUDIO_FORMAT_PCM |
AUDIO_FORMAT_PCM_SUB_8_24_BIT),
And if we look at the definitions of AUDIO_FORMAT_PCM_SUB_32_BIT and AUDIO_FORMAT_PCM_8_24_BIT we find some helpful comments:
AUDIO_FORMAT_PCM_SUB_32_BIT = 0x3, /* PCM signed .31 fixed point */
AUDIO_FORMAT_PCM_SUB_8_24_BIT = 0x4, /* PCM signed 7.24 fixed point */
In response to Michael's comment:
signed .31 means 1 bit for sign, 0 bits for the whole part, and 31 bits for the fractional part. signed 7.24 means 1 bit for sign, 7 bits for the whole part, and 24 bits for the fractional part. Read up on fixed-point arithmetic if you want to know more about how it's used.
AUDIO_FORMAT_PCM_8_24_BIT most likely refers to a padded 8 bits of zeros as the 7.24 fixed point doesn't make sense for PCM data. This is because PCM data ranges from [1.0 .. -1.0]. (it technically should be 8.23, otherwise 7.24 == 25-bits!). So the use of a "whole" [number] part does not make sense.
A single sample of AUDIO_FORMAT_PCM_8_24_BIT will contain 4 bytes, where only 3 bytes will hold any meaningful data and the remaining single byte will be all zeros.
The alternative is AUDIO_FORMAT_PCM_24_BIT_PACKED that only contains 3 bytes per sample and no padding. 24-bit audio has a strange format, and it doesn't fit well in the powers of 2 of digital audio. It is typically easier to handle a 24-bit sample as if it was 32-bit.

Cursor window: window is full

I've created a ListView populated by the data returned from a query.
It works, but in the LogCat I've got the message:
Cursor Window: Window is full: requested allocation 444 bytes, free space 363 bytes, window size 2097152 bytes
and it uses a couple of minutes for loading / visualizing the ListView.
My query returns about 3700 rows of String/Int/Double, each of which with 30 columns; no images or particular datatypes
What does this message exactly mean and how can I avoid it?
Can you improve performances by changing this Cursor Window?
From my experience this means that the query results are too large for the cursor's window and it requests more memory. Most times this request is honored, but on low end devices it could throw exceptions.
I don't know the specifics of the app in question but you referred to a ListView. A ListView cannot show 3700 rows at once and a endless list could help to load the data on demand
My advise is to break up the query into a multiple queries that return smaller results and close them before running the next query. After each successive query combine the results.
Short version:
After some investigation, it appears that this message is part of normal operation, and not a cause for concern. It is logged at the "Warning" level, but I think this is simply overeager.
Longer version:
This is (clearly labelled as) a "Windowed" cursor, which means that old records will be discarded as new records are obtained. In the simplest form, such a "window" implementation may contain up to N rows total, possibly with some read-ahead. In this implementation, however, the window size is defined instead by the total size. The number of rows kept in memory is instead based on how many would fit in the overall window, and will vary at runtime (This could perhaps be considered more of a "buffered" Cursor than "windowed" Cursor).
As a buffered implementation with a (soft-?)capped size, the earliest rows will be discarded only when the buffer is too full to accommodate the next row. In this case, 1 or more older rows are dropped. This "keep allocating rows as-needed until we can no longer have room for more, at which point we free up the oldest record(s) in our buffer and try again" process appears to be completely normal and expected, as a normal part of the process to keep the memory space confined.
I based this conclusion on reading the source here, combined with some inference:
https://android.googlesource.com/platform/frameworks/base/+/master/libs/androidfw/CursorWindow.cpp
Why are people talking about images and other massive LOBs?
If the size of a single row is larger than the entire "window" (buffer), then this strategy breaks down and you have an actual problem.
This was the message #op was getting:
Cursor Window: Window is full: requested allocation 444 bytes, free space 363 bytes, window size 2097152 bytes
This was the message #vovahost was getting:
CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes
In the first case, requested allocation is much smaller than the windows size. I expect that similar messages are issued repeatedly, with the same window size and varying requested allocation sizes. Each time this is printed, memory is freed from the larger window, and new allocations are made. This is normal and healthy operation.
In the second case, requested allocation size exceeds the overall window size. This is an actual problem, requiring storing and reading data in a more streamable way.
The difference is "length" (total number of rows) vs "width" (memory cost of the largest single row). The former (#tirrel's issue) is not an issue, but the latter (#vovahost's issue) is.
I also got this problem. In my case I saved a 2.2 MB image in database. When loading the data from the database using Cursor.getBlob() I would see this message in the Log:
CursorWindow: Window is full: requested allocation 2202504 bytes, free space 2076560 bytes, window size 2097152 bytes
After I would get this message if I try to retrieve any data (String, number, etc) for successive rows it is returned as null without any errors.
The solution was to remove the 2.2 MB blob. I don't know if it's possible to load bigger blobs from database in Android.
Also, note that changing the window has overhead of IPC.
So, if the cursor has large number of items and is used with a listview, fast navigation results in change of window and hence frequent IPCs. This might result in ANR if the system is loaded.

Android Bitmap Pixels - write directly to file?

Background:
The goal is to write a rather large (at least 2048 x 2048 pixels) image file with OpenGL rendered data.
Today I first use glReadPixels in order to get the 32-bit (argb8888) pixel data into an int array.
Then I copy the data into a new short array, converting the 32-bit argb values into 16-bit (rgb565) values. At this point I also turn the image upside down and change the color order to make the opengl-image data compatible with android bitmap data (different row order and color channel order).
Finally I create a Bitmap() instance and .copyPixelsFromBuffer(Buffer b) in order to be able to save it to disk as a png-file.
However I want to use memory more efficient in order to avoid out of memory crashes on some phones.
Question:
Can I skip the first transformation from int[] -> short[] in some way (and avoid the allocation of a new array for pixel data)? Maybe just use byte arrays / buffers and write the converted pixels to the same array I read from...
More important: Can I skip the bitmap creation (here's where the program crash) and somehow write the data directly to disk as a working image file (and avoid allocation of the pixel data again in the bitmap object)?
EDIT: If I could write the data directly to file, maybe I don't need to convert to 16-bit pixel data, depending on the file size and how fast the file can be read into memory at a later point.
I'm not sure that this could help but, this PNGJ library allows to write a PNG sequentially, line by line. If memory usage if your primary concern (and if you can access the pixels values in the order of the final PNG file from the rendered data) it could be useful.

Manipulating 256x256 bitmap crashing android-ndk's JNI

Perhaps I am attempting to do something I ought not.
I'm running a block of code in the emulator. It looks (more or less)
like this: http://pastie.org/1291380
This is to construct a live wallpaper background. I pass in a bitmap,
color palette, and tile array.The size of my bitmap is 256 x 256.
getRedPal / getGreenPal / getBluePal essentially does a call to
Color.red() / Color.green() / Color.blue() in order to get the rgb
color components of a palette object.
The loops chug along; I get all the way to the point where the j value
of drawInC hits 32, before the emulator crashes and burns:
11-11 15:34:44.032: INFO/distort_bmp(598): DrawInC: i: 0 j: 32
11-11 15:34:44.032: INFO/distort_bmp(598): DrawTiles: i: 0 j: 0
11-11 15:34:44.032: INFO/distort_bmp(598): DrawTiles: i: 0 j: 1
11-11 15:34:44.032: INFO/distort_bmp(598): DrawTiles: i: 0 j: 2
11-11 15:34:44.032: INFO/distort_bmp(598): DrawTiles: i: 0 j: 3
11-11 15:34:44.032: INFO/distort_bmp(598): DrawTiles: i: 0 j: 4
After which I get a dump file sent to /data/tombstones . Here is the
dump (but I sincerely don't find anything in it worth any value, just
a bunch of memory addresses): http://pastie.org/1291394
I added android:vmSafeMode="true" to my tag after
reading elsewhere that that could solve a problem. This is on 2.2,
using bitmap.h.
Personally I am dubious of that
jbyte* buffer =
(*env)->GetByteArrayElements(env, arr, &isCopy)
call; I plucked that
code from the net somewhere, as I was totally unable to get values
from my byte array "arr."
Any ideas?
EDIT
After manipulating my loop iterators (I shortened the number of loops), I now get an informative error:
"ReferenceTable overflow (max=512)"
JNI local reference table summary (512 entries):
509 of Ljava/lang/Class; 164B (3 unique)
2 of Ljava/lang/String; 28B (2 unique)
1 of [Ljava/lang/String; 28B
Memory held directly by tracked refs is 576 bytes
Failed adding to JNI local ref table (has 512 entries)
That "509 of java.lang.class" doesn't look too right to me...how can I optimize my code here?
From that error message, it appears that some bit of native code has called a function that returns a Class object, and has done so 509 times. 507 of those calls returned one particular class.
JNI local references let the GC know that native code is looking at an object, and therefore that object can't be collected even if there are no references to it elsewhere. These local refs are released when the native code returns to the VM. If the native code does a lot of work without returning, it's possible to overflow the local ref table.
You probably just need to add a DeleteLocalRef somewhere. My guess is you need to add one at the end of DrawTile, because of the GetObjectClass call. Better yet, move those GetMethodID calls to a one-time setup function. (They do string searches to find the method, making them not especially quick.)
For more info see JNI Tips.
i think this might be a memory problem. do you release the arrays?
if you get arrays with
(*env)->GetByteArrayElements(env, arr, &isCopy)
you must release the array on the c-side it after each procedure or you will fill your memory till you get over the limit (limit size depends on android version and/or manufacturer but is to my knowledge max 48MB per app)
(*env)->ReleaseByteArrayElements(env, arr, &isCopy, 0);
see here: http://www.iam.ubc.ca/guides/javatut99/native1.1/implementing/array.html
btw, this method does copy the arrays from java to a new memory block in c, you work there and at the end its copied back to java (which memory might have been moved to another location till then). for performance improvement you might look at https://groups.google.com/forum/?fromgroups#!msg/android-ndk/phDP5zqiYY4/BFMw4zTme8IJ

Categories

Resources