From cef35ac7cecd56ac31b2f7ce352b696a31a80d5e Mon Sep 17 00:00:00 2001 From: Pieter de Bie Date: Thu, 20 Nov 2008 17:30:59 +0100 Subject: [PATCH] GitGrapher: Rewrite looping code to C++ This makes the revwalking faster by not creating as many NSObjects as before. --- GitX.xcodeproj/project.pbxproj | 16 ++-- PBGitGrapher.h | 10 +- PBGitGrapher.m | 146 ---------------------------- PBGitGrapher.mm | 169 +++++++++++++++++++++++++++++++++ PBGitLane.h | 39 +++++--- PBGitLane.m | 35 ------- PBGitLane.mm | 46 +++++++++ PBGitRevList.m | 4 +- 8 files changed, 255 insertions(+), 210 deletions(-) delete mode 100644 PBGitGrapher.m create mode 100644 PBGitGrapher.mm delete mode 100644 PBGitLane.m create mode 100644 PBGitLane.mm diff --git a/GitX.xcodeproj/project.pbxproj b/GitX.xcodeproj/project.pbxproj index 2f3f5cc..3aed4d0 100644 --- a/GitX.xcodeproj/project.pbxproj +++ b/GitX.xcodeproj/project.pbxproj @@ -62,7 +62,7 @@ F5AD56790E79B78100EDAAFE /* PBCommitList.m in Sources */ = {isa = PBXBuildFile; fileRef = F5AD56780E79B78100EDAAFE /* PBCommitList.m */; }; F5B721C40E05CF7E00AF29DC /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = F5B721C20E05CF7E00AF29DC /* MainMenu.xib */; }; F5C007750E731B48007B84B2 /* PBGitRef.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C007740E731B48007B84B2 /* PBGitRef.m */; }; - F5C6F68D0E65FF9300478D97 /* PBGitLane.m in Sources */ = {isa = PBXBuildFile; fileRef = F5C6F68C0E65FF9300478D97 /* PBGitLane.m */; }; + F5C6F68D0E65FF9300478D97 /* PBGitLane.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5C6F68C0E65FF9300478D97 /* PBGitLane.mm */; }; F5DFFA6C0E075D8800617813 /* PBEasyFS.m in Sources */ = {isa = PBXBuildFile; fileRef = F5DFFA6B0E075D8800617813 /* PBEasyFS.m */; }; F5E424110EA3E4D60046E362 /* PBDiffWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = F5E424100EA3E4D60046E362 /* PBDiffWindow.xib */; }; F5E424150EA3E4E10046E362 /* PBDiffWindowController.m in Sources */ = {isa = PBXBuildFile; fileRef = F5E424130EA3E4E10046E362 /* PBDiffWindowController.m */; }; @@ -78,7 +78,7 @@ F5FC43FE0EBD08EE00191D80 /* PBRefMenuItem.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FC43FD0EBD08EE00191D80 /* PBRefMenuItem.m */; }; F5FE6C030EB13BC900F30D12 /* PBServicesController.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FE6C020EB13BC900F30D12 /* PBServicesController.m */; }; F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E170E0829C20006317A /* PBGitRevList.m */; }; - F5FF4E7A0E082E440006317A /* PBGitGrapher.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E790E082E440006317A /* PBGitGrapher.m */; }; + F5FF4E7A0E082E440006317A /* PBGitGrapher.mm in Sources */ = {isa = PBXBuildFile; fileRef = F5FF4E790E082E440006317A /* PBGitGrapher.mm */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -194,7 +194,7 @@ F5C007730E731B48007B84B2 /* PBGitRef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitRef.h; sourceTree = ""; }; F5C007740E731B48007B84B2 /* PBGitRef.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitRef.m; sourceTree = ""; }; F5C6F68B0E65FF9300478D97 /* PBGitLane.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitLane.h; sourceTree = ""; }; - F5C6F68C0E65FF9300478D97 /* PBGitLane.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitLane.m; sourceTree = ""; }; + F5C6F68C0E65FF9300478D97 /* PBGitLane.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PBGitLane.mm; sourceTree = ""; }; F5D2DC850EA401A80034AD24 /* PBGitConfig.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitConfig.h; sourceTree = ""; }; F5D619ED0EAE62EA00341D73 /* html */ = {isa = PBXFileReference; includeInIndex = 0; lastKnownFileType = folder; path = html; sourceTree = ""; }; F5DFFA6A0E075D8800617813 /* PBEasyFS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBEasyFS.h; sourceTree = ""; }; @@ -225,7 +225,7 @@ F5FF4E160E0829C20006317A /* PBGitRevList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitRevList.h; sourceTree = ""; }; F5FF4E170E0829C20006317A /* PBGitRevList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitRevList.m; sourceTree = ""; }; F5FF4E780E082E440006317A /* PBGitGrapher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PBGitGrapher.h; sourceTree = ""; }; - F5FF4E790E082E440006317A /* PBGitGrapher.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PBGitGrapher.m; sourceTree = ""; }; + F5FF4E790E082E440006317A /* PBGitGrapher.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PBGitGrapher.mm; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -456,7 +456,7 @@ isa = PBXGroup; children = ( F5FF4E780E082E440006317A /* PBGitGrapher.h */, - F5FF4E790E082E440006317A /* PBGitGrapher.m */, + F5FF4E790E082E440006317A /* PBGitGrapher.mm */, F50FE0E10E07BE9600854FCD /* PBGitRevisionCell.h */, F50FE0E20E07BE9600854FCD /* PBGitRevisionCell.m */, F56CC7270E65E0AD004307B4 /* PBGitGraphLine.h */, @@ -464,7 +464,7 @@ F56CC7300E65E0E5004307B4 /* PBGraphCellInfo.h */, F56CC7310E65E0E5004307B4 /* PBGraphCellInfo.m */, F5C6F68B0E65FF9300478D97 /* PBGitLane.h */, - F5C6F68C0E65FF9300478D97 /* PBGitLane.m */, + F5C6F68C0E65FF9300478D97 /* PBGitLane.mm */, ); name = Graphing; sourceTree = ""; @@ -656,12 +656,12 @@ F5DFFA6C0E075D8800617813 /* PBEasyFS.m in Sources */, F50FE0E30E07BE9600854FCD /* PBGitRevisionCell.m in Sources */, F5FF4E180E0829C20006317A /* PBGitRevList.m in Sources */, - F5FF4E7A0E082E440006317A /* PBGitGrapher.m in Sources */, + F5FF4E7A0E082E440006317A /* PBGitGrapher.mm in Sources */, 911111F80E594F3F00BF76B4 /* PBRepositoryDocumentController.m in Sources */, 913D5E5F0E556A9300CECEA2 /* PBCLIProxy.mm in Sources */, F56CC7290E65E0AD004307B4 /* PBGitGraphLine.m in Sources */, F56CC7320E65E0E5004307B4 /* PBGraphCellInfo.m in Sources */, - F5C6F68D0E65FF9300478D97 /* PBGitLane.m in Sources */, + F5C6F68D0E65FF9300478D97 /* PBGitLane.mm in Sources */, F5C007750E731B48007B84B2 /* PBGitRef.m in Sources */, F5AD56790E79B78100EDAAFE /* PBCommitList.m in Sources */, F53FF2050E7ABB5300389171 /* PBGitRevSpecifier.m in Sources */, diff --git a/PBGitGrapher.h b/PBGitGrapher.h index 806b551..9d3a4ba 100644 --- a/PBGitGrapher.h +++ b/PBGitGrapher.h @@ -11,17 +11,9 @@ #import "PBGitGraphLine.h" #import "PBGraphCellInfo.h" -struct PBGitGraphColumn { - NSString* commit; // Commit that we're looking for - int color; -}; - - -#define PBGitMaxColumns 100 - @interface PBGitGrapher : NSObject { PBGraphCellInfo* previous; - NSMutableArray* previousLanes; + void *pl; NSDictionary* refs; PBGitRepository* repository; } diff --git a/PBGitGrapher.m b/PBGitGrapher.m deleted file mode 100644 index 299e8d4..0000000 --- a/PBGitGrapher.m +++ /dev/null @@ -1,146 +0,0 @@ -// -// PBGitGrapher.m -// GitX -// -// Created by Pieter de Bie on 17-06-08. -// Copyright 2008 __MyCompanyName__. All rights reserved. -// - -#import "PBGitGrapher.h" -#import "PBGitCommit.h" -#import "PBGitLane.h" - -@implementation PBGitGrapher - -#define MAX_LANES 32 - -- (id) initWithRepository: (PBGitRepository*) repo -{ - refs = repo.refs; - repository = repo; - previousLanes = [NSMutableArray arrayWithCapacity:MAX_LANES]; - [PBGitLane resetColors]; - - return self; -} - -- (void) decorateCommit: (PBGitCommit *) commit -{ - int i = 0, newPos = -1; - NSMutableArray* currentLanes = [NSMutableArray arrayWithCapacity:MAX_LANES]; - NSMutableArray* lines = [NSMutableArray array]; - PBGitLane* currentLane = NULL; - BOOL didFirst = NO; - - // First, iterate over earlier columns and pass through any that don't want this commit - if (previous != nil) { - - // We can't count until numColumns here, as it's only used for the width of the cell. - for (PBGitLane* lane in previousLanes) { - i++; - // This is our commit! We should do a "merge": move the line from - // our upperMapping to their lowerMapping - if ([lane isCommit:commit.sha]) { - if (!didFirst) { - didFirst = YES; - currentLane = lane; - [currentLanes addObject: lane]; - newPos = [currentLanes count]; - } - [lines addObject: [PBGitGraphLine upperLineFrom: i to: newPos color: [lane index]]]; - } - else { - // We are not this commit. - // Try to find an earlier column for this commit. - int j = 0; - BOOL found = NO; - for (PBGitLane* column in currentLanes) { - j++; - // ??? what is this? -// if (j == newPos) -// continue; - if ([lane isCommit: commit.sha]) { - // We already have a column for this commit. use it instead - [lines addObject: [PBGitGraphLine upperLineFrom: i to: j color: [lane index]]]; - found = YES; - break; - } - } - - // We need a new column for this. - if (!found) { - - [currentLanes addObject: lane]; - [lines addObject: [PBGitGraphLine upperLineFrom: i to: [currentLanes count] color: [lane index]]]; - [lines addObject: [PBGitGraphLine lowerLineFrom: [currentLanes count] to: [currentLanes count] color: [lane index]]]; - } - } - // For existing columns, we always just continue straight down - // ^^ I don't know what that means anymore :( - [lines addObject:[PBGitGraphLine lowerLineFrom:newPos to:newPos color: [currentLane index]]]; - } - } - - //Add your own parents - - // If we already did the first parent, don't do so again - if (!didFirst && [currentLanes count] < MAX_LANES) { - PBGitLane* newLane = [[PBGitLane alloc] initWithCommit:[commit.parents objectAtIndex:0]]; - [currentLanes addObject: newLane]; - newPos = [currentLanes count]; - [lines addObject:[PBGitGraphLine lowerLineFrom: newPos to: newPos color: [newLane index]]]; - } - - // Add all other parents - - // If we add at least one parent, we can go back a single column. - // This boolean will tell us if that happened - BOOL addedParent = NO; - - for (NSString* parent in [commit.parents subarrayWithRange:NSMakeRange(1, [commit.parents count] -1)]) { - int i = 0; - BOOL was_displayed = NO; - for (PBGitLane* column in currentLanes) { - i++; - if ([column isCommit: parent]) { - [lines addObject:[PBGitGraphLine lowerLineFrom: i to: newPos color: [column index]]]; - was_displayed = YES; - break; - } - } - if (was_displayed) - continue; - - if ([currentLanes count] >= MAX_LANES) - break; - - // Really add this parent - addedParent = YES; - PBGitLane* newLane = [[PBGitLane alloc] initWithCommit:parent]; - [currentLanes addObject: newLane]; - [lines addObject:[PBGitGraphLine lowerLineFrom: [currentLanes count] to: newPos color: [newLane index]]]; - } - - previous = [[PBGraphCellInfo alloc] initWithPosition:newPos andLines:lines]; - previous.sign = commit.sign; - - // If a parent was added, we have room to not indent. - if (addedParent) - previous.numColumns = [currentLanes count] - 1; - else - previous.numColumns = [currentLanes count]; - - if ([commit.parents count] > 0 && ![[commit.parents objectAtIndex:0] isEqualToString:@""]) - currentLane.sha = [commit.parents objectAtIndex:0]; - else - [currentLanes removeObject:currentLane]; - - previousLanes = currentLanes; - commit.lineInfo = previous; -} - -- (void) finalize -{ - [super finalize]; -} -@end diff --git a/PBGitGrapher.mm b/PBGitGrapher.mm new file mode 100644 index 0000000..2b26fdc --- /dev/null +++ b/PBGitGrapher.mm @@ -0,0 +1,169 @@ +// +// PBGitGrapher.m +// GitX +// +// Created by Pieter de Bie on 17-06-08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "PBGitGrapher.h" +#import "PBGitCommit.h" +#import "PBGitLane.h" +#import + +using namespace std; + +@implementation PBGitGrapher + +#define MAX_LANES 32 + +- (id) initWithRepository: (PBGitRepository*) repo +{ + refs = repo.refs; + repository = repo; + pl = new std::vector; + + PBGitLane::resetColors(); + //[PBGitLane resetColors]; + + return self; +} + +- (void) decorateCommit: (PBGitCommit *) commit +{ + //NSLog(@"Decoriting commit %@", commit.sha); + int i = 0, newPos = -1; + std::vector *currentLanes = new std::vector; + std::vector *previousLanes = (std::vector *)pl; + + NSMutableArray* lines = [NSMutableArray array]; + PBGitLane *currentLane = NULL; + BOOL didFirst = NO; + + // First, iterate over earlier columns and pass through any that don't want this commit + if (previous != nil) { + // We can't count until numColumns here, as it's only used for the width of the cell. + std::vector::iterator it = previousLanes->begin(); + for (; it < previousLanes->end(); ++it) { + i++; + // This is our commit! We should do a "merge": move the line from + // our upperMapping to their lowerMapping + + if ((*it)->isCommit([commit sha])) { + if (!didFirst) { + didFirst = YES; + currentLanes->push_back(*it); + currentLane = currentLanes->back(); + newPos = currentLanes->size(); + [lines addObject: [PBGitGraphLine upperLineFrom: i to: newPos color: (*it)->index()]]; + } + else { + [lines addObject: [PBGitGraphLine upperLineFrom: i to: newPos color: (*it)->index()]]; + delete *it; + } + } + else { + // We are not this commit. + // Try to find an earlier column for this commit. + int j = 0; + BOOL found = NO; + std::vector::iterator it2 = currentLanes->begin(); + for (; it2 < currentLanes->end(); ++it2) { + j++; + // ??? what is this? +// if (j == newPos) +// continue; + if ((*it)->isCommit([commit sha])) { + // We already have a column for this commit. use it instead + [lines addObject: [PBGitGraphLine upperLineFrom: i to: j color: (*it)->index()]]; + found = YES; + break; + } + } + + // We need a new column for this. + if (found) { + //NSLog(@"Need to delete"); + } else { + //NSLog(@"Found another"); + currentLanes->push_back(*it); + [lines addObject: [PBGitGraphLine upperLineFrom: i to: currentLanes->size() color: (*it)->index()]]; + [lines addObject: [PBGitGraphLine lowerLineFrom: currentLanes->size() to: currentLanes->size() color: (*it)->index()]]; + } + } + // For existing columns, we always just continue straight down + // ^^ I don't know what that means anymore :( + + if (currentLane) + [lines addObject:[PBGitGraphLine lowerLineFrom:newPos to:newPos color: currentLane->index()]]; + else + [lines addObject:[PBGitGraphLine lowerLineFrom:newPos to:newPos color: 0]]; + } + } + //Add your own parents + + // If we already did the first parent, don't do so again + if (!didFirst && currentLanes->size() < MAX_LANES) { + PBGitLane *newLane = new PBGitLane([commit.parents objectAtIndex:0]); + currentLanes->push_back(newLane); + newPos = currentLanes->size(); + [lines addObject:[PBGitGraphLine lowerLineFrom: newPos to: newPos color: newLane->index()]]; + } + + // Add all other parents + + // If we add at least one parent, we can go back a single column. + // This boolean will tell us if that happened + BOOL addedParent = NO; + + for (NSString* parent in [commit.parents subarrayWithRange:NSMakeRange(1, [commit.parents count] -1)]) { + int i = 0; + BOOL was_displayed = NO; + std::vector::iterator it = currentLanes->begin(); + for (; it < currentLanes->end(); ++it) { + i++; + if ((*it)->isCommit(parent)) { + [lines addObject:[PBGitGraphLine lowerLineFrom: i to: newPos color: (*it)->index()]]; + was_displayed = YES; + break; + } + } + if (was_displayed) + continue; + + if (currentLanes->size() >= MAX_LANES) + break; + + // Really add this parent + addedParent = YES; + PBGitLane *newLane = new PBGitLane(parent); + currentLanes->push_back(newLane); + [lines addObject:[PBGitGraphLine lowerLineFrom: currentLanes->size() to: newPos color: newLane->index()]]; + } + + previous = [[PBGraphCellInfo alloc] initWithPosition:newPos andLines:lines]; + previous.sign = commit.sign; + + // If a parent was added, we have room to not indent. + if (addedParent) + previous.numColumns = currentLanes->size() - 1; + else + previous.numColumns = currentLanes->size(); + + // Update the current lane to point to the new parent + if (currentLane && [commit.parents count] > 0 && ![[commit.parents objectAtIndex:0] isEqualToString:@""]) + currentLane->setSha([commit.parents objectAtIndex:0]); + // else + // [currentLanes removeObject:currentLane]; + + delete previousLanes; + + pl = currentLanes; + commit.lineInfo = previous; +} + +- (void) finalize +{ + [super finalize]; +} +@end diff --git a/PBGitLane.h b/PBGitLane.h index ab89cbb..02e68cc 100644 --- a/PBGitLane.h +++ b/PBGitLane.h @@ -5,19 +5,36 @@ // Created by Pieter de Bie on 27-08-08. // Copyright 2008 __MyCompanyName__. All rights reserved. // - #import -@interface PBGitLane : NSObject { - NSString* sha; - int index; -} -- (id) initWithCommit: (NSString*) c; -- (BOOL) isCommit: (NSString*) c; +class PBGitLane { + static int s_colorIndex; -+ (void) resetColors; + NSString *d_sha; + int d_index; -@property(assign) NSString* sha; -@property(readonly) int index; +public: -@end + PBGitLane(NSString *sha) + { + d_index = s_colorIndex++; + d_sha = [sha copy]; + } + + PBGitLane() + { + d_index = s_colorIndex++; + d_sha = NULL; + } + + bool isCommit(NSString *sha) const; + void setSha(NSString *sha); + NSString *sha() const + { + return [d_sha copy]; + } + + int index() const; + + static void resetColors(); +}; diff --git a/PBGitLane.m b/PBGitLane.m deleted file mode 100644 index 2d80d94..0000000 --- a/PBGitLane.m +++ /dev/null @@ -1,35 +0,0 @@ -// -// PBGitLane.m -// GitX -// -// Created by Pieter de Bie on 27-08-08. -// Copyright 2008 __MyCompanyName__. All rights reserved. -// - -#import "PBGitLane.h" - - -@implementation PBGitLane - -static int PBGITLANE_CURRENT_INDEX = 0; - -@synthesize sha, index; - -+ (void) resetColors -{ - PBGITLANE_CURRENT_INDEX = 0; -} - -- (id) initWithCommit: (NSString*) c -{ - index = PBGITLANE_CURRENT_INDEX++; - sha = c; - - return self; -} - -- (BOOL) isCommit: (NSString*) s -{ - return [sha isEqualToString:s]; -} -@end diff --git a/PBGitLane.mm b/PBGitLane.mm new file mode 100644 index 0000000..a712a5b --- /dev/null +++ b/PBGitLane.mm @@ -0,0 +1,46 @@ +// +// PBGitLane.m +// GitX +// +// Created by Pieter de Bie on 27-08-08. +// Copyright 2008 __MyCompanyName__. All rights reserved. +// + +#import "PBGitLane.h" +//class PBGitLane { +// static int s_colorIndex; +// +// char d_sha[20]; +// int d_index; +// +//public: +// PBGitLane(NSString *sha); +// +// bool isCommit(NSString *sha) const; +// int index(); const; +// +// static resetColors(); +//}; + +int PBGitLane::s_colorIndex = 0; + +bool PBGitLane::isCommit(NSString *sha) const +{ + //NSLog(@"Comparing %@ with %@", d_sha, sha); + return [d_sha isEqualToString:sha]; +} + +int PBGitLane::index() const +{ + return d_index; +} + +void PBGitLane::setSha(NSString *sha) +{ + d_sha = sha; +} + +void PBGitLane::resetColors() +{ + s_colorIndex = 0; +} diff --git a/PBGitRevList.m b/PBGitRevList.m index b4d37ec..a10de74 100644 --- a/PBGitRevList.m +++ b/PBGitRevList.m @@ -61,7 +61,7 @@ - (void) walkRevisionListWithSpecifier: (PBGitRevSpecifier*) rev { - + NSDate *start = [NSDate date]; NSMutableArray* revisions = [NSMutableArray array]; PBGitGrapher* g = [[PBGitGrapher alloc] initWithRepository: repository]; NSDictionary* refs = [repository refs]; @@ -147,6 +147,8 @@ [currentLine setString: @""]; } + NSTimeInterval duration = [[NSDate date] timeIntervalSinceDate:start]; + NSLog(@"Loaded %i commits in %f seconds", num, duration); // Make sure the commits are stored before exiting. [self performSelectorOnMainThread:@selector(setCommits:) withObject:revisions waitUntilDone:YES]; [task waitUntilExit];