Skip to content
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

Merged
merged 70 commits into from
Feb 9, 2018
Merged

Limit Jedi RAM consumption #744

merged 70 commits into from
Feb 9, 2018

Conversation

MikhailArkhipov
Copy link

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.

@@ -1,1660 +1,1667 @@
{
Copy link
Author

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

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
Copy link

codecov bot commented Feb 9, 2018

Codecov Report

Merging #744 into master will increase coverage by 0.01%.
The diff coverage is 71.87%.

Impacted file tree graph

@@            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
Impacted Files Coverage Δ
src/client/common/types.ts 100% <ø> (ø) ⬆️
src/client/common/configSettings.ts 91.71% <100%> (+0.05%) ⬆️
src/client/common/extensions.ts 88.23% <100%> (+1.56%) ⬆️
src/client/common/logger.ts 53.33% <33.33%> (-10.31%) ⬇️
src/client/providers/jediProxy.ts 72.15% <78.26%> (+0.15%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 012985c...e78e311. Read the comment docs.

.catch(() => {
if (onError) {
//vscode.window.createOutputChannel(STANDARD_OUTPUT_CHANNEL).appendLine(`Promise exception: ${reason.ToString()}`);
onError();

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

Copy link
Author

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

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.

Copy link
Author

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.

Copy link
Author

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.

Copy link
Author

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

}
})
.then(() => {
if (onComplete) {

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.

Copy link
Author

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.

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());

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()

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.

Copy link
Author

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?

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.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

RAM Consumption
2 participants