codecadwallader / codemaid

CodeMaid is an open source Visual Studio extension to cleanup and simplify our C#, C++, F#, VB, PHP, PowerShell, JSON, XAML, XML, ASP, HTML, CSS, LESS, SCSS, JavaScript and TypeScript coding.
http://www.codemaid.net
GNU Lesser General Public License v3.0
1.9k stars 358 forks source link

TextEditorEventListener.TextEditorEvents_LineChanged throws on every Output Window update #745

Open olegtk opened 4 years ago

olegtk commented 4 years ago

Visual Studio telemetry indicates one of the top UI delays is caused by this symbol:

stevecadwallader.codemaid.dll!SteveCadwallader.CodeMaid.Integration.Events.TextEditorEventListener.TextEditorEvents_LineChanged

The scenarios appears to be building large solution. On each Output Window update TextEditorEventListener.TextEditorEvents_LineChanged is called synchronously on the UI thread and the following line throws because there is no EnvDTE.Document corresponding to the Output Window (EnvDTE.Document represents document window):

var document = startPoint.Parent.Parent;

I suggest ignore Output Window and other non code files by checking first startPoint.Parent.Language - it will be "Plain Text" for the Output window and other txt files and text buffers hosted in other tool windows.

codecadwallader commented 4 years ago

Thanks for reporting the issue and proposing a fix. I haven't been able to reproduce yet that accessing startPoint.Parent.Parent causes an exception to be thrown. I'm seeing it simply return null as expected and the following if guard exits out cleanly. Can you please provide some more information (e.g. what version of VS, how you're getting the telemetry) so that I can look to reproduce it as well?

olegtk commented 3 years ago

It's not a crash so I don't have a repro, but I thought it should be trivial to repro the exception by just running a build. This issue is detected by Visual Studio PerfWatson as UI delay and it only captures UI thread. The delay affects all 16.0 versions seemingly, the rate is not that high, but for some reason significantly increased in 16.9. Here is all I got:

clr.dll!CLREventWaitHelper2 clr.dll!CLREventWaitHelper clr.dll!CLREventBase::WaitEx clr.dll!SVR::gc_heap::user_thread_wait clr.dll!WKS::gc_heap::background_gc_wait clr.dll!WKS::gc_heap::try_allocate_more_space clr.dll!WKS::gc_heap::allocate_large_object clr.dll!WKS::GCHeap::Alloc clr.dll!Alloc clr.dll!SlowAllocateString clr.dll!FramedAllocateString mscorlib.dll!System.String.Concat mscorlib.dll!System.Exception.InternalPreserveStackTrace clr.dll!CallDescrWorkerInternal clr.dll!CallDescrWorkerWithHandler clr.dll!MethodDescCallSite::CallTargetWorker clr.dll!ExceptionPreserveStackTrace clr.dll!RealCOMPlusThrow clr.dll!RealCOMPlusThrow clr.dll!MarshalNative::ThrowExceptionForHR microsoft.visualstudio.editor.implementation.dll!Microsoft.VisualStudio.Editor.Implementation.TextDocData.get_DTEDocument microsoft.visualstudio.editor.implementation.dll!Microsoft.VisualStudio.Editor.Implementation.TextDocData.EnvDTE.IExtensibleObject.GetAutomationObject ?!dynamicClass.IL_STUB_COMtoCLR clr.dll!COMToCLRDispatchHelper clr.dll!COMToCLRWorker ?!? msenv.dll!CTextDocument::get_Parent ?!dynamicClass.IL_STUB_CLRtoCOM stevecadwallader.codemaid.dll!SteveCadwallader.CodeMaid.Integration.Events.TextEditorEventListener.TextEditorEvents_LineChanged ?!EnvDTE._dispTextEditorEvents_SinkHelper.LineChanged clr.dll!CallDescrWorkerWithHandler clr.dll!CallDescrWorkerReflectionWrapper clr.dll!RuntimeMethodHandle::InvokeMethod mscorlib.dll!System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal mscorlib.dll!System.Reflection.RuntimeMethodInfo.Invoke clr.dll!CallDescrWorkerInternal clr.dll!CallDescrWorkerWithHandler clr.dll!MethodDescCallSite::CallTargetWorker clr.dll!DispatchInfo::InvokeMemberWorker clr.dll!DispatchInfo::InvokeMemberDebuggerWrapper clr.dll!DispatchInfo::InvokeMember clr.dll!InternalDispatchImpl_Invoke clr.dll!InternalDispatchImpl_Invoke_CallBack clr.dll!InternalDispatchImpl_Invoke_Wrapper msenv.dll!CProxy_dispTextEditorEvents::Fire_LineChanged msenv.dll!CTextEditorEvents::FireTextEditorEvent msenv.dll!ExtensibilityFireLineCommitEvent msenv.dll!CTextManager::FireTextEditorEvent microsoft.visualstudio.editor.implementation.dll!dynamicClass.IL_STUB_CLRtoCOM microsoft.visualstudio.editor.implementation.dll!Microsoft.VisualStudio.Editor.Implementation.TextDocData.ExtensibilityFireLineCommitEvent microsoft.visualstudio.editor.implementation.dll!Microsoft.VisualStudio.Editor.Implementation.TextDocData.OnTextBufferChanged microsoft.visualstudio.platform.vseditor.dll!Microsoft.VisualStudio.Text.Utilities.GuardedOperations.RaiseEvent microsoft.visualstudio.platform.vseditor.dll!Microsoft.VisualStudio.Text.Implementation.BaseBuffer.RawRaiseEvent microsoft.visualstudio.platform.vseditor.dll!Microsoft.VisualStudio.Text.Implementation.BaseBuffer+TextContentChangedEventRaiser.RaiseEvent microsoft.visualstudio.platform.vseditor.dll!Microsoft.VisualStudio.Text.Implementation.BufferGroup.FinishEdit microsoft.visualstudio.platform.vseditor.dll!Microsoft.VisualStudio.Text.Implementation.BaseBuffer+TextBufferEdit.Apply microsoft.visualstudio.editor.implementation.dll!Microsoft.VisualStudio.Editor.Implementation.TextDocData+<>c__DisplayClass_0.b__ microsoft.visualstudio.editor.implementation.dll!Microsoft.VisualStudio.Editor.Implementation.TextDocData.ReplaceLinesHelper microsoft.visualstudio.editor.implementation.dll!Microsoft.VisualStudio.Editor.Implementation.TextDocData.ReplaceLinesEx ?!dynamicClass.IL_STUB_COMtoCLR clr.dll!COMToCLRDispatchHelper clr.dll!COMToCLRWorker ?!? msenv.dll!TextLines_Append msenv.dll!ResultList_OutputString msenv.dll!COutputWindowPane::OutputStringInternalEx msenv.dll!COutputWindowPane::OutputStringDeferredEx msenv.dll!COutputWindowPane::OutputString msenv.dll!CSUIBuilder::OutputStringNoPump csproj.dll!CLangBuildMgr::ProcessErrorTaskFromMSBuild csproj.dll!CLangBuildMgr::AddBuildMessageFromMSBuild csproj.dll!CVsBuildFeedback::LogTextMessage microsoft.visualstudio.commonide.dll!dynamicClass.IL_STUB_CLRtoCOM microsoft.visualstudio.commonide.dll!Microsoft.VisualStudio.Build.ComInteropWrapper.HostLogger.Write microsoft.build.dll!Microsoft.Build.BackEnd.Logging.ParallelConsoleLogger.WriteBasedOnPrefix microsoft.build.dll!Microsoft.Build.BackEnd.Logging.ParallelConsoleLogger.WriteMessageAligned microsoft.build.dll!Microsoft.Build.BackEnd.Logging.ParallelConsoleLogger.PrintMessage microsoft.build.dll!Microsoft.Build.BackEnd.Logging.ParallelConsoleLogger.MessageHandler

codecadwallader commented 3 years ago

Thanks for the call stack. I still don't see it throwing an error when I debug through it, but I agree we're not trying to listen to text changes on the output window. Since we offer cleanup on .txt and README files which are also listed as Plain Text I think we would need a different way to distinguish editor vs. tool window scenarios.

olegtk commented 3 years ago

Yeah, you are right, plain text is too wide. I don't know off hand any better option, but there must be some way, perhaps through IExtensibleObject.