sl@0
|
1 |
// Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
|
sl@0
|
2 |
// All rights reserved.
|
sl@0
|
3 |
// This component and the accompanying materials are made available
|
sl@0
|
4 |
// under the terms of the License "Eclipse Public License v1.0"
|
sl@0
|
5 |
// which accompanies this distribution, and is available
|
sl@0
|
6 |
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
|
sl@0
|
7 |
//
|
sl@0
|
8 |
// Initial Contributors:
|
sl@0
|
9 |
// Nokia Corporation - initial contribution.
|
sl@0
|
10 |
//
|
sl@0
|
11 |
// Contributors:
|
sl@0
|
12 |
//
|
sl@0
|
13 |
// Description:
|
sl@0
|
14 |
// e32test\bench\t_membm.cpp
|
sl@0
|
15 |
//
|
sl@0
|
16 |
//
|
sl@0
|
17 |
|
sl@0
|
18 |
#include <e32std.h>
|
sl@0
|
19 |
#include <e32std_private.h>
|
sl@0
|
20 |
#include <e32base.h>
|
sl@0
|
21 |
#include <e32base_private.h>
|
sl@0
|
22 |
#include <e32test.h>
|
sl@0
|
23 |
#include <e32svr.h>
|
sl@0
|
24 |
|
sl@0
|
25 |
#define ALIGN_UP(x, y) (TInt8*)(_ALIGN_UP((TInt)(x), (y)))
|
sl@0
|
26 |
#define ALIGN_DOWN(x, y) (TInt8*)(_ALIGN_DOWN((TInt)(x), (y)))
|
sl@0
|
27 |
|
sl@0
|
28 |
const TInt KHeapSize=720*1024;
|
sl@0
|
29 |
const TInt KAverageOverInMilliseconds=500;
|
sl@0
|
30 |
const TInt Len64K = 64*1024;
|
sl@0
|
31 |
|
sl@0
|
32 |
volatile TInt count;
|
sl@0
|
33 |
volatile TInt iters;
|
sl@0
|
34 |
|
sl@0
|
35 |
TInt8* trg;
|
sl@0
|
36 |
TInt8* src;
|
sl@0
|
37 |
TInt8* dummy;
|
sl@0
|
38 |
TInt8 trgoffset;
|
sl@0
|
39 |
TInt8 srcoffset;
|
sl@0
|
40 |
TInt len=64*1024;
|
sl@0
|
41 |
TInt64 result;
|
sl@0
|
42 |
|
sl@0
|
43 |
RTest test(_L("T_MEMBM"));
|
sl@0
|
44 |
|
sl@0
|
45 |
GLREF_C TInt MemBaseline(TAny*);
|
sl@0
|
46 |
GLREF_C TInt MemCopy(TAny*);
|
sl@0
|
47 |
GLREF_C TInt MemMove(TAny*);
|
sl@0
|
48 |
GLREF_C TInt MemFill(TAny*);
|
sl@0
|
49 |
GLREF_C TInt MemSwap(TAny*);
|
sl@0
|
50 |
GLREF_C TInt WordMove(TAny*);
|
sl@0
|
51 |
GLREF_C TInt MemCopyUncached(TAny*);
|
sl@0
|
52 |
GLREF_C TInt WordMoveUncached(TAny*);
|
sl@0
|
53 |
GLREF_C TInt MemFillUncached(TAny*);
|
sl@0
|
54 |
GLREF_C TInt PurgeCache();
|
sl@0
|
55 |
|
sl@0
|
56 |
TInt nextLen(TInt aTestLength)
|
sl@0
|
57 |
{
|
sl@0
|
58 |
if (len == Len64K)
|
sl@0
|
59 |
return 0;
|
sl@0
|
60 |
if (!aTestLength)
|
sl@0
|
61 |
return Len64K;
|
sl@0
|
62 |
|
sl@0
|
63 |
TInt inc = aTestLength;
|
sl@0
|
64 |
for (TInt i = len >> 5 ; i ; i >>= 1)
|
sl@0
|
65 |
inc <<= 1;
|
sl@0
|
66 |
|
sl@0
|
67 |
return len + inc;
|
sl@0
|
68 |
}
|
sl@0
|
69 |
|
sl@0
|
70 |
/**
|
sl@0
|
71 |
* Run benchmarks on the supplied function.
|
sl@0
|
72 |
*
|
sl@0
|
73 |
* @param aFunction The function to benchmark
|
sl@0
|
74 |
* @param aTestBackwards Run copy tests with overlapping areas to test backwards copy
|
sl@0
|
75 |
* @param aTestSrcAlign Run tests for source alignments 0 - 31
|
sl@0
|
76 |
* @param aTestDestAlign Run tests for destination alignments 0 - 31
|
sl@0
|
77 |
* @param aTestLength If non-zero, run tests for different lengths starting at aTestLength
|
sl@0
|
78 |
*/
|
sl@0
|
79 |
TInt64 runTest(TThreadFunction aFunction,const TDesC& aTitle, TBool aTestBackwards, TBool aTestSrcAlign, TBool aTestDestAlign, TInt aTestLength)
|
sl@0
|
80 |
{
|
sl@0
|
81 |
TInt8* buffer = (TInt8*)User::Alloc(640 * 1024 + 32);
|
sl@0
|
82 |
test(buffer != 0);
|
sl@0
|
83 |
|
sl@0
|
84 |
test(!(aTestLength && aTestBackwards)); // not supported
|
sl@0
|
85 |
|
sl@0
|
86 |
TBool goingforward=ETrue;
|
sl@0
|
87 |
|
sl@0
|
88 |
FOREVER
|
sl@0
|
89 |
{
|
sl@0
|
90 |
if (aTestLength)
|
sl@0
|
91 |
test.Printf(_L("Running length experiment on %S. Results follow:\n"), &aTitle);
|
sl@0
|
92 |
|
sl@0
|
93 |
len = 0;
|
sl@0
|
94 |
while(len = nextLen(aTestLength), len)
|
sl@0
|
95 |
{
|
sl@0
|
96 |
src = ALIGN_UP(buffer, 32);
|
sl@0
|
97 |
if (goingforward)
|
sl@0
|
98 |
trg = src + 512 * 1024; // blow half a meg
|
sl@0
|
99 |
else
|
sl@0
|
100 |
trg = ALIGN_DOWN(src + len - 1, 32); // ensure overlapping, doesn't work for length < 32
|
sl@0
|
101 |
|
sl@0
|
102 |
if (aTestLength)
|
sl@0
|
103 |
test.Printf(_L("%d, "), len);
|
sl@0
|
104 |
else
|
sl@0
|
105 |
test.Printf(_L("Test array bases trg=0x%08x, src=0x%08x. Running experiment on %S. Results follow:\n"), trg, src, &aTitle);
|
sl@0
|
106 |
|
sl@0
|
107 |
const TInt xsquare = aTestDestAlign ? 32 : 1;
|
sl@0
|
108 |
const TInt ysquare = aTestSrcAlign ? 32 : 1;
|
sl@0
|
109 |
|
sl@0
|
110 |
for (srcoffset = 0 ; srcoffset < ysquare ; srcoffset++)
|
sl@0
|
111 |
{
|
sl@0
|
112 |
for (trgoffset = 0 ; trgoffset < xsquare ; trgoffset++)
|
sl@0
|
113 |
{
|
sl@0
|
114 |
RThread thread;
|
sl@0
|
115 |
TInt r=thread.Create(aTitle,aFunction,KDefaultStackSize,KHeapSize,KHeapSize,NULL);
|
sl@0
|
116 |
if(r!=KErrNone)
|
sl@0
|
117 |
{
|
sl@0
|
118 |
test.Printf(_L("Failed to create thread with error %d\n"),r);
|
sl@0
|
119 |
return(r);
|
sl@0
|
120 |
}
|
sl@0
|
121 |
thread.SetPriority(EPriorityLess);
|
sl@0
|
122 |
thread.Resume();
|
sl@0
|
123 |
User::After(50000); // 50 msec is more than enough in EKA2
|
sl@0
|
124 |
count=0;
|
sl@0
|
125 |
User::After(5000); // even if the second reset fails, max inaccuracy is 5000 usecs
|
sl@0
|
126 |
count=0; // try and reduce the probability of failing to reset
|
sl@0
|
127 |
User::After(KAverageOverInMilliseconds*1000);
|
sl@0
|
128 |
result=count;
|
sl@0
|
129 |
thread.Kill(0);
|
sl@0
|
130 |
CLOSE_AND_WAIT(thread);
|
sl@0
|
131 |
PurgeCache();
|
sl@0
|
132 |
|
sl@0
|
133 |
result *= 1000;
|
sl@0
|
134 |
result /= KAverageOverInMilliseconds;
|
sl@0
|
135 |
|
sl@0
|
136 |
TInt s = I64INT(result);
|
sl@0
|
137 |
test.Printf(_L("%d, "),s);
|
sl@0
|
138 |
}
|
sl@0
|
139 |
test.Printf(_L("\n"));
|
sl@0
|
140 |
}
|
sl@0
|
141 |
}
|
sl@0
|
142 |
|
sl@0
|
143 |
if (aTestBackwards && goingforward)
|
sl@0
|
144 |
goingforward = EFalse;
|
sl@0
|
145 |
else
|
sl@0
|
146 |
break;
|
sl@0
|
147 |
}
|
sl@0
|
148 |
|
sl@0
|
149 |
User::Free(buffer);
|
sl@0
|
150 |
|
sl@0
|
151 |
return(result);
|
sl@0
|
152 |
}
|
sl@0
|
153 |
|
sl@0
|
154 |
enum TTestType
|
sl@0
|
155 |
{
|
sl@0
|
156 |
ENormalTests,
|
sl@0
|
157 |
EFullTests,
|
sl@0
|
158 |
ELengthTests,
|
sl@0
|
159 |
};
|
sl@0
|
160 |
|
sl@0
|
161 |
// Return whether we should run the full alignment benchmarks
|
sl@0
|
162 |
TTestType ParseCommandLine()
|
sl@0
|
163 |
{
|
sl@0
|
164 |
TBuf<32> args;
|
sl@0
|
165 |
User::CommandLine(args);
|
sl@0
|
166 |
|
sl@0
|
167 |
if (args == _L("-f"))
|
sl@0
|
168 |
return EFullTests;
|
sl@0
|
169 |
else if (args == _L("-l"))
|
sl@0
|
170 |
return ELengthTests;
|
sl@0
|
171 |
else if (args != KNullDesC)
|
sl@0
|
172 |
{
|
sl@0
|
173 |
test.Printf(_L("usage: t_membm [OPTIONS]\n"));
|
sl@0
|
174 |
test.Printf(_L(" -f Run full alignment benchmarks\n"));
|
sl@0
|
175 |
test.Printf(_L(" -l Run memcpy length benchmarks\n"));
|
sl@0
|
176 |
test(EFalse);
|
sl@0
|
177 |
}
|
sl@0
|
178 |
|
sl@0
|
179 |
return ENormalTests;
|
sl@0
|
180 |
}
|
sl@0
|
181 |
|
sl@0
|
182 |
TInt E32Main()
|
sl@0
|
183 |
//
|
sl@0
|
184 |
// Benchmark for Mem functions
|
sl@0
|
185 |
//
|
sl@0
|
186 |
{
|
sl@0
|
187 |
|
sl@0
|
188 |
test.Title();
|
sl@0
|
189 |
test.Start(_L("Benchmarks for Mem functions"));
|
sl@0
|
190 |
|
sl@0
|
191 |
TTestType testType = ParseCommandLine();
|
sl@0
|
192 |
|
sl@0
|
193 |
switch (testType)
|
sl@0
|
194 |
{
|
sl@0
|
195 |
case ENormalTests:
|
sl@0
|
196 |
case EFullTests:
|
sl@0
|
197 |
{
|
sl@0
|
198 |
TBool srcAlign = testType == EFullTests;
|
sl@0
|
199 |
|
sl@0
|
200 |
if (srcAlign)
|
sl@0
|
201 |
test.Printf(_L("Running full alignment benchmarks (may take a long time)\n"));
|
sl@0
|
202 |
else
|
sl@0
|
203 |
test.Printf(_L("Not testing source alignment (run with -f if you want this)\n"));
|
sl@0
|
204 |
|
sl@0
|
205 |
runTest(MemBaseline, _L("Processor baseline"), EFalse, EFalse, EFalse, 0);
|
sl@0
|
206 |
runTest(MemFill, _L("Memory fill"), EFalse, EFalse, ETrue, 0);
|
sl@0
|
207 |
runTest(MemCopy, _L("Memory copy"), ETrue, srcAlign, ETrue, 0);
|
sl@0
|
208 |
runTest(MemSwap, _L("Memory swap"), ETrue, srcAlign, ETrue, 0);
|
sl@0
|
209 |
}
|
sl@0
|
210 |
break;
|
sl@0
|
211 |
case ELengthTests:
|
sl@0
|
212 |
test.Printf(_L("Running length benchmarks (may take a long time)\n"));
|
sl@0
|
213 |
runTest(MemFill, _L("Fill length cached"), EFalse, EFalse, EFalse, 1);
|
sl@0
|
214 |
runTest(MemFillUncached, _L("Fill length uncached"), EFalse, EFalse, EFalse, 1);
|
sl@0
|
215 |
runTest(MemCopy, _L("Copy length cached"), EFalse, EFalse, EFalse, 1);
|
sl@0
|
216 |
runTest(MemCopyUncached, _L("Copy length uncached"), EFalse, EFalse, EFalse, 1);
|
sl@0
|
217 |
runTest(WordMove, _L("Word move length cached"), EFalse, EFalse, EFalse, 4);
|
sl@0
|
218 |
runTest(WordMoveUncached,_L("Word move length uncached"), EFalse, EFalse, EFalse, 4);
|
sl@0
|
219 |
break;
|
sl@0
|
220 |
default:
|
sl@0
|
221 |
test(EFalse);
|
sl@0
|
222 |
break;
|
sl@0
|
223 |
}
|
sl@0
|
224 |
|
sl@0
|
225 |
test.End();
|
sl@0
|
226 |
return(KErrNone);
|
sl@0
|
227 |
}
|