@@ -14,6 +14,15 @@ namespace ReClassNET.MemoryScanner
14
14
{
15
15
public class Scanner : IDisposable
16
16
{
17
+ /// <summary>
18
+ /// Helper class for consolidated memory regions.
19
+ /// </summary>
20
+ private class ConsolidatedMemoryRegion
21
+ {
22
+ public IntPtr Address { get ; set ; }
23
+ public int Size { get ; set ; }
24
+ }
25
+
17
26
private readonly RemoteProcess process ;
18
27
private readonly CircularBuffer < ScanResultStore > stores ;
19
28
@@ -192,12 +201,14 @@ private Task<bool> FirstScan(IScanComparer comparer, IProgress<int> progress, Ca
192
201
return Task . FromResult ( true ) ;
193
202
}
194
203
195
- var initialBufferSize = ( int ) sections . Average ( s => s . Size . ToInt32 ( ) ) ;
204
+ var regions = ConsolidateSections ( sections ) ;
205
+
206
+ var initialBufferSize = ( int ) ( regions . Average ( s => s . Size ) + 1 ) ;
196
207
197
208
progress ? . Report ( 0 ) ;
198
209
199
210
var counter = 0 ;
200
- var totalSectionCount = ( float ) sections . Count ;
211
+ var totalSectionCount = ( float ) regions . Count ;
201
212
202
213
return Task . Run ( ( ) =>
203
214
{
@@ -207,23 +218,24 @@ private Task<bool> FirstScan(IScanComparer comparer, IProgress<int> progress, Ca
207
218
// 3. n Worker -> m Sections: Read data, search results, store results
208
219
209
220
var result = Parallel . ForEach (
210
- sections , // Sections get grouped by the framework to balance the workers.
221
+ regions , // Sections get grouped by the framework to balance the workers.
211
222
( ) => new ScannerContext ( Settings , comparer , initialBufferSize ) , // Create a new context for every worker (thread).
212
223
( s , state , _ , context ) =>
213
224
{
214
225
if ( ! ct . IsCancellationRequested )
215
226
{
216
- var start = s . Start ;
217
- var size = s . Size . ToInt32 ( ) ;
227
+ var start = s . Address ;
228
+ var end = s . Address + s . Size ;
229
+ var size = s . Size ;
218
230
219
- if ( Settings . StartAddress . InRange ( s . Start , s . End ) )
231
+ if ( Settings . StartAddress . InRange ( start , end ) )
220
232
{
233
+ size = size - Settings . StartAddress . Sub ( start ) . ToInt32 ( ) ;
221
234
start = Settings . StartAddress ;
222
- size = size - Settings . StartAddress . Sub ( s . Start ) . ToInt32 ( ) ;
223
235
}
224
- if ( Settings . StopAddress . InRange ( s . Start , s . End ) )
236
+ if ( Settings . StopAddress . InRange ( start , end ) )
225
237
{
226
- size = size - s . End . Sub ( Settings . StopAddress ) . ToInt32 ( ) ;
238
+ size = size - end . Sub ( Settings . StopAddress ) . ToInt32 ( ) ;
227
239
}
228
240
229
241
context . EnsureBufferSize ( size ) ;
@@ -325,6 +337,42 @@ private Task<bool> NextScan(IScanComparer comparer, IProgress<int> progress, Can
325
337
} , ct ) ;
326
338
}
327
339
340
+ /// <summary>
341
+ /// Consolidate memory sections which are direct neighbours to reduce the number of work items.
342
+ /// </summary>
343
+ /// <param name="sections">A list of sections.</param>
344
+ /// <returns>A list of consolidated memory regions.</returns>
345
+ private static List < ConsolidatedMemoryRegion > ConsolidateSections ( IList < Section > sections )
346
+ {
347
+ var regions = new List < ConsolidatedMemoryRegion > ( ) ;
348
+
349
+ if ( sections . Count > 0 )
350
+ {
351
+ var address = sections [ 0 ] . Start ;
352
+ var size = sections [ 0 ] . Size . ToInt32 ( ) ;
353
+
354
+ for ( var i = 1 ; i < sections . Count ; ++ i )
355
+ {
356
+ var section = sections [ i ] ;
357
+ if ( address + size != section . Start )
358
+ {
359
+ regions . Add ( new ConsolidatedMemoryRegion { Address = address , Size = size } ) ;
360
+
361
+ address = section . Start ;
362
+ size = section . Size . ToInt32 ( ) ;
363
+ }
364
+ else
365
+ {
366
+ size += section . Size . ToInt32 ( ) ;
367
+ }
368
+ }
369
+
370
+ regions . Add ( new ConsolidatedMemoryRegion { Address = address , Size = size } ) ;
371
+ }
372
+
373
+ return regions ;
374
+ }
375
+
328
376
/// <summary>
329
377
/// Creates a result block from the scan results and adjusts the result offset.
330
378
/// </summary>
0 commit comments