提交 45ee3c59 编写于 作者: R roblou

4 processes (still very rough)

上级 13953dbb
...@@ -12,6 +12,7 @@ import * as fs from 'fs'; ...@@ -12,6 +12,7 @@ import * as fs from 'fs';
import * as path from 'path'; import * as path from 'path';
import * as cp from 'child_process'; import * as cp from 'child_process';
import { PPromise, TPromise } from 'vs/base/common/winjs.base';
import * as baseMime from 'vs/base/common/mime'; import * as baseMime from 'vs/base/common/mime';
import { ILineMatch, IProgress } from 'vs/platform/search/common/search'; import { ILineMatch, IProgress } from 'vs/platform/search/common/search';
import { FileWalker } from 'vs/workbench/services/search/node/fileSearch'; import { FileWalker } from 'vs/workbench/services/search/node/fileSearch';
...@@ -40,8 +41,7 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> { ...@@ -40,8 +41,7 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> {
private limitReached: boolean; private limitReached: boolean;
// private worker: cp.ChildProcess; // private worker: cp.ChildProcess;
private client: Client; private channels: any[] = [];
private channel: any;
private onResult: any; private onResult: any;
...@@ -51,7 +51,6 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> { ...@@ -51,7 +51,6 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> {
this.walker = walker; this.walker = walker;
this.contentPattern = config.contentPattern.pattern; this.contentPattern = config.contentPattern.pattern;
const pattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, { matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true }); const pattern = strings.createRegExp(config.contentPattern.pattern, config.contentPattern.isRegExp, { matchCase: config.contentPattern.isCaseSensitive, wholeWord: config.contentPattern.isWordMatch, multiline: false, global: true });
console.log('pattern: ' + pattern.toString());
this.isCanceled = false; this.isCanceled = false;
this.limitReached = false; this.limitReached = false;
this.maxResults = config.maxResults; this.maxResults = config.maxResults;
...@@ -69,21 +68,24 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> { ...@@ -69,21 +68,24 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> {
// }); // });
// this.worker.send({ initialize: { contentPattern: config.contentPattern.pattern }}); // this.worker.send({ initialize: { contentPattern: config.contentPattern.pattern }});
this.client = new Client(
uri.parse(require.toUrl('bootstrap')).fsPath, for (let i=0; i<4; i++) {
{ let client = new Client(
serverName: 'Search Worker', uri.parse(require.toUrl('bootstrap')).fsPath,
timeout: 60 * 60 * 1000, {
args: ['--type=searchWorker'], serverName: 'Search Worker',
env: { timeout: 60 * 60 * 1000,
AMD_ENTRYPOINT: 'vs/workbench/services/search/node/worker/searchWorkerApp', args: ['--type=searchWorker'],
PIPE_LOGGING: 'true', env: {
VERBOSE_LOGGING: 'true' AMD_ENTRYPOINT: 'vs/workbench/services/search/node/worker/searchWorkerApp',
}, PIPE_LOGGING: 'true',
// debugBrk: 5878 VERBOSE_LOGGING: 'true'
} },
); // debugBrk: 5878
this.channel = this.client.getChannel('searchWorker'); }
);
this.channels.push(client.getChannel('searchWorker'));
}
// process.on('exit', () => this.worker.kill()); // process.on('exit', () => this.worker.kill());
} }
...@@ -94,7 +96,7 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> { ...@@ -94,7 +96,7 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> {
} }
public search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void { public search(onResult: (match: ISerializedFileMatch) => void, onProgress: (progress: IProgress) => void, done: (error: Error, complete: ISerializedSearchComplete) => void): void {
this.channel.call('initialize', { contentPattern: this.contentPattern }); this.channels.forEach(channel => channel.call('initialize', { contentPattern: this.contentPattern }));
let resultCounter = 0; let resultCounter = 0;
this.onResult = onResult; this.onResult = onResult;
...@@ -125,8 +127,10 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> { ...@@ -125,8 +127,10 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> {
}; };
// Walk over the file system // Walk over the file system
const files = [];
let size;
this.walker.walk(this.rootFolders, this.extraFiles, result => { this.walker.walk(this.rootFolders, this.extraFiles, result => {
const size = result.size || 1; size = result.size || 1;
this.total += size; this.total += size;
// If the result is empty or we have reached the limit or we are canceled, ignore it // If the result is empty or we have reached the limit or we are canceled, ignore it
...@@ -138,15 +142,25 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> { ...@@ -138,15 +142,25 @@ export class Engine implements ISearchEngine<ISerializedFileMatch> {
progress(); progress();
const absolutePath = result.base ? [result.base, result.relativePath].join(path.sep) : result.relativePath; const absolutePath = result.base ? [result.base, result.relativePath].join(path.sep) : result.relativePath;
this.channel.call('search', absolutePath).then(fileMatch => { files.push(absolutePath);
// console.log('got result: ' + fileMatch);
if (fileMatch && fileMatch.lineMatches.length) {
onResult(fileMatch);
}
unwind(size);
});
}, (error, isLimitHit) => { }, (error, isLimitHit) => {
const portionSize = Math.ceil(files.length/this.channels.length);
TPromise.join(this.channels.map((c, i) => {
const subsetFiles = files.slice(portionSize*i, portionSize*i + portionSize);
return c.call('search', subsetFiles).then(matches => {
// console.log('got result: ' + fileMatch);
matches.forEach(m => {
if (m && m.lineMatches.length) {
onResult(m);
}
})
});
})).then(() => {
unwind(this.total);
})
this.walkerIsDone = true; this.walkerIsDone = true;
this.walkerError = error; this.walkerError = error;
unwind(0 /* walker is done, indicate this back to our handler to be able to unwind */); unwind(0 /* walker is done, indicate this back to our handler to be able to unwind */);
......
...@@ -39,13 +39,46 @@ export class SearchWorker { ...@@ -39,13 +39,46 @@ export class SearchWorker {
private nResults = 0; private nResults = 0;
private running = true;
private results = [];
private paths;
private finalCallback;
constructor(args: any) { constructor(args: any) {
this.contentPattern = strings.createRegExp(args.contentPattern, false, { multiline: false, global: true, matchCase: false }); this.contentPattern = strings.createRegExp(args.contentPattern, false, { multiline: false, global: true, matchCase: false });
profiler.startProfiling('p1'); console.log('worker started: ' + Date.now());
}
private start(p: string) {
return this.doSearch(p).then(fileMatch => {
this.results.push(fileMatch);
if (this.paths.length) {
this.start(this.paths.pop());
} else if (this.running) {
this.running = false;
this.finalCallback(this.results.filter(r => !!r));
}
})
} }
public search(absolutePath: string): TPromise<FileMatch> { public search(absolutePaths: string[]): TPromise<FileMatch[]> {
// profiler.startProfiling('p1');
console.log('starting search: ' + Date.now());
this.paths = absolutePaths;
for (let i=0; i<50; i++) {
this.start(absolutePaths[i]);
}
return new TPromise(resolve => {
this.finalCallback = resolve;
});
}
public doSearch(absolutePath: string): TPromise<FileMatch> {
let fileMatch: FileMatch = null; let fileMatch: FileMatch = null;
// console.log('doing search: ' + absolutePath); // console.log('doing search: ' + absolutePath);
...@@ -74,12 +107,13 @@ export class SearchWorker { ...@@ -74,12 +107,13 @@ export class SearchWorker {
// Read lines buffered to support large files // Read lines buffered to support large files
this.readlinesAsync(absolutePath, perLineCallback, { bufferLength: 8096, encoding: 'utf8' }, resolve); this.readlinesAsync(absolutePath, perLineCallback, { bufferLength: 8096, encoding: 'utf8' }, resolve);
}).then(() => { }).then(() => {
if (this.nResults++ === 100) { // if (this.nResults++ === 200) {
const p1 = profiler.stopProfiling('p1'); // const profile = profiler.stopProfiling('p1');
p1.export() // profile.export(function(error, result) {
.pipe(fs.createWriteStream('/Users/roblou/code/vscode/p1.cpuprofile')) // fs.writeFileSync('p1.cpuprofile', result);
.on('finish', () => p1.delete()); // profile.delete();
} // });
// }
return fileMatch; return fileMatch;
}); });
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册