|
1 // tallochelper.cpp |
|
2 // |
|
3 // Copyright (c) 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 |
|
13 #include <fshell/ioutils.h> |
|
14 #include <fshell/common.mmh> |
|
15 #include <fshell/heaputils.h> |
|
16 #include <fshell/ltkutils.h> |
|
17 |
|
18 using namespace IoUtils; |
|
19 using LtkUtils::RAllocatorHelper; |
|
20 |
|
21 class CCmdTAllocHelper : public CCommandBase |
|
22 { |
|
23 public: |
|
24 static CCommandBase* NewLC(); |
|
25 ~CCmdTAllocHelper(); |
|
26 private: |
|
27 CCmdTAllocHelper(); |
|
28 void PrintStats(const TDesC& aDesc); |
|
29 |
|
30 void AllocL(TInt aSize, TInt aNumber=1); |
|
31 void Free(TInt aNumber=1); |
|
32 void FormatSize(TDes& aBuf, TInt64 aSize); |
|
33 static TBool WalkCallback(RAllocatorHelper& aAlloc, TAny* aContext, RAllocatorHelper::TExtendedCellType aType, TLinAddr aAddress, TInt aLength); |
|
34 static void RHeapWalkCallback(TAny* aContext, RHeap::TCellType aType, TAny* aCell, TInt aLength); |
|
35 |
|
36 private: // From CCommandBase. |
|
37 virtual const TDesC& Name() const; |
|
38 virtual const TDesC& Description() const; |
|
39 virtual void DoRunL(); |
|
40 virtual void ArgumentsL(RCommandArgumentList& aArguments); |
|
41 virtual void OptionsL(RCommandOptionList& aOptions); |
|
42 private: |
|
43 RAllocatorHelper iAlloc; |
|
44 RArray<TAny*> iAllocations; |
|
45 TBool iBytes; |
|
46 TBool iWaitOnExit; |
|
47 |
|
48 TInt iAllocationsAccordingToRHeapWalker; |
|
49 }; |
|
50 |
|
51 EXE_BOILER_PLATE(CCmdTAllocHelper) |
|
52 |
|
53 CCommandBase* CCmdTAllocHelper::NewLC() |
|
54 { |
|
55 CCmdTAllocHelper* self = new(ELeave) CCmdTAllocHelper(); |
|
56 CleanupStack::PushL(self); |
|
57 self->BaseConstructL(); |
|
58 return self; |
|
59 } |
|
60 |
|
61 CCmdTAllocHelper::~CCmdTAllocHelper() |
|
62 { |
|
63 iAlloc.Close(); |
|
64 Free(iAllocations.Count()); |
|
65 iAllocations.Close(); |
|
66 } |
|
67 |
|
68 CCmdTAllocHelper::CCmdTAllocHelper() |
|
69 : CCommandBase(EManualComplete) |
|
70 { |
|
71 } |
|
72 |
|
73 const TDesC& CCmdTAllocHelper::Name() const |
|
74 { |
|
75 _LIT(KName, "tallochelper"); |
|
76 return KName; |
|
77 } |
|
78 |
|
79 const TDesC& CCmdTAllocHelper::Description() const |
|
80 { |
|
81 _LIT(KDescription, "Test code for RAllocatorHelper"); |
|
82 return KDescription; |
|
83 } |
|
84 |
|
85 void CCmdTAllocHelper::ArgumentsL(RCommandArgumentList& /*aArguments*/) |
|
86 { |
|
87 } |
|
88 |
|
89 void CCmdTAllocHelper::OptionsL(RCommandOptionList& aOptions) |
|
90 { |
|
91 aOptions.AppendBoolL(iBytes, 'b', _L("bytes"), _L("Display sizes in bytes rather than rounded off KB or MB")); |
|
92 aOptions.AppendBoolL(iWaitOnExit, 'w', _L("wait"), _L("Wait indefinitely before exiting - for testing remote heap walking")); |
|
93 } |
|
94 |
|
95 void CCmdTAllocHelper::DoRunL() |
|
96 { |
|
97 LeaveIfErr(iAlloc.Open(&User::Allocator()), _L("Couldn't open RAllocatorHelper")); |
|
98 iAllocations.ReserveL(128); |
|
99 |
|
100 Printf(_L("Udeb allocator=%d\r\n"), iAlloc.AllocatorIsUdeb()); |
|
101 |
|
102 PrintStats(_L("Initial stats")); |
|
103 // And do an RHeap walk, just to compare |
|
104 User::Allocator().DebugFunction(128, (TAny*)&RHeapWalkCallback, this); |
|
105 Printf(_L("allocated size according to RHeap::Walk: %d\r\n"), iAllocationsAccordingToRHeapWalker); |
|
106 |
|
107 AllocL(64*1024); |
|
108 PrintStats(_L("Stats after 1 64K alloc")); |
|
109 User::Allocator().DebugFunction(128, (TAny*)&RHeapWalkCallback, this); // debug |
|
110 |
|
111 |
|
112 AllocL(4, 50); |
|
113 PrintStats(_L("Stats after 50 small allocs")); |
|
114 |
|
115 /* |
|
116 // Open a new RAllocatorHelper cos the stats will be cached otherwise |
|
117 RAllocatorHelper h; h.Open(&User::Allocator()); |
|
118 iAllocationsAccordingToRHeapWalker = 0; |
|
119 User::Allocator().DebugFunction(128, (TAny*)&RHeapWalkCallback, this); |
|
120 Printf(_L("allocated size according to RHeap::Walk: %d\r\n"), iAllocationsAccordingToRHeapWalker); |
|
121 Printf(_L("iTotalAllocSize is %d\r\n"), h.AllocatedSize()); |
|
122 h.Close(); |
|
123 */ |
|
124 |
|
125 if (!iWaitOnExit) |
|
126 { |
|
127 Free(50); |
|
128 PrintStats(_L("Stats after freeing them")); |
|
129 Complete(); |
|
130 } |
|
131 } |
|
132 |
|
133 void CCmdTAllocHelper::PrintStats(const TDesC& aDesc) |
|
134 { |
|
135 iAlloc.RefreshDetails(); |
|
136 TBuf<16> allocSize, freeSize, dlaSize, slabSize, freeDlaSize, partiallyFreeSlabSize, freeSlabSize, pageSize; |
|
137 FormatSize(allocSize, iAlloc.SizeForCellType(RAllocatorHelper::EAllocationMask)); |
|
138 FormatSize(freeSize, iAlloc.SizeForCellType(RAllocatorHelper::EFreeMask)); |
|
139 FormatSize(dlaSize, iAlloc.SizeForCellType(RAllocatorHelper::EDlaAllocation)); |
|
140 FormatSize(slabSize, iAlloc.SizeForCellType(RAllocatorHelper::ESlabAllocation)); |
|
141 FormatSize(freeDlaSize, iAlloc.SizeForCellType(RAllocatorHelper::EDlaFreeCell)); |
|
142 FormatSize(partiallyFreeSlabSize, iAlloc.SizeForCellType(RAllocatorHelper::ESlabFreeCell)); |
|
143 FormatSize(freeSlabSize, iAlloc.SizeForCellType(RAllocatorHelper::ESlabFreeSlab)); |
|
144 FormatSize(pageSize, iAlloc.SizeForCellType(RAllocatorHelper::EPageAllocation)); |
|
145 |
|
146 Printf(_L("\r\n%S:\r\n\ |
|
147 Alloc: %d (%S), DLA: %d (%S) Slab: %d (%S) Paged: %d (%S)\r\n\ |
|
148 Free: %d (%S), DLA: %d (%S) Slab: %d (%S) Free slabs: %d (%S)\r\n"), |
|
149 &aDesc, iAlloc.AllocationCount(), &allocSize, |
|
150 iAlloc.CountForCellType(RAllocatorHelper::EDlaAllocation), &dlaSize, |
|
151 iAlloc.CountForCellType(RAllocatorHelper::ESlabAllocation), &slabSize, |
|
152 iAlloc.CountForCellType(RAllocatorHelper::EPageAllocation), &pageSize, |
|
153 iAlloc.CountForCellType(RAllocatorHelper::EFreeMask), &freeSize, |
|
154 iAlloc.CountForCellType(RAllocatorHelper::EDlaFreeCell), &freeDlaSize, |
|
155 iAlloc.CountForCellType(RAllocatorHelper::ESlabFreeCell), &partiallyFreeSlabSize, |
|
156 iAlloc.CountForCellType(RAllocatorHelper::ESlabFreeSlab), &freeSlabSize |
|
157 ); |
|
158 |
|
159 iAlloc.Walk(&WalkCallback, this); // Check cell lengths match up |
|
160 } |
|
161 |
|
162 void CCmdTAllocHelper::AllocL(TInt aSize, TInt aNumber) |
|
163 { |
|
164 while (aNumber--) |
|
165 { |
|
166 TAny* result = User::AllocL(aSize); |
|
167 TInt err = iAllocations.Append(result); |
|
168 if (err) |
|
169 { |
|
170 User::Free(result); |
|
171 User::Leave(KErrNoMemory); |
|
172 } |
|
173 } |
|
174 } |
|
175 |
|
176 void CCmdTAllocHelper::Free(TInt aNumber) |
|
177 { |
|
178 while (aNumber--) |
|
179 { |
|
180 TInt i = iAllocations.Count() - 1; |
|
181 User::Free(iAllocations[i]); |
|
182 iAllocations.Remove(i); |
|
183 } |
|
184 } |
|
185 |
|
186 void CCmdTAllocHelper::FormatSize(TDes& aBuf, TInt64 aSize) |
|
187 { |
|
188 if (iBytes) |
|
189 { |
|
190 aBuf.Num(aSize); |
|
191 } |
|
192 else |
|
193 { |
|
194 LtkUtils::FormatSize(aBuf, aSize); |
|
195 } |
|
196 } |
|
197 |
|
198 TBool CCmdTAllocHelper::WalkCallback(RAllocatorHelper& /*aAlloc*/, TAny* aContext, RAllocatorHelper::TExtendedCellType aType, TLinAddr aAddress, TInt aLength) |
|
199 { |
|
200 if (aType & RAllocatorHelper::EAllocationMask) |
|
201 { |
|
202 TInt lenFromAllocLen = User::AllocLen((TAny*)aAddress); |
|
203 if (lenFromAllocLen != aLength) |
|
204 { |
|
205 static_cast<CCmdTAllocHelper*>(aContext)->PrintWarning(_L("Walker reports cell 0x%08x size %d but AllocLen says %d\r\n"), aAddress, aLength, lenFromAllocLen); |
|
206 } |
|
207 } |
|
208 |
|
209 return ETrue; // Keep walking |
|
210 } |
|
211 |
|
212 void CCmdTAllocHelper::RHeapWalkCallback(TAny* aContext, RHeap::TCellType aType, TAny* aCell, TInt aLength) |
|
213 { |
|
214 if (aType == RHeap::EGoodAllocatedCell) |
|
215 { |
|
216 CCmdTAllocHelper* self = static_cast<CCmdTAllocHelper*>(aContext); |
|
217 self->iAllocationsAccordingToRHeapWalker += aLength; |
|
218 } |
|
219 } |