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

Rewrite project event forwarder. #1544

Conversation

bjorkstromm
Copy link
Member

  • The previous implementation had one lock for all events. This implementation only locks for same event.
  • The previous implementation had a 500ms delay before getting project information request. Don't think that's necessary anymore. Especially not after removing support for project.json. MSBuild project system will make sure all projects in the queue are processed before returning project information.

Quickly tested, and it felt like large code bases loaded faster.

Here be dragons...

- The previous implementation had one lock for all events. This implementation only locks for same event.
- The previous implementation had a 500ms delay before getting project information request. Don't think that's necessary anymore. Especially not after removing support for project.json. MSBuild project system will make sure all projects in the queue are processed before returning project information.
@bjorkstromm bjorkstromm force-pushed the rewrite-project-event-forwarder branch from e5a49b9 to 5ed2fd3 Compare July 7, 2019 21:15
@bjorkstromm
Copy link
Member Author

@filipw is there a way to know that a project system is enabled but not yet initialized?
https://github.com/OmniSharp/omnisharp-roslyn/pull/1544/files#diff-e6170c657dc5cf9a062216bde7c8deb9R91

I think it would be wise in startup to wait for the project system to initialize before pushing project information.

@filipw
Copy link
Member

filipw commented Jul 8, 2019

yeah at the moment, no. the Initialized flag is false both for disabled and enabled but not yet initialized projects. I guess we could expose another flag, Enabled?

@nickspoons
Copy link
Member

Would these initialisation flags by any chance help with #1521?

@bjorkstromm
Copy link
Member Author

@nickspoons yes, Initialized flag introduced in #1543 should help with that. Problem is that we should probably wait for Enabled project system to get initialized, otherwise we might miss a request, or like in this PR, don’t forward a project event.

}

if (e != null)
var added = false;
using (await _eventLocks.GetOrAdd(workspaceEvent, _ => { added = true; return new AsyncLock(); }).LockAsync())
Copy link

@rchande rchande Jul 8, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think what this code is trying to say is:

  • For a given event type, attempt to add a lock over that workspace type
  • If my valueCreator is called, I am the one who added the lock
  • Because of that I can lock my lock and do my processing

However, per the remarks here:

However, the valueFactory delegate is called outside the locks to avoid the problems that can arise from executing unknown code under a lock. Therefore, GetOrAdd is not atomic with regards to all other operations on the ConcurrentDictionary<TKey,TValue> class. Since a key/value can be inserted by another thread while valueFactory is generating a value, you cannot trust that just because valueFactory executed, its produced value will be inserted into the dictionary and returned.

So I don't think this is going to have the desired effect.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's where something like BlockingCollection might work better in this scenario, we're just locking because HashSet is not thread safe, but in reality we want the data to push out asap, the delay doesn't need to be there for sure.

OnWorkspaceChanged adds an item to the queue synchronously. Then we spin up a dedicated thread that just sits and does TryTake(out var item, TimeSpan.Infinity) and just writes out to the emitter. This lets us queue these operations up, and dequeue them as quickly as possible.

Another option is to use System.Reactive and buffer the requests so that we pipe out all events every <500 ms (or whatever)>.

The blocking collection works well for LSP, so it should probably work okay here.

Copy link

@rchande rchande left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure this works as intended :)

@bjorkstromm
Copy link
Member Author

@rchande you are absolutely correct! Back to double locking (or do we even need locks?). Problem is that project system might be in a completely different state, so that was probably why it was double locking before, and it had a 500ms delay. The 500ms delay should not be needed as getting project info from MSBuild project system empties the processing queue before responding. The lock would then just assure we don’t send multiple events of the same form within a specific time. What are these events used for on VSCode side?

@rchande
Copy link

rchande commented Jul 8, 2019

@mholo65 C# extension sends these events in response to file change notifications from VS Code. I think we just need to make sure whatever we come up with maintains the same "correctness" we had before. IMO, it might be nice to make some more concrete statements about the gains than "Quickly tested, and it felt like large code bases loaded faster." :)

@filipw
Copy link
Member

filipw commented Jan 9, 2020

what is the status of this? 😀

@bjorkstromm
Copy link
Member Author

@filipw

what is the status of this? 😀

Probably not going to happen in current form. Without any tests around "how it should work", we'll probably just end up breaking things 😄 I must however say that the await Task.Delay(500); in the original code annoys me very much.

@filipw
Copy link
Member

filipw commented Mar 2, 2020

@mholo65 I will close this PR then, because they start to pile up - please open a new one when you feel like it's ready 😀

@filipw filipw closed this Mar 2, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants