-
Notifications
You must be signed in to change notification settings - Fork 169
Improve performance when fetching Decls. #679
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
Conversation
0ad2f48 to
d2dfe56
Compare
In this particular case, the int i = 0;
CXCursor currentDecl = Handle.GetDecl(i);
do
{
yield return TranslationUnit.GetOrCreate<Decl>(currentDecl);
currentDecl = currentDecl.NextDeclInContext;
}
while (!currentDecl.IsNull);If This would allow the implementation to be something like this: _decls = LazyList.Create<Decl>(Handle.NumDecls, (i, initializedDecls) => {
if (i == 0)
{
return Handle.GetDecl(0);
}
else
{
return initializedDecls[^1].NextDeclInContext;
}
}
); |
The current implementation in clangsharp_Cursor_getDecl to get a Decl is an N^2 algorithm; getting a Decl for index X means looping through all the previous indices 0-(X-1) first. This is rather slow when dealing with hundreds of thousands of Decl instances, here's a screenshot from Instruments showing 74% of the time spent in clangsharp_Cursor_getDecl: <img width="921" height="348" alt="Screenshot 2026-01-07 at 12 47 26" src="https://github.com/user-attachments/assets/c96d5611-683e-4f0d-9878-cc551ba60c71" /> So I added a way in LazyList to use an existing item to get the next item, and then use Decl.NextDeclInContext to take advantage of this, effectively making an N algorithm (which becomes 2N, because we iterate over all the Decls first to count them). My main scenario now runs in ~51 seconds instead of 3m05 seconds, so less that 1/3 of the time.
c048e20 to
2dad035
Compare
|
I tried your suggestion, and it works! Speed increase is quite comparable (not sure if it's worse or better, because I'm not using the exact same test case, but it's very much in the same ballpark). Also it's a fully managed solution, so existing tests work fine. |
The current implementation in clangsharp_Cursor_getDecl to get a Decl is an N^2 algorithm; getting a Decl for index X means looping through all the previous indices 0-(X-1) first.
This is rather slow when dealing with hundreds of thousands of Decl instances, here's a screenshot from Instruments showing 74% of the time spent in clangsharp_Cursor_getDecl:
So I added a way in LazyList to use an existing item to get the next item, and then use Decl.NextDeclInContext to take advantage of this, effectively making an N algorithm (which becomes 2N, because we iterate over all the Decls first to count them).
My main scenario now runs in ~51 seconds instead of 3m05 seconds, so less that 1/3 of the time.