Skip to content

Commit 709d7d4

Browse files
committed
Fixes to accelerate and avoid processsor hogging in QSProcessMonitor.m:
- Only include app processes in list, exclude XPC and background - Avoid calling the slow [NSBundle bundleWithIdentifier:]
1 parent 310597e commit 709d7d4

File tree

1 file changed

+64
-11
lines changed

1 file changed

+64
-11
lines changed

Quicksilver/Code-QuickStepCore/QSProcessMonitor.m

Lines changed: 64 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -167,10 +167,12 @@ - (void)dealloc {
167167
- (QSObject *)imbuedFileProcessForDict:(NSDictionary *)dict {
168168
NSString *ident = [dict objectForKey:@"NSApplicationBundleIdentifier"];
169169
NSString *appPath = [dict objectForKey:@"NSApplicationPath"];
170-
NSBundle *bundle = [NSBundle bundleWithIdentifier:ident];
170+
171+
// We used to call the (slow) [NSBundle bundleWithIdentifier:ident], but we can pull this from dict instead
172+
NSString *bundlePath = [dict objectForKey:@"BundlePath"];
171173
QSObject *newObject = nil;
172-
if (bundle && [appPath isEqualToString:[bundle executablePath]]) {
173-
newObject = [QSObject fileObjectWithPath:[bundle bundlePath]];
174+
if ([appPath isEqualToString: bundlePath]) {
175+
newObject = [QSObject fileObjectWithPath:bundlePath];
174176
// NSLog(@"%@ %@", bundlePath, newObject);
175177
}
176178

@@ -240,6 +242,33 @@ - (NSDictionary *)infoForApp:(NSRunningApplication *)app {
240242
return dict;
241243
}
242244

245+
// Helper method to determine whether we want to include a process in the processes dict
246+
- (BOOL)includeApp:(NSRunningApplication *)app {
247+
248+
// Background processes are excluded unless QSShowBackgroundProcesses is set
249+
if ((app.activationPolicy == NSApplicationActivationPolicyProhibited) &&
250+
![[NSUserDefaults standardUserDefaults] boolForKey:@"QSShowBackgroundProcesses"])
251+
return NO;
252+
253+
// Get bundle info, if available
254+
NSDictionary *bundleInfo;
255+
if(app.bundleURL)
256+
bundleInfo = [[NSBundle bundleWithURL:app.bundleURL] infoDictionary];
257+
else
258+
bundleInfo = nil;
259+
260+
// Determine bundle type
261+
NSString *fileType;
262+
fileType = bundleInfo ? [bundleInfo objectForKey:@"CFBundlePackageType"] : @"NIL ";
263+
264+
// Exclude all processes except for APPL (regular apps) and FNDR (Finder)
265+
if(![fileType isEqualToString:@"APPL"] &&
266+
![fileType isEqualToString:@"FNDR"])
267+
return NO;
268+
269+
return YES;
270+
}
271+
243272
- (NSDictionary *)infoForPSN:(ProcessSerialNumber)processSerialNumber {
244273

245274
NSMutableDictionary *dict = [(NSDictionary *)CFBridgingRelease(ProcessInformationCopyDictionary(&processSerialNumber, kProcessDictionaryIncludeAllInformationMask)) mutableCopy];
@@ -264,6 +293,21 @@ - (NSDictionary *)infoForPSN:(ProcessSerialNumber)processSerialNumber {
264293
return dict;
265294
}
266295

296+
// Helper method to determine whether we want to include a process in the processes dict
297+
// Calls through to the NSRunningApplication-based method
298+
- (BOOL)includePSN:(ProcessSerialNumber)processSerialNumber {
299+
pid_t pid;
300+
NSRunningApplication *app;
301+
302+
GetProcessPID(&processSerialNumber, &pid);
303+
app = [NSRunningApplication runningApplicationWithProcessIdentifier: pid];
304+
if(app)
305+
return [self includeApp: app];
306+
307+
return NO;
308+
}
309+
310+
267311
#pragma mark -
268312
#pragma mark Process Notifications
269313

@@ -295,7 +339,11 @@ - (void)appLaunched:(ProcessSerialNumber)psn {
295339
NSDictionary *dict = [self infoForPSN:psn];
296340

297341
// if we're including background processes (i.e. all processes) OR if it's a foreground process, reload
298-
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"QSShowBackgroundProcesses"] || ![[dict objectForKey:@"LSBackgroundOnly"] boolValue]) {
342+
if ([self includePSN: psn]) {
343+
344+
#ifdef DEBUG
345+
NSLog(@"appLaunched: NSApplicationPath=%@", [dict objectForKey:@"NSApplicationPath"]);
346+
#endif
299347
[self reloadProcesses];
300348
}
301349
if (dict) {
@@ -398,18 +446,23 @@ - (void)_reloadProcesses {
398446

399447
NSArray *tempProcesses = [[NSWorkspace sharedWorkspace] runningApplications];
400448
NSMutableDictionary *procs = [[NSMutableDictionary alloc] initWithCapacity:tempProcesses.count];
449+
450+
401451
for (NSRunningApplication *app in tempProcesses) {
402-
NSDictionary *info = [self infoForApp:app];
403-
QSObject *procObject = [self imbuedFileProcessForDict:info];
404-
NSNumber *pidValue = [NSNumber numberWithInt:app.processIdentifier];
405-
406-
if (procObject) {
407-
[procs setObject:procObject forKey:pidValue];
452+
if ([self includeApp: app]) {
453+
NSDictionary *info = [self infoForApp:app];
454+
QSObject *procObject = [self imbuedFileProcessForDict:info];
455+
NSNumber *pidValue = [NSNumber numberWithInt:app.processIdentifier];
456+
457+
if (procObject) {
458+
[procs setObject:procObject forKey:pidValue];
459+
}
408460
}
409461
}
462+
410463
processes = [procs copy];
411464
#ifdef DEBUG
412-
NSLog(@"Reload time: %f ms", [date timeIntervalSinceNow]*-1000);
465+
NSLog(@"_reloadProcesses: Reload time: %f ms for %d processes", [date timeIntervalSinceNow]*-1000, (int) procs.count);
413466
#endif
414467

415468
[self didChangeValueForKey:@"allProcesses"];

0 commit comments

Comments
 (0)