Skip to content
This repository has been archived by the owner on Apr 14, 2022. It is now read-only.

Stubs aren't analyzed before their modules #907

Closed
jakebailey opened this issue Apr 8, 2019 · 9 comments
Closed

Stubs aren't analyzed before their modules #907

jakebailey opened this issue Apr 8, 2019 · 9 comments
Assignees
Labels
bug Something isn't working performance

Comments

@jakebailey
Copy link
Member

This affects PyQt5 pretty heavily.

image

image

This module has a stub next to it, which was added to the module by TryCreateModuleStub, but this stub was never analyzed (the state is at Analyzing) and has an empty analysis. This leaves the LS to spend all its in the ModuleSymbolTable with 30k+ evaluators to process.

@jakebailey
Copy link
Member Author

The underlying issue for PyQt5 actually seems to be the size; we'll probably start treating library stubs specially to help this (but this issue still stands).

@AlexanderSher
Copy link
Contributor

No repro so far. Feel free to reopen it if you see it.

@MikhailArkhipov
Copy link

MikhailArkhipov commented May 26, 2019

I can repro it in tests. Request to analyze signal comes when its stub still has empty analysis.

image

@MikhailArkhipov
Copy link

MikhailArkhipov commented May 27, 2019

I think this might be because producer in the walker has all modules in the same list and may happen to produce module before its stub. Perhaps separate higher priority queue of stubs would help or making graph of stubs for the graph of modules and processing it before modules? Also, in case of parallel tasks task for the module might start before task for the stub?

@AlexanderSher
Copy link
Contributor

Modules can't be produced before stubs unless there is a loop from some stub to that module, which is unlikely. Analysis will be empty if there is an error in analysis itself. In this case, we don't crash LS or terminate analysis session, but there should be a record in the log.

@MikhailArkhipov
Copy link

MikhailArkhipov commented May 30, 2019

Events:

  1. Load user module that has import logging
  2. Module finds logging dependency.
  3. logging dependency loads stub via
if (!TryCreateModuleStub(name, moduleImport.ModulePath, out var stub)) {
    stub = _interpreter.TypeshedResolution.GetOrLoadModule(moduleImport.IsBuiltin ? name : moduleImport.FullName);
}
  1. Stub is loaded and parsing starts. But since there is no await, parsing and analysis of logging (Library) starts in parallel.
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.PythonModule.Parse() Line 298	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.PythonModule.InitializeContent(string content, int version) Line 500	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.PythonModule.PythonModule(Microsoft.Python.Analysis.Modules.ModuleCreationOptions creationOptions, Microsoft.Python.Core.IServiceContainer services) Line 115	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.PythonModule.PythonModule(string moduleName, string filePath, Microsoft.Python.Analysis.Modules.ModuleType moduleType, Microsoft.Python.Analysis.Types.IPythonModule stub, Microsoft.Python.Core.IServiceContainer services) Line 88	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.CompiledPythonModule.CompiledPythonModule(string moduleName, Microsoft.Python.Analysis.Modules.ModuleType moduleType, string filePath, Microsoft.Python.Analysis.Types.IPythonModule stub, Microsoft.Python.Core.IServiceContainer services) Line 29	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.StubPythonModule.StubPythonModule(string moduleName, string stubPath, bool isTypeshed, Microsoft.Python.Core.IServiceContainer services) Line 28	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.Resolution.TypeshedResolution.CreateModule(string name) Line 62	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.Resolution.ModuleResolutionBase.ModuleRef.GetOrCreate(string name, Microsoft.Python.Analysis.Modules.Resolution.ModuleResolutionBase mrb) Line 158	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.Resolution.ModuleResolutionBase.GetOrLoadModule(string name) Line 97	C#
>	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.Resolution.MainModuleResolution.CreateModule(string name) Line 106	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.Resolution.ModuleResolutionBase.ModuleRef.GetOrCreate(string name, Microsoft.Python.Analysis.Modules.Resolution.ModuleResolutionBase mrb) Line 158	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.Resolution.ModuleResolutionBase.GetOrLoadModule(string name) Line 97	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Analyzer.PythonAnalyzer.LoadMissingDocuments(Microsoft.Python.Analysis.IPythonInterpreter interpreter, Microsoft.Python.Core.Collections.ImmutableArray<Microsoft.Python.Analysis.Analyzer.AnalysisModuleKey> missingKeys) Line 306	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Analyzer.PythonAnalyzer.TryCreateSession(int graphVersion, Microsoft.Python.Analysis.Analyzer.PythonAnalyzerEntry entry, out Microsoft.Python.Analysis.Analyzer.PythonAnalyzerSession session) Line 251	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Analyzer.PythonAnalyzer.AnalyzeDocument(Microsoft.Python.Analysis.Analyzer.AnalysisModuleKey key, Microsoft.Python.Analysis.Analyzer.PythonAnalyzerEntry entry, Microsoft.Python.Core.Collections.ImmutableArray<Microsoft.Python.Analysis.Analyzer.AnalysisModuleKey> dependencies) Line 218	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Analyzer.PythonAnalyzer.EnqueueDocumentForAnalysis(Microsoft.Python.Analysis.Types.IPythonModule module, int bufferVersion) Line 163	C#
 	Microsoft.Python.Analysis.dll!Microsoft.Python.Analysis.Modules.PythonModule.Parse(System.Threading.CancellationToken cancellationToken) Line 352	C#

later logging (Library) simple gets queued again when stub becomes available. From what I see in the log, it gets processed 4 times (I guess b/c more stubs become available and dependent module analysis changes causing logging to be analyzed again.

@MikhailArkhipov
Copy link

Add

Debug.Assert(!(_stubAnalysis is EmptyAnalysis))

to ModuleWalker.MergeStub. Test:

import types

image

@MikhailArkhipov
Copy link

Need to check with #1470, may have been fixed.

@MikhailArkhipov MikhailArkhipov removed this from the June 2019.2 milestone Sep 4, 2019
@MikhailArkhipov
Copy link

Haven't seen it for a while, there is an assert there that does not trigger.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working performance
Projects
None yet
Development

No branches or pull requests

3 participants