Simulating LowMem (low memory stress tool) on the emulator

Login to reply to this topic.
Wed, 2006-12-20 23:10
Joined: 2004-05-29
Forum posts: 149
1. Is there a version of LowMem for the emulator?

Since I'm pretty sure the answer is no,
2. Has anyone been successful trying to mimic having low memory on the stress test?  I tried doing this:

Code:
#ifdef MEMORY_STRESS
// Memory-stress tool
const TInt onlyFreeSpace = 2000;
TInt biggestBlock;
TInt avail = User::Available(biggestBlock);

RDebug::Print(_L(" 1Available: %d   Biggest block: %d"), avail, biggestBlock);

// Can't allocate more than (KMaxTInt/2)
while (avail > ( KMaxTInt/2 ) + onlyFreeSpace)
{
User::Alloc( 0x3FFF0000 );
avail = User::Available(biggestBlock);
RDebug::Print(_L(" 2Available: %d   Biggest block: %d"), avail, biggestBlock);
}

iDebugHeap = User::Alloc(avail - onlyFreeSpace);
avail = User::Available(biggestBlock);

RDebug::Print(_L(" 3Available: %d   Biggest block: %d"), avail, biggestBlock);
#endif

The above should allocate until there is only onlyFreeSpace bytes left of heap space available.  However, this doesn't seem to do as intended.  It does seem to print out the correct information:
   1Available: 55980   Biggest block: 55608
   3Available: 1988   Biggest block: 1616

But then later calls to User::Available() shows that there is more heap space again.  This memory is NOT freed here, so it doesn't make sense.  Either User::Available() isn't returning what I think it is, or the emulator is always giving me as much memory as I want.

Any suggestions?

Thu, 2006-12-21 14:24
Joined: 2004-11-29
Forum posts: 1134
Re: Simulating LowMem (low memory stress tool) on the emulator
Havn't used these functions, but from reading the documentation, maybe the problem is it gives the _current_ max, not counting in that your heap may expand.

A thread has a min and a max limit for its heap, when the thread is started, it gets the min size of the heap, and if a call to alloc doesn't fit, it will expand it, in increments, until it hits the max limit.

So if it hasn't expanded yet when you call that function, and then the next allocation will make it expand, you would get the result you are experiencing.



Thu, 2006-12-21 15:05
Forum Nokia Champion
Joined: 2004-08-31
Forum posts: 30
Re: Simulating LowMem (low memory stress tool) on the emulator
The correct way is to spawn a thread to run the application in. When creating the thread, you specify the maximum heap.

On 9.1, you have to add support code to your application's E32Main. I do it like:

Code:
// in the tester
RChunk heapc;
User::LeaveIfError(heapc.CreateGlobal(KHeapName, 20, 20));
CleanupClosePushL(heapc); pushed++;
TInt *heapp=(TInt*)heapc.Base();
*heapp=iCurrentMaxHeapSize;
RProcess thread;
TInt err=thread.Create(KExeName, KNullDesC);

// in the app
TInt RunApplication(TAny*)
{
        return EikStart::RunApplication(NewApplication);
}

GLDEF_C TInt E32Main()
    {
    RChunk heapc;
    TInt err=heapc.OpenGlobal(_L("contextcontacts_heap"), ETrue);
    if (err!=KErrNone) {
        return EikStart::RunApplication(NewApplication);
    }
        RThread thread;
        TInt heap=*(TInt*)heapc.Base();
        heapc.Close();
        err=thread.Create(_L("contextcontacts2"),
                &RunApplication, // thread's main function
                20*1024, /* stack */
                heap, /* min heap */
                heap, /* max heap */
                0,
                EOwnerProcess);
        if (err!=KErrNone) return err;
        thread.SetPriority(EPriorityNormal);
        TRequestStatus s;
        thread.Logon(s);
        thread.Resume();
        User::WaitForRequest(s);
        TExitCategoryName n=thread.ExitCategory();
        TInt reason=thread.ExitReason();
        TExitType exittype=thread.ExitType();
        thread.Close();
        if (exittype==EExitPanic) {
                RDebug::Print( n );
                User::Panic( n, reason);
        }
        return reason;
}

On pre-9.1, you can fully encapsulate the code in the tester:
Code:
void run_app_inner()
{
        TInt pushed=0;

        TFileName fn=_L("z:\\system\\apps\\context_log\\context_log.app");
        CApaCommandLine* cmd=CApaCommandLine::NewL(fn);
        /* RunAppInsideThread deletes the command line */
        EikDll::RunAppInsideThread(cmd);

        CleanupStack::PopAndDestroy(pushed);
}

TInt run_app(TAny*)
{
        CTrapCleanup* cleanupStack = CTrapCleanup::New();
        TRAPD(err, run_app_inner());
        delete cleanupStack;
        return err;
}

// and then
                RThread thread;
                TInt err=thread.Create(_L("context_log"),
                        &run_app, // thread's main function
                        20*1024, /* stack */
                        0,  // parameters
                        0,
                        NULL,
                        heap, /* min heap */
                        heap, /* max heap */
                        EOwnerProcess);

On both you then follow in the tester with:
Code:
                User::LeaveIfError(err);
                thread.SetPriority(EPriorityNormal);
                TRequestStatus s;
                thread.Logon(s);
                thread.Resume();
                User::WaitForRequest(s);
                msg=_L8(" done: ");
                msg.Append(thread.ExitCategory());
                msg.Append(_L8(" "));
                msg.AppendNum(thread.ExitReason());
                msg.Append(_L8("\n"));

That's the basic idea.
Thu, 2007-01-04 22:11
Joined: 2004-05-29
Forum posts: 149
Re: Simulating LowMem (low memory stress tool) on the emulator
Thanks for the great advice! I have an exciting program which simulates the LowMem app on the emulator now.  (Sometimes you can see when something fails within their code due to low memory, but which would normally work perfectly given enough memory... looks like at least the emulator version of the OS needs some better error handling!)

There's only one thing, though.  With the actual LowMem app given by Symbian, when the app runs out of memory and a message box appears saying "Out of memory", the LowMem app steals back the focus and asks you if you want to continue the test.  So, obviously the LowMem app is aware when the thread has run out of memory.  LowMem will close down the app (I can see my destructors being called on the device because of log files).

My app in particular is tricky because there is an APP and a LIB, and also the LIB uses networking.  It seems as if both the GUI code in the APP, and the networking code in the LIB are running out simultaneously (they're active objects after all).

Well, the exception handling of RThread probably doesn't work on the emulator (because windows always catches things like access violations).  At least, I tried it.  So, in my version of the LowMem tool I run the threads as an active object, with another timer active object in the background.  If the thread hasn't ended normally after 15 seconds, the timer shuts it down with either a RThread::Kill() or a RThread::Terminate() call.  (I've tried them both, they both seem to do exactly the same thing)

The problem is, RThread::Kill and Terminate immediately stop the thread... no destructors are called.  Does anyone have any idea how LowMem does it?  i.e. forces the app to shut down when you tell it to continue the test?  Because that's where my app is causing KERN-EXEC 3 errors on the device.

Thanks,
-euroq
Mon, 2007-01-08 08:42
Forum Nokia Champion
Joined: 2004-08-31
Forum posts: 30
Re: Simulating LowMem (low memory stress tool) on the emulator
You shouldn't get an access violation (although you will, if the framework code runs out of memory).

Your app should exit with -4 if it runs out of memory and can't recover. I couldn't actually run my app on the 3rd edition satisfactorily, since the framework code crashes so easily, so you'll have to investigate how to properly propagate the error yourself.
  • Login to reply to this topic.