1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/kerneltest/e32test/defrag/perf/t_perf.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,360 @@
1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// e32test/defrag/perf/t_perf.cpp
1.18 +// t_pagemove loads and opens the logical device driver ("D_PAGEMOVE.LDD").
1.19 +// Following this, it requests that the driver attempt to move various kinds of pages
1.20 +// directly amd notes time taken for each of the moves.
1.21 +// Platforms/Drives/Compatibility:
1.22 +// Hardware only. No defrag support on emulator.
1.23 +// 2 - Test the performance of moving user chunk pages
1.24 +// 3 - Test the performance of moving dll pages
1.25 +// 4 - Test the performance of moving kernel stack pages
1.26 +//
1.27 +//
1.28 +
1.29 +//! @SYMTestCaseID KBASE-T_DEFRAGPERF-0601
1.30 +//! @SYMTestType CT
1.31 +//! @SYMPREQ PREQ308
1.32 +//! @SYMTestCaseDesc Testing performace of page moving
1.33 +//! @SYMTestActions 1 - Test the performance of moving code chunk pages
1.34 +//! @SYMTestExpectedResults Finishes if the system behaves as expected, panics otherwise
1.35 +//! @SYMTestPriority High
1.36 +//! @SYMTestStatus Implemented
1.37 +//--------------------------------------------------------------------------------------------------
1.38 +#define __E32TEST_EXTENSION__
1.39 +#include <e32test.h>
1.40 +#include <e32std.h>
1.41 +#include <e32std_private.h>
1.42 +
1.43 +#include "..\d_pagemove.h"
1.44 +#include "..\..\mmu\mmudetect.h"
1.45 +#include "t_perf.h"
1.46 +
1.47 +
1.48 +LOCAL_D RTest test(_L("T_DEFRAGPERF"));
1.49 +
1.50 +const TPtrC KLddFileName=_L("D_PAGEMOVE.LDD");
1.51 +
1.52 +const TUint KRepetitions=50;
1.53 +const TUint KPageMoves = 2000; // default to moving a page 2000 times
1.54 +
1.55 +
1.56 +TInt gPageSize;
1.57 +
1.58 +#define DEFRAG_CHUNK_MAX (4 * 1024 * 1024)
1.59 +#define DEFRAG_CHUNK_MIN (1 * 1024 * 1024)
1.60 +
1.61 +#define MIN_PROCS 10
1.62 +#define MAX_PROCS 50
1.63 +#define PROC_INCREMENTS 10
1.64 +
1.65 +_LIT(BaseFileName, "t_defragtestperf");
1.66 +_LIT(BaseFileNameExt, ".exe");
1.67 +
1.68 +LOCAL_C void TestUserDataMove(RPageMove& pagemove)
1.69 +{
1.70 + RChunk chunk;
1.71 + TInt size;
1.72 + TInt r = KErrGeneral;
1.73 +
1.74 + DefragLatency timer;
1.75 + timer.CalibrateTimer(test);
1.76 +
1.77 + size = DEFRAG_CHUNK_MAX;
1.78 +
1.79 + while (size > DEFRAG_CHUNK_MIN)
1.80 + {
1.81 + /* Create a local chunk */
1.82 + r = chunk.CreateLocal(size,size);
1.83 + if (r == KErrNone)
1.84 + {
1.85 + TEST_PRINTF(_L("Created %dMB chunk\n"), size/(1024 * 1024));
1.86 + break;
1.87 + }
1.88 + size = size / 2;
1.89 + }
1.90 +
1.91 + test(r == KErrNone);
1.92 +
1.93 + /* Initialise the Chunk */
1.94 + TUint8* base = (TUint8 *)chunk.Base();
1.95 + for (TUint i = 0; i < size/sizeof(*base); i++)
1.96 + {
1.97 + base[i] = i;
1.98 + }
1.99 +
1.100 +
1.101 + TEST_PRINTF(_L("Starting to move chunk pages (%x %d) ...\n"), chunk.Base(), size);
1.102 + TUint j = 0;
1.103 + for (; j < KRepetitions; j++)
1.104 + {
1.105 + TInt size2 = size;
1.106 + base = (TUint8 *)chunk.Base();
1.107 + timer.StartTimer();
1.108 + while (size2)
1.109 + {
1.110 + test_KErrNone(pagemove.TryMovingUserPage(base));
1.111 + base += gPageSize;
1.112 + size2 -= gPageSize;
1.113 + }
1.114 +
1.115 + test(timer.StopTimer(test) > 0);
1.116 + }
1.117 +
1.118 + DTime_t average, max, min, delay;
1.119 + TEST_PRINTF(_L("Finished moving chunk pages\n"));
1.120 + average = timer.GetResult(max, min, delay);
1.121 + test.Printf(_L("Fast counter ticks to move %d chunk pages: Av %d Min %d Max %d (Overhead %d)\n"), size/gPageSize, average, min, max, delay);
1.122 + test.Printf(_L("Average of %d ticks to move one page\n\n"), average / (size/gPageSize));
1.123 +
1.124 + base = (TUint8 *)chunk.Base();
1.125 + for (TUint i = 0; i < size/sizeof(*base); i++)
1.126 + {
1.127 + test_Equal((TUint8)i, base[i]);
1.128 + }
1.129 +}
1.130 +
1.131 +TInt CreateProc(RProcess& aProcess, TInt aIndex)
1.132 + {
1.133 + TFileName filename;
1.134 + TRequestStatus status;
1.135 + TBuf<64> command;
1.136 +
1.137 + filename.Format(_L("%S%S"), &BaseFileName, &BaseFileNameExt);
1.138 + TInt r=aProcess.Create(filename, command);
1.139 +
1.140 + if (r!=KErrNone)
1.141 + {
1.142 + test.Printf(_L("Process %d could not be loaded!\n"), aIndex);
1.143 + return r;
1.144 + }
1.145 +
1.146 + aProcess.Rendezvous(status);
1.147 + aProcess.Resume();
1.148 + User::WaitForRequest(status);
1.149 + return KErrNone;
1.150 + }
1.151 +
1.152 +void KillAllProcs(RProcess *aProcess, TInt aNum, TInt aError)
1.153 + {
1.154 + TInt i;
1.155 + for (i = 0; i < aNum; i++)
1.156 + {
1.157 + aProcess[i].Kill(aError);
1.158 + }
1.159 + }
1.160 +
1.161 +TInt TestDLL(int aNumProcess, RPageMove& aPageMove)
1.162 + {
1.163 + RProcess *process;
1.164 + TInt retVal;
1.165 +
1.166 + process = new RProcess[aNumProcess];
1.167 +
1.168 + if (process == NULL)
1.169 + return KErrGeneral;
1.170 +
1.171 + TEST_PRINTF(_L("Starting %d processes\n"), aNumProcess);
1.172 + for (TInt i = 0; i < aNumProcess; i++)
1.173 + {
1.174 + retVal = CreateProc(process[i], i);
1.175 + if (retVal != KErrNone)
1.176 + {
1.177 + // More Cleanup ?
1.178 + KillAllProcs(process, i, KErrNone);
1.179 + delete[] process;
1.180 + return retVal;
1.181 + }
1.182 + }
1.183 +
1.184 + /* Now Map the DLL to this process and Run the tests */
1.185 + DllDefrag dll;
1.186 + TEST_PRINTF(_L("Main Proc Loading The DLL ... \n"));
1.187 + retVal = dll.LoadTheLib(0, test);
1.188 +
1.189 + if (retVal != KErrNone)
1.190 + {
1.191 + KillAllProcs(process, aNumProcess, retVal);
1.192 + test.Printf(_L("Error (%d) Loading The DLLs!\n"), retVal);
1.193 + delete[] process;
1.194 + return KErrGeneral;
1.195 + }
1.196 +
1.197 + retVal = dll.TestDLLPerformance(0, aPageMove, test);
1.198 + KillAllProcs(process, aNumProcess, KErrNone);
1.199 + delete[] process;
1.200 +
1.201 + return retVal;
1.202 + }
1.203 +
1.204 +/*
1.205 + * Is this portable .. Hell No, so dont ask.
1.206 + */
1.207 +#define isNum(a) ((a) >= '0' && (a) <= '9')
1.208 +
1.209 +TInt atoi(const TBuf<64>& buf, TInt pos)
1.210 + {
1.211 + TInt i = pos;
1.212 + TInt num = 0;
1.213 + TInt len = User::CommandLineLength();
1.214 + while(i < len)
1.215 + {
1.216 + TInt8 ch = buf[i++];
1.217 + if (!isNum(ch))
1.218 + {
1.219 + test.Printf(_L("Invalid Argument!\n"));
1.220 + return KErrGeneral;
1.221 + }
1.222 + num = (num * 10) + (ch - '0');
1.223 + }
1.224 + return num;
1.225 + }
1.226 +
1.227 +void TestCodeChunkMoving(RPageMove aPageMove)
1.228 + {
1.229 + _LIT(ELOCL_DEFAULT, "");
1.230 + _LIT(ELOCLUS, "T_LOCLUS_RAM");
1.231 +
1.232 + // Change locale and move the locale page repeatedly
1.233 + // On multiple memmodel this is the easiest way to move CodeChunk pages.
1.234 +
1.235 +
1.236 + // Setup the RAM loaded US Locale DLL
1.237 + test_KErrNone(UserSvr::ChangeLocale(ELOCLUS));
1.238 + TLocale locale;
1.239 + locale.Refresh();
1.240 +
1.241 +
1.242 + // Now get a pointer to some data in the DLL. This will be used to move a
1.243 + // page from the dll
1.244 + SLocaleLanguage localeLanguage;
1.245 + TPckg<SLocaleLanguage> localeLanguageBuf(localeLanguage);
1.246 + TInt r = RProperty::Get(KUidSystemCategory, KLocaleLanguageKey, localeLanguageBuf);
1.247 + test_KErrNone(r);
1.248 + TAny* localeAddr = (TAny *) localeLanguage.iDateSuffixTable;
1.249 + test(localeAddr != NULL);
1.250 +
1.251 +
1.252 + // Now we have a RAM loaded locale page determine the performance
1.253 + TEST_PRINTF(_L("Start moving a RAM loaded locale page\n"));
1.254 + // Setup the timer
1.255 + DefragLatency timer;
1.256 + timer.CalibrateTimer(test);
1.257 + TUint reps = 0;
1.258 + for (; reps < KRepetitions; reps++)
1.259 + {
1.260 + timer.StartTimer();
1.261 + TUint i = 0;
1.262 + for (; i < KPageMoves; i++)
1.263 + {
1.264 + test_KErrNone(aPageMove.TryMovingLocaleDll(localeAddr));
1.265 + }
1.266 + test_Compare(timer.StopTimer(test), >, 0);
1.267 + }
1.268 + DTime_t max, min, delay;
1.269 + TUint average = timer.GetResult(max, min, delay);
1.270 + test.Printf(_L("Fast counter ticks to move code chunk page %d times: Av %d Min %d Max %d (Overhead %d)\n"), KPageMoves, average, min, max, delay);
1.271 + test.Printf(_L("Average of %d ticks to move one page\n\n"), average/ KPageMoves);
1.272 +
1.273 +
1.274 + // Reset the Locale to the default
1.275 + r=UserSvr::ChangeLocale(ELOCL_DEFAULT);
1.276 + test(r==KErrNone);
1.277 + locale.Refresh();
1.278 + }
1.279 +
1.280 +GLDEF_C TInt E32Main()
1.281 + {
1.282 + test.Title();
1.283 + TInt procs = 1;
1.284 + _LIT(KStart,"-procs=");
1.285 + const TInt offset = KStart().Length();
1.286 +
1.287 + TBuf<64> cmd;
1.288 + User::CommandLine(cmd);
1.289 +
1.290 + if (!HaveMMU())
1.291 + {
1.292 + test.Printf(_L("This test requires an MMU\n"));
1.293 + return KErrNone;
1.294 + }
1.295 + test.Start(_L("Load test LDD"));
1.296 + TInt r=User::LoadLogicalDevice(KLddFileName);
1.297 + test(r==KErrNone || r==KErrAlreadyExists);
1.298 +
1.299 + r=UserHal::PageSizeInBytes(gPageSize);
1.300 + test_KErrNone(r);
1.301 +
1.302 + RPageMove pagemove;
1.303 + test.Next(_L("Open test LDD"));
1.304 + r=pagemove.Open();
1.305 + test_KErrNone(r);
1.306 +
1.307 + DefragLatency timer;
1.308 + timer.CalibrateTimer(test);
1.309 + test.Printf(_L("\nFast Counter Frequency = %dHz \n\n"), timer.iFastCounterFreq);
1.310 +
1.311 +
1.312 + test.Next(_L("Test performance of moving code chunk pages"));
1.313 + TestCodeChunkMoving(pagemove);
1.314 +
1.315 + /*
1.316 + * Test User Data.
1.317 + * Create a large chunk ~ 4MB (> L2 Cache) and move pages from that chunk
1.318 + */
1.319 + test.Next(_L("Test performance of moving user chunk pages"));
1.320 + TestUserDataMove(pagemove);
1.321 +
1.322 + /* Test DLL Move */
1.323 + test.Next(_L("Test performance of moving dll pages"));
1.324 + TInt pos = cmd.FindF(KStart);
1.325 + if (pos >= 0)
1.326 + {
1.327 + pos += offset;
1.328 + procs = atoi(cmd, pos);
1.329 + }
1.330 +
1.331 + if (procs < MIN_PROCS)
1.332 + procs = MIN_PROCS;
1.333 + else if (procs > MAX_PROCS)
1.334 + procs = MAX_PROCS;
1.335 +
1.336 + for (TInt i = 1; ; )
1.337 + {
1.338 + test.Printf(_L("Testing with %d Processes mapping a DLL\n"), i);
1.339 + TestDLL(i, pagemove);
1.340 +
1.341 + if (i >= procs)
1.342 + break;
1.343 +
1.344 + if (i + PROC_INCREMENTS >= procs)
1.345 + i = procs;
1.346 + else
1.347 + i += PROC_INCREMENTS;
1.348 + }
1.349 +
1.350 + if ((MemModelAttributes()&EMemModelTypeMask) != EMemModelTypeFlexible)
1.351 + {
1.352 + test.Next(_L("Test performance of moving kernel stack pages"));
1.353 + r = pagemove.TestKernelDataMovePerformance();
1.354 + test_KErrNone(r);
1.355 + }
1.356 +
1.357 + test.Next(_L("Close test LDD"));
1.358 +
1.359 + pagemove.Close();
1.360 + User::FreeLogicalDevice(KLddFileName);
1.361 + test.End();
1.362 + return(KErrNone);
1.363 + }