Skip to content
Snippets Groups Projects
Commit ecc6bad2 authored by George Nachman's avatar George Nachman
Browse files

Performance improvements for Find. Convert positions to x,y ranges in batches....

Performance improvements for Find. Convert positions to x,y ranges in batches. Cache block position in findSubstring:stopAt.
parent 63fd1abd
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -41,6 +41,15 @@
}
@end
 
@interface XYRange : NSObject {
@public
int xStart;
int yStart;
int xEnd;
int yEnd;
}
@end
typedef struct FindContext {
int absBlockNum;
NSString* substring;
Loading
Loading
@@ -248,6 +257,9 @@ typedef struct FindContext {
// Returns TRUE if the conversion was successful, false if the position was out of bounds.
- (BOOL) convertPosition: (int) position withWidth: (int) width toX: (int*) x toY: (int*) y;
 
// Returns an array of XYRange values
- (NSArray*)convertPositions:(NSArray*)resultRanges withWidth:(int)width;
// Convert x,y coordinates (with y=0 being the first line) into a position. Offset is added to the position safely.
// Returns TRUE if the conversion was successful, false, if out of bounds.
- (BOOL) convertCoordinatesAtX: (int) x atY: (int) y withWidth: (int) width toPosition: (int*) position offset:(int)offset;
Loading
Loading
Loading
Loading
@@ -33,6 +33,9 @@
@implementation ResultRange
@end
 
@implementation XYRange
@end
@implementation LineBlock
 
- (LineBlock*) initWithRawBufferSize: (int) size
Loading
Loading
@@ -525,34 +528,9 @@ static NSString* RewrittenRegex(NSString* originalRegex) {
return rewritten;
}
 
static int Search(NSString* needle,
screen_char_t* rawline,
int raw_line_length,
int start,
int end,
int options,
int* resultLength)
{
NSString* haystack;
unichar* charHaystack;
int* deltas;
haystack = ScreenCharArrayToString(rawline,
start,
end,
&charHaystack,
&deltas);
// screen_char_t[i + deltas[i]] begins its run at charHaystack[i]
int result = CoreSearch(needle, rawline, raw_line_length, start, end, options, resultLength,
haystack, charHaystack, deltas, deltas[0]);
free(deltas);
free(charHaystack);
return result;
}
int CoreSearch(NSString* needle, screen_char_t* rawline, int raw_line_length, int start, int end,
int options, int* resultLength, NSString* haystack, unichar* charHaystack,
int* deltas, int deltaOffset)
static int CoreSearch(NSString* needle, screen_char_t* rawline, int raw_line_length, int start, int end,
int options, int* resultLength, NSString* haystack, unichar* charHaystack,
int* deltas, int deltaOffset)
{
int apiOptions = 0;
NSRange range;
Loading
Loading
@@ -666,6 +644,31 @@ int CoreSearch(NSString* needle, screen_char_t* rawline, int raw_line_length, in
return result;
}
 
static int Search(NSString* needle,
screen_char_t* rawline,
int raw_line_length,
int start,
int end,
int options,
int* resultLength)
{
NSString* haystack;
unichar* charHaystack;
int* deltas;
haystack = ScreenCharArrayToString(rawline,
start,
end,
&charHaystack,
&deltas);
// screen_char_t[i + deltas[i]] begins its run at charHaystack[i]
int result = CoreSearch(needle, rawline, raw_line_length, start, end, options, resultLength,
haystack, charHaystack, deltas, deltas[0]);
free(deltas);
free(charHaystack);
return result;
}
- (void) _findInRawLine:(int) entry
needle:(NSString*)needle
options:(int) options
Loading
Loading
@@ -1353,8 +1356,9 @@ static int RawNumLines(LineBuffer* buffer, int width) {
multipleResults:((context->options & FindMultipleResults) != 0)];
NSMutableArray* filtered = [NSMutableArray arrayWithCapacity:[context->results count]];
BOOL haveOutOfRangeResults = NO;
int blockPosition = [self _blockPosition:context->absBlockNum - num_dropped_blocks];
for (ResultRange* range in context->results) {
range->position += [self _blockPosition:context->absBlockNum - num_dropped_blocks];
range->position += blockPosition;
if (context->dir * (range->position - stopAt) > 0 ||
context->dir * (range->position + context->matchLength - stopAt) > 0) {
// result was outside the range to be searched
Loading
Loading
@@ -1380,6 +1384,87 @@ static int RawNumLines(LineBuffer* buffer, int width) {
context->absBlockNum += context->dir;
}
 
// Returns an array of XRange values
- (NSArray*)convertPositions:(NSArray*)resultRanges withWidth:(int)width
{
// Create sorted array of all positions to convert.
NSMutableArray* unsortedPositions = [NSMutableArray arrayWithCapacity:[resultRanges count] * 2];
for (ResultRange* rr in resultRanges) {
[unsortedPositions addObject:[NSNumber numberWithInt:rr->position]];
[unsortedPositions addObject:[NSNumber numberWithInt:rr->position + rr->length - 1]];
}
// Walk blocks and positions in parallel, converting each position in order. Store in
// intermediate dict, mapping position->NSPoint(x,y)
NSArray *positionsArray = [unsortedPositions sortedArrayUsingSelector:@selector(compare:)];
int i = 0;
int yoffset = 0;
int numBlocks = [blocks count];
int passed = 0;
LineBlock *block = [blocks objectAtIndex:0];
int used = [block rawSpaceUsed];
NSMutableDictionary* intermediate = [NSMutableDictionary dictionaryWithCapacity:[resultRanges count] * 2];
int prev = -1;
for (NSNumber* positionNum in positionsArray) {
int position = [positionNum intValue];
if (position == prev) {
continue;
}
prev = position;
// Advance block until it includes this position
while (position >= passed + used && i < numBlocks) {
passed += used;
yoffset += [block getNumLinesWithWrapWidth:width];
i++;
if (i < numBlocks) {
block = [blocks objectAtIndex:i];
used = [block rawSpaceUsed];
}
}
if (i < numBlocks) {
int x, y;
assert(position >= passed);
assert(position < passed + used);
assert(used == [block rawSpaceUsed]);
BOOL isOk = [block convertPosition:position - passed
withWidth:width
toX:&x
toY:&y];
assert(x < 2000);
if (isOk) {
y += yoffset;
[intermediate setObject:[NSValue valueWithPoint:NSMakePoint(x, y)]
forKey:positionNum];
} else {
assert(false);
}
}
}
// Walk the positions array and populate results by looking up points in intermediate dict.
NSMutableArray* result = [NSMutableArray arrayWithCapacity:[resultRanges count]];
for (ResultRange* rr in resultRanges) {
NSValue *start = [intermediate objectForKey:[NSNumber numberWithInt:rr->position]];
NSValue *end = [intermediate objectForKey:[NSNumber numberWithInt:rr->position + rr->length - 1]];
if (start && end) {
XYRange *xyrange = [[[XYRange alloc] init] autorelease];
NSPoint startPoint = [start pointValue];
NSPoint endPoint = [end pointValue];
xyrange->xStart = startPoint.x;
xyrange->yStart = startPoint.y;
xyrange->xEnd = endPoint.x;
xyrange->yEnd = endPoint.y;
[result addObject:xyrange];
} else {
assert(false);
[result addObject:[NSNull null]];
}
}
return result;
}
- (BOOL) convertPosition: (int) position withWidth: (int) width toX: (int*) x toY: (int*) y
{
int i;
Loading
Loading
Loading
Loading
@@ -3253,24 +3253,22 @@ void DumpBuf(screen_char_t* p, int n) {
// Handle the current state
BOOL isOk;
switch (context->status) {
case Matched:
case Matched: {
// NSLog(@"matched");
// Found a match in the text.
for (ResultRange* rr in context->results) {
NSArray *allPositions = [linebuffer convertPositions:context->results
withWidth:WIDTH];
int k = 0;
for (ResultRange* currentResultRange in context->results) {
SearchResult* result = [[SearchResult alloc] init];
isOk = [linebuffer convertPosition:rr->position
withWidth:WIDTH
toX:&result->startX
toY:&startY];
assert(isOk);
result->absStartY = startY + [self totalScrollbackOverflow];
isOk = [linebuffer convertPosition:rr->position + rr->length - 1
withWidth:WIDTH
toX:&result->endX
toY:&endY];
assert(isOk);
result->absEndY = endY + [self totalScrollbackOverflow];
XYRange* xyrange = [allPositions objectAtIndex:k++];
result->startX = xyrange->xStart;
result->endX = xyrange->xEnd;
result->absStartY = xyrange->yStart + [self totalScrollbackOverflow];
result->absEndY = xyrange->yEnd + [self totalScrollbackOverflow];
[results addObject:result];
[result release];
if (!(context->options & FindMultipleResults)) {
Loading
Loading
@@ -3283,6 +3281,7 @@ void DumpBuf(screen_char_t* p, int n) {
}
[context->results removeAllObjects];
break;
}
 
case Searching:
// NSLog(@"searching");
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment