I noticed an odd memory increase in one of my Activities. Hence I ran a little test: I opened the dialog multiple times (open - close - open - close ....) and the memory kept increasing. So I used the DDMS to dump an HPROF file and opened it in MAT (Memory analyzer). The leak suspect report indicated, that the main reason for the growing memory consumption was this:
So I did a histogramm, to check that dialog I ran my tests on and what's keeping it alive. Turns out, it's kept alive by it's AutoCompleteTextViews, which in turn are kept alive by android.widget.TextView$IClipboardDataPasteEventImpl. However there are no immediate dominators for IClipboardDataPasteEventImpl (except of course the GC Root). I tried to find that IClipboardDataPasteEventImpl on the internet and I searched grepcode (the android source), but the only thing I could come up with was this blog entry. I can't read whatever language that is, but what I could read are the English words thrown in, which indicates, that it might be a bug on the Samsung Galaxy SII (the phone I am using, running android 2.3.x), related to the ClipboardManager. However I am unsure of this (I want to fix this, hence I am disinclined to simply accept it to be an unfixable bug) and I have no clue, where this Clipboard is spawned and why. I would greatly appreciate any pointers/ideas on the matter.
Investigation
Here're my research results:
It happens to any Activity whose content view consists of an EditText. finish()ing the Activity does not get it garbage collected as it is being referenced, like this:
activity com.example.MyActivity
<- mContext android.widget.TextView
<- this$0 android.widget.TextView$IClipboardDataPasteEventImpl
<- this$1 android.widget.TextView$IClipboardDataPasteEventImpl$1
<- referent java.lang.ref.FinalizerReference
It happens on my Samsung Galaxy Tab GT-P7300 running Android 4.0.4, but not on my Samsung Galaxy Mini GT-S5570 running Android 2.2.1.
The IClipboardDataPasteEventImpl objects eventually get freed, actually, but only at times which seems to be unpredictable.
Since they are referenced by java.lang.ref.FinalizerReference, I believe that the IClipboardDataPasteEventImpl objects are waiting to be finalize()'d, which happens only when the JVM feels like to. For details, check out these SO questions:
is memory leak? why java.lang.ref.Finalizer eat so much memory
Very strange OutOfMemoryError
Solution / Workaround
Sorry, no solution, but here's my best workaround:
In onDestroy() of your Activity, free as many references to other objects as possible (especially the big ones, such as bitmaps, collections, and child views of your activity), like this:
#Override
protected void onDestroy()
{
// Free reference to large objects.
m_SomeLargeObject = null;
m_AnotherLargeObject = null;
// For ArrayList, if you are a paranoid to null, you may call clear() and then trimToSize().
m_SomeLargeArrayList.clear();
m_SomeLargeArrayList.trimToSize();
// Free child views.
m_MyButton = null;
// Free adapters.
m_ListViewAdapter = null;
... etc.
// Don't forget to chain the call to the superclass.
super.onDestroy();
}
This way, we can at least reduce the casualties and hopefully won't go out of memory before the JVM has the mood to finialize and collect all those evil IClipboardDataPasteEventImpl objects.
In an ideal world of garbage collected environment, this would be unnecessary, but I guess we should all realize that our world is not perfect, and we just have to live with the flaws.
Below is my translation of the original blog entry (in Chinese) as mentioned in the question. Hopefully this can give everybody a better understanding about the issue.
Galaxy S2 memory leak with TextView
不知道是不是哪邊弄錯
Not sure where it went wrong
但是galaxy s2的textview會產生memory leak
But the textview of galaxy s2 causes memory leaks
leak是發生在android.widget.TextView$IClipboardDataPasteEventImpl這個interface上
Leak happens on the interface android.widget.TextView$IClipboardDataPasteEventImpl
它會抓住mContext造成整個activity沒辦法被gc
It holds the mContext, stopping the activity from being gc'ed
同樣的程式在htc sensation(2.3.4)跟se xperia arc(2.3.4)和acer liquid(2.1)都沒有問題
No such problem with the same app on htc sensation(2.3.4), se xperia arc(2.3.4) and acer liquid(2.1)
而且網路上完全找不到android.widget.TextView$IClipboardDataPasteEventImpl相關的資料
And, I can't find anything related to android.widget.TextView$IClipboardDataPasteEventImpl on the web at all
android source code裡也找不到 看起來應該是samsung自己加的東西...
Not even in the android source code, so it seems to be something added by samsung themselves...
之前的opengl viewport bug 已經夠頭痛了 接下來soundpool相關bug也搞累很多人
The opengl viewport bug was a headache already, and the soundpool related bug had frustrated many
現在這個memory leak又來攪局...
And now, here comes a memory leak messing around...
看來手機外型還是比較重要 /_\... 外型好先吸到人來買 bug再慢慢修就好
Seems that the appearance of mobile phones are more important /_\... good appearance attracts customers; bugs could be fixed later
[後記]
[P.S.]
經過一些試驗發現 只要按HOME button回到桌面,那些leak就會被釋放掉...
After some tests, I found out that the leaks will be freed by pressing the HOME button to go back to the desktop...
logcat會顯示一行Hide Clipboard dialog at Starting input: finished by someone else... !
It shows Hide Clipboard dialog at Starting input: finished by someone else... ! in logcat
看起來galaxy s2裡面有偷偷對clipboard作一些操作...
It seems that galaxy s2 is operating on the clipboard under the hood...
但如果一直保持在app裡面運作的話,那些leak還是會存在...最後應該會發生OOM exception
But if we stay in the app, those leaks remain... eventually an OOM exception would occur
現在只能期望galaxy s2 的ics版會修掉這個怪問題了...
Now we can only hope that this strange problem would be resolved in the ics version of galaxy s2...
My memleak investigation also brought me here. Im having problems with Activity leaking over EditText. android.widget.TextView$IClipboardDataPasteEventImpl object is holding the EditText which is holding the activity. This happens on Samsung Galaxy Tab 10.1, and Galaxy Tab 2 10.1, 7.0. I wasn't able to reproduce it on other non Samsung devices (Asus, Acer).
The bad thing is that I didn't find a solution for it yet :)
Related
I am having issues with HLS playback using the media player library at least since v0.3.0 which continue until the current version (v0.5.0). I know the player library is in beta so I am wondering if others see what I see.
Basically, the issue manifests itself in such a way that, after some time, Chromecast device becomes unresponsive. The debugger stops showing any output, closing it and attempting to access it again results in a timeout error. Sometimes, after some time, device just crashes to homescreen (no brainfreeze).
I tried looking at the profiles and timeline before this happens and I don't see any unusual spikes. I did notice some errors in the log (but they could be unrelated to this), saying something like:
An attempt was made to use an object that is not, or is no longer, usable
The only "unusual" thing I am doing is that I broadcast status on every video timeupdate event. This does not cause any such issues in normal playback though.
Hoping that you already fixed that, I come with a workaround for people having the same problem.
I have a receiver streaming HLS (correctly encoded, using CORS headers and AES encryption). I noticed that sometimes the Chromecast goes crazy with huge segments (>25Mo) driving it to crash (almost) randomly when appending the latter segment.
Believing that I was probably asking too much of this small device, there are two solutions to lower the device load :
Disabling AES encryption (not always acceptable)
Reducing the segments quality
About solution 2, this works well :
window.host = new cast.player.api.Host({'mediaElement':mediaElement, 'url':url});
window.protocol = cast.player.api.CreateHlsStreamingProtocol( host );
window.host.getQualityLevel = function(streamIndex, qualityLevel){
var lowestQuality = protocol.getStreamInfo()["bitrates"].length-1;
var plusOneQuality = (qualityLevel == lowestQuality)?qualityLevel:qualityLevel+1;
console.log( "original QualityLevel : " + qualityLevel, "returned QualityLevel", plusOneQuality );
return plusOneQuality;
}
I'd love having some feedback about this. Does someone already had to use such a trick to prevent HLS HD streaming to crash the device ?
I implemented a loop with up to 100fps and can not spend more than 63fps.
What I believe is that the thread that runs the method of drawing opengl has a speed limit.
"(
#Override
public void onDrawFrame(GL10 gl)
)"
It depends on whether or not your rendering context has vertical sync enabled. Most LCD devices refresh at 60hz, and it may be waiting for the next refresh to call onDrawFrame(). That's one reason you'd be seeing that number.
The other possibility is that your draw is just taking long enough that it can't run any faster.
You should read the spec, for eglSwapInterval. It has to be implemented in your driver (I presume this is an Android device) to be able to see the effect. You can use it in any OpenGLES2 based application.
http://www.khronos.org/registry/egl/sdk/docs/man/xhtml/eglSwapInterval.html
A gist showing the usage here:
https://gist.github.com/prabindh/8467984
I am trying to capture a screen shot on the ipad while the camera is on. My code looks exactly like the AVCaptureFrames from the Xamarin MonoTouch sample:
For some reason, though, I keep getting an Invalid Handler Exception. I have looked at other questions similar to mine, such as:
CGBitmapContext in MonoTouch throws invalid handle exception and "Invalid Handle" Create CGBitmapContext
But their solutions aren't solving my similar problem. My issue doesn't stem from a sending in null or because my memory is too large. I'm not sending in a null value and I checked my memory usage through the xcode allocations instrument and my memory usage doesn't explode; it only adds 400KB at the most.
I'm developing an app (XNA Game) for the XBOX, which is a pretty simple app. The startpage contains tiles with moving gif images. Those gif images are actually all png images, which gets loaded once by every tile, and put in an array. Then, using a defined delay, these images are played (using a counter which increases every time a delay passes).
This all works well, however, I noticed some small lag every x seconds in the movement of the GIF images. I then started to add some benchmarking stuff:
http://gyazo.com/f5fe0da3ff81bd45c0c52d963feb91d8
As you can see, the FPS is pretty low for such a simple program (This is in debug, when running the app from the Xbox itself, I get an avg of 62fps).
2 important settings:
Graphics.SynchronizeWithVerticalRetrace = false;
IsFixedTimeStep = false;
Changing isFixedTimeStep to true increases the lag. The settings tile has wheels which rotate, and you can see the wheels go back a little every x seconds. The same counts for SynchronizeWVR, also increases lag.
I noticed a connection between the lag and the moment the garbage collector kicks in, every time it kicks in, there is a lag...
Don't mind the MAX HMU(Heap memory usage), as this is takes the amount of the start, the avg is more realistic.
Here is another screen from the performance monitor, however I don't understand much from this tool, first time I'm using it... Hope it helps:
http://gyazo.com/f70a3d400657ac61e6e9f2caaaf17587
After a little research I found the culprit.
I have custom components that all derive from GameComponent, and who get added to the Component list of the main Game class.
This was one (of a total of 2) major problem, causing to update everything that wasn't needing an update. (The draw method was the only one who kept the page state in mind, and only drew if needed).
I fixed this by using different "screens" (or pages as I called them), wich are the only components who derive from GameComponent.
Then I only update the page wich is active, and the custom components on that page also get updated. Problem fixed.
The second big problem, is the following;
I made a class which helps me on positioning stuff on the screen, relative that is, with percentages and stuff like that. Parent containers, aligns & v-aligns etc etc.
That class had properties, for size & vectors, but instead of saving the calculated value in a backing field, I recalculated them everytime I accessed a property. But calculating complex stuff like that uses references (to parent & child containers for example) wich made it very hard for the CLR, because it had alot of work to do.
I now rebuilt the whole positioning class to a fully functional optimized class, with different flags for recalculating when necessairy, and instead of drops of 20fps, I now get an average of 170+fps!
I'm finding CG appears to have a memory leak. I submitted a report via nvidia.com, but if you try this here:
If you remove the line that says
cgD3D11SetTextureParameter( g.theTexture, g.sharedTex ) ;
The leak stops.
Does CG 3.0 really leak?
Using ATI Radeon 5850 GPU / Windows 7 64-bit.
Yes, it leaks. Internally it creates a ShaderResourceView on every call, and never releases it. I think the API is ill-designed, they should have taken a ShaderResourceView* as a parameter to this function, instead of just a Resource*.
I posted about this on nvidia forums about 6 months ago and never got a response
Is your report posted publicly? Or some kind of private support ticket?
Yes, Cg 3.0 leaks every time you call cgD3D11SetTextureParameter(), causing your application's memory usage to climb. Unfortunately it makes Cg 3.0 with D3D11 completely unusable. One symptom of this is that, after a while of your application running, it will stop rendering and the screen will just go black. I wasted a lot of time trying to determine the cause of this before discovering the Cg bug.
If anybody is wondering why this isn't apparent with the Cg D3D11 demos, its because the few that actually use textures are so simple that they can get away with only calling cgD3D11SetTextureParameter() once at the start.
This same bug remains with Cg Toolkit 3.1 (April 2012).
jmp [UPDATE] ;; skip obsolete text segment
Could it be that Cg is being destroyed after d3d so it doesn't release the reference on time? Or vice-versa? such as the function acquiring the texture but not releasing it before d3d closes, because when you set a texture to a shader, the texture is acquired until shader resources are released somehow. You are destroying the d3d context, here:
SAFE_RELEASE( g.d3d );
SAFE_RELEASE( g.gpu );
Later on, you free the shader, as follows CleanupCg():
cgDestroyProgram( g.v_vncShader );
checkForCgError( "destroying vertex program" );
cgDestroyProgram( g.px_vncShader );
checkForCgError( "destroying fragment program" );
Try to change the order of the calls in a way you first release all resources from both cg and d3d, this: cgD3D11SetDevice( g.cgContext, NULL ); should also be called before releasing the d3d context, just in case.
UPDATE:
This should be different inside WinMain():
initD3D11() ; // << FIRST you init D3D
initCg() ; // << SECOND you init CG with the D3D pointers
initD2D1() ; //
initVBs() ;
// Main message loop
while( WM_QUIT != msg.message ){ /* loop code */ }
CleanupDevice(); //// << FIRST you release all D3D, when Cg is still referencing it (why?).
CleanupCg(); //// << SECOND if something in the Cg runtime depend on d3dcontext which you just destroyed, it will crash or leak or do whatever it wants
so you should swap them to ensure Cg to free any d3d pointer:
CleanupCg(); //// << FIRST release Cg to ensure it's not referencing D3D anymore.
CleanupDevice(); //// << SECOND D3D isn't either referencing or being referenced by Cg, so just release it all
You could also provide the debugger output and other info as I asked down there, because you're basically saying "Cg seems to be broken, this is the whole code, look the line ###, is it broken?" but there are more than a thousand lines (1012) of C, C++ and shader code in your file, you basically provide no info but readily point to a Cg bug (based on... what?) which of course, if you're so sure, why would anyone look at the code if the code is fine? Which isn't by the way, not that I don't like it but... it got these little things such as the call ordering which are silly mistakes but that can make debugging a real hell, it's a clear bug, and I may also think that if I just looked into Main and found a bug, well there is a long way up to the render call and the Cg implementation, isn't it? I can't run the app on WinXP, but these errors are in the most predictable places :)
So... when your code is clean of any bug... ohh! look! what I've just found..
~VertexBuffer()
{
SAFE_RELEASE( vb );
SAFE_RELEASE( layout ) ;
}
turns out in VertexBuffer constructor you call iD3D->GetImmediateContext( &gpu ); and store the pointer in a private member, so... shouldn't you add:
SAFE_RELEASE( gpu ); // ? there are 3 VertexBuffers instances, so that's another memory leak.
Ok so there are some things you should fix in your code that cause memory leaks, and I just took a look on it, so you didn't really try. On the other hand, it seems your code is clear and full of explanations and I need to learn some DX11, so actually I should thank you for it. The downvote was somewhat rude though :P specially because I'm probably right, and other people would avoid reading your code as soon as the page displays.