-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Limit Jedi RAM consumption #744
Conversation
@@ -1,1660 +1,1667 @@ | |||
{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure why diff is so large
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
White spaces, I think you have re-formatted package.json (you're probably using tabs instead of spaces). Do you have the the editor config extension installed?
Codecov Report
@@ Coverage Diff @@
## master #744 +/- ##
==========================================
+ Coverage 62.63% 62.65% +0.01%
==========================================
Files 242 242
Lines 11236 11256 +20
Branches 2033 2037 +4
==========================================
+ Hits 7038 7052 +14
- Misses 4190 4196 +6
Partials 8 8
Continue to review full report at Codecov.
|
src/client/common/extensions.ts
Outdated
.catch(() => { | ||
if (onError) { | ||
//vscode.window.createOutputChannel(STANDARD_OUTPUT_CHANNEL).appendLine(`Promise exception: ${reason.ToString()}`); | ||
onError(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we be capturing the reason and passing that through to the onError
function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which logger should I use
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the purpose of doNotWait
. If i'm not mistaken, we'd only use this in case where we don't care about any exceptions raised at all. Hence I'd say, we don't care about the errors, that's why we didn't have any error handlers in the first place. If we do want them, then i'd put the logging in the code itself, rather than creating an extension method.
So, all we need is:
/**
* Explicitly tells that promise should be run asynchonously.
*/
Promise.prototype.doNotWait = function(this: Promise) {
this.catch(()=>{});
// or this.catch(nop);
};
Now, when you look at the code, this extension feels kind of redundant or we should rename it to something such as ignoreErrors()
.
Because technically this still returns a promise that will get resolved. So it not about waiting or not. We just want to ignore the errors.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The purpose is to explicitly state that we don't want to await here by design. Generally caller doesn't care about exceptions, but may appreciate if they are logged.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In C# we have SilenceException
and DoNotWait
. The latter indicates that task runs freely and is not awaited, but it does rethrow exceptions.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's make this one into ignoreErrors
. We can discuss rethrowing separately
src/client/common/extensions.ts
Outdated
} | ||
}) | ||
.then(() => { | ||
if (onComplete) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd removed all the parameters completely. If the purpose of this extension is to let promises not to wait, then all we need is a catch inside this and it should log if necessary.
Else this function is identical to a standard promise, apart from the fact that we have a default catch handler.
Ie this extension should do what it says, not to wait. However we are adding callbacks for when it completes. I.e. we are waiting.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, you are right. I confused C# 'ContinueWith' with 'then'. Primary purpose is to make tslint happy.
src/client/providers/jediProxy.ts
Outdated
this.pythonSettings.on('change', () => this.pythonSettingsChangeHandler()); | ||
this.initialized = createDeferred<void>(); | ||
// tslint:disable-next-line:no-empty | ||
this.startLanguageServer().catch(() => { }).then(() => this.initialized.resolve()); | ||
this.startLanguageServer().doNotWait(() => this.initialized.resolve()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't l like this, we're just creating a water for promises.
Ideally we need to handle the then
the normal way, then after that we can call the doNotWit as follows:
this.startL...().then(()=> this.initialized.resolve()).doNotWait()
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I.e. doNotWait should not require any args, else it's same as a promise but epmty default catch handler.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK. So this.startLanguageServer().catch(() => { }).then(() => this.initialized.resolve()); actually waits?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this.startLanguageServer().catch(() => { }).then(() => this.initialized.resolve());
no, the problem is the last method this.initialized.resolve()
invoked in the chain could fail, hence tslint wants us to handle errors at the end.
So, the solution is:
this.startLanguageServer()
.catch(() => { })
.then(() => this.initialized.resolve())
.catch(() => { });
Or:
this.startLanguageServer()
.catch(() => { })
.then(() => this.initialized.resolve())
.doNotWait();
I think we need a global const for nop
(where const nop = ()=> {};
)
this.startLanguageServer()
.catch(nop)
.then(() => this.initialized.resolve())
.catch(nop)
Again, all the promises are getting chained, and TS lint wants us to catch an exception from the last method in the chain.
Fixes #263
Introduces setting for the Jedi RAM limit. Default (0) means 1024 MB. Max 8GB.
RAM consumption is checked every 2 seconds and completion.py process is killed if threshold is exceeded. Process is then auto-restarted.