Author |
Topic  |
|
CliffyP
Ketchup Master
   
63 Posts |
Posted - May 18 2019 : 4:40:03 PM
|
Doing a find reference on a symbol that has a common/generic name can be extremely slow. Even if that specific symbol is actually only used in a few places... |
|
accord
Whole Tomato Software
    
United Kingdom
3287 Posts |
Posted - May 19 2019 : 7:07:31 PM
|
Do you see messages related to creating templates in the status bar? It is one thing that can be slow. It looks like this:
 |
 |
|
feline
Whole Tomato Software
    
United Kingdom
19147 Posts |
Posted - May 20 2019 : 05:09:50 AM
|
Another thought, in the Find References Results window, do you have search all projects, the button "Display references from all projects" turned On or Off? If you are working in a large solution, with a lot of projects, then searching more code will be slower than searching less code, rather obviously. |
zen is the art of being at one with the two'ness |
 |
|
CliffyP
Ketchup Master
   
63 Posts |
Posted - May 28 2019 : 2:50:42 PM
|
yes, yes.
I am aware of the project limit option. Not sure how well that works in ue4, I just let it search all to make sure I don't miss anything. |
 |
|
feline
Whole Tomato Software
    
United Kingdom
19147 Posts |
Posted - May 29 2019 : 2:18:43 PM
|
OK, to try and pin this down I have loaded VS2017, using VA 2333.0, and a new, default Puzzle Unreal project. Sitting inside the puzzle game project I have triggered Find References on "Super", figuring this is a good test of a common string.
Searching the entire solution, so the puzzle plus Unreal Engine 4.22 Find References took about 8 minutes, start to finish.
Not fast, but given the amount of code to parse and understand, this does not strike me as terrible. How does this compare to what you are seeing? Is this the sort of performance you are getting? Are you seeing Find References take an hour? 20 seconds?
This search returned 572 (+29 hidden) references in 141 files. For context, Open File in Solution, when set to only show files in the current solution, is showing a total of 41,934 files. This is the second number in the title bar of the Open File dialog. |
zen is the art of being at one with the two'ness |
 |
|
CliffyP
Ketchup Master
   
63 Posts |
Posted - Feb 24 2025 : 1:53:16 PM
|
Its been five years since this post and this problem still persists, perhaps worse than ever.
Part of the problem is that Epic is using more and more generic names for things in the engine code which makes VA's find references feature less and less useful because it is simply too slow.
Like try running find references on this in UE 5.5:
UTransBuffer::Reset
I tried it, and I let it go for I dunno how long, 15 minutes? I lost patience after that and stopped it. |
 |
|
feline
Whole Tomato Software
    
United Kingdom
19147 Posts |
Posted - Feb 26 2025 : 12:15:50 PM
|
Were you getting any results before you stopped the find?
Doing the same search here, on a UE 5.3 solution, I got my first results after 1 minute 30 seconds, and its clearly going to take a while to finish the full search.
The problem is, I am not sure what we could realistically do about this. Our database looks for symbol definitions, not all symbol calls. To make a full database of every symbol call, and its full scope information, would be both very slow and very large. Now if you were going to use a large portion of this database that might make sense. But Open File is showing over 56,000 files. Find Symbol dialog isn't listing the UE symbols for me, but I am not sure I want to know how many there are. But, realistically, you are only going to want to run Find References on a tiny portion of them. So we can probably assume that 99.9% of this database is never going to be used. But we don't know which 99.9%.
Am I missing an obvious approach here? Quite happy to accept that I may be missing something very obvious. |
zen is the art of being at one with the two'ness |
 |
|
feline
Whole Tomato Software
    
United Kingdom
19147 Posts |
Posted - Feb 26 2025 : 12:38:26 PM
|
I had left that Find References running, and it finished in just under half an hour. I agree, this is fairly useless for a quick search. But, if we can take this as a guide as to how long it will take to search for and properly resolve references, it suggests building a full database could take a few hours, at the very least.
If you only need these results for a few symbols, you can use the Clone Results button in the Find References Results to save the result, once it is finally generated. I do accept this isn't a great solution, but the UE code base is rather large, which complicates matters somewhat. |
zen is the art of being at one with the two'ness |
 |
|
CliffyP
Ketchup Master
   
63 Posts |
Posted - Feb 27 2025 : 5:44:05 PM
|
quote: Originally posted by feline ... you can use the Clone Results button in the Find References Results to save the result, ...
I'm not new to VA...
When I use VA's Find References feature, I expect to see all the references and only the references.
When it doesn't show me all the references and misses some (which it does), that is a failure of its purpose.
When it takes too long to produce the full results, then it loses its usefulness. |
 |
|
CliffyP
Ketchup Master
   
63 Posts |
Posted - Feb 27 2025 : 9:52:50 PM
|
quote: Originally posted by feline The problem is, I am not sure what we could realistically do about this. Our database looks for symbol definitions, not all symbol calls. To make a full database of every symbol call, and its full scope information, would be both very slow and very large. Now if you were going to use a large portion of this database that might make sense. But Open File is showing over 56,000 files. Find Symbol dialog isn't listing the UE symbols for me, but I am not sure I want to know how many there are. But, realistically, you are only going to want to run Find References on a tiny portion of them. So we can probably assume that 99.9% of this database is never going to be used. But we don't know which 99.9%.
Am I missing an obvious approach here? Quite happy to accept that I may be missing something very obvious.
I have no idea how VA does what it does as its not public right? I thought it ran its own c++ parser to figure out what is what, beyond that I don't know the details.
How does it figure out which are the references to the one we called find references on, when the name is the same? Presumably it is a similar way to the way c++ does it when it compiles?
The part I don't understand is why it would take longer for VA to find refs on one thing than it does to compile the project after I modify that very thing.
It's not like VA is single threaded right? It seems more like its a problem where it is not narrowing its search well enough, and it also has the 'guess hits' which I don't understand why its guessing anything since its not like c++ is guessing. |
 |
|
feline
Whole Tomato Software
    
United Kingdom
19147 Posts |
Posted - Feb 28 2025 : 07:09:46 AM
|
The first steps in compiling code are stripping out all of the comments, and expanding all of the macros, along with pulling in the included files. All of this "heavily" modifies the code files. The more macros you use, and the more complex they are, obviously, the more this modifies the files. UE is quite, probably very, macro heavy.
The thing is, VA has to parse and work in your code as you are editing it, we don't get to modify the files like the compiler does. Once you consider this, you can see that this makes things harder.
Then we get to template code, where we don't get to generate all of the template instances as code files either.
Now consider that VA is mainly helpful when you are editing, so the code is "incomplete", so doesn't compile. The compiler is completely free to just stop when the code is invalid, but we do our best to keep going and make as much sense as we can of everything.
A Find References guess hit, in an ideal world, would never happen. In reality, it happens when VA sees the symbol, but cannot work out the correct scope for the symbol, so we cannot know if it should be included or excluded. The easiest examples for this are invalid code, code you are currently editing but doesn't actually compile. This is the sort of situation where "I guessed" is actually a reasonable response from Find References.
In code that does compile, guess hits are harder to pin down, but one easy example would be where a single macro has multiple definitions, depending on OS. VA may be using the "wrong" version of the macro, resulting in our parser not being able to understand the code correctly. Or it may actually be a piece of code that our parser fails to parse correctly, which I will put in a bug report for, if its a new problem.
Some guess hits that have turned up in Unreal Engine over time are due to macros that confuse our parser, causing us to completely miss some class members, so when these unknown class members are used in code, VA simply cannot parse the code, since it appears invalid. Rare, but those tend to take some digging into to understand and try to solve when they get reported.
All of this applies to all "normal" code. When you consider the Qt library, or Unreal Engine, both tools run their own "extra" compiler step before the normal compiler gets called. This extra step generates extra code files that are required to compile, so properly understand, all of the code.
VA has its own tricks to try and simplify all of this, and work around it a bit better, but hopefully this explains the background a bit.
Find References is indeed multithreaded, but comparing us to the compiler is actually a good way to understand this. Since we don't actually get to compile anything, we are trying to expand all macros and template code in memory to get the correct scope, every time we find the symbol name you are searching for, to see if it has the correct, matching, scope or not.
Further, the compiler will save out its intermediate files, so any that are still valid are re-used without recompiling anything. So your next compiler pass is normally faster. We do something similar in that we don't reparse stable include directories, or the UE engine if we consider it to be stable. But our stable include directories is only a list of symbols, their types, and where they are.
Find References doesn't save out its search conclusions to reuse them like this. If you are going to be running the same Find References hundreds of times then it would make sense to do so. But our expectation is that you will run many different Find References, so saving out the intermediate results isn't worth it. Is this assumption wrong for you? |
zen is the art of being at one with the two'ness |
 |
|
CliffyP
Ketchup Master
   
63 Posts |
Posted - Mar 01 2025 : 12:12:23 PM
|
quote: Originally posted by feline we don't get to modify the files like the compiler does.
You don't? Why not? It's not like the compiler is modifing the source file, the compiler creates its proxies where it does its includes and all that, I thought VA would have done the same, I don't know why it wouldn't be allowed to, its just more cached derived data, whats the problem?
quote: Originally posted by feline Unreal Engine, both tools run their own "extra" compiler step before the normal compiler gets called
That is a pre-compile step yes but it is also done up-front before a project is opened with the generate project files bat or from the uproject context menu.
quote: Originally posted by feline ... every time we find the symbol name you are searching for, to see if it has the correct, matching, scope or not.
So when its looking for UTransBuffer::Reset it is checking the scopes of all Reset symbols in the project and in order for it to do that it has to expand the templates/macros and all that for each? But isn't that the problem? It shouldn't need to check all of them, UTransBuffer:: is the scope, so shouldn't it narrow the search to that scope when looking for the Reset symbol?
quote: Originally posted by feline Is this assumption wrong for you?
It's fine. Caching the results might be useful for carrying results over from one session to the next but I'd rather it just be faster.
|
 |
|
feline
Whole Tomato Software
    
United Kingdom
19147 Posts |
Posted - Mar 03 2025 : 09:04:53 AM
|
Assume we modify the cpp file, and expand all of the macros, and the template types. We then need to map every key press, every edit, between the file you are working in, and the modified file that is easier to parse. But as soon as you type a macro name, use Alt-G on a macro, you are using a symbol that does not exist in the modified "true" file.
I am not saying this cannot be done, but it is going to introduce a whole pile of problems. This is before you consider all of the code that gets removed by the pre-processor since it isn't live in the current compilation mode, even though this is code that you may well still be working on.
This is one of those things that will work wonderfully some of the time, and turn into a total nightmare other times.
I don't know enough about how UE is compiled to comment on the extra step. I do know that years ago, when I used to work with the Qt library a lot, the extra files were generated at compile time, which obviously meant that unless you had done a compile, the "moc" files, the extra code files, would be out of date and inaccurate if you had modified the class declaration but not yet re-compiled. Which can get fun if the code then doesn't compile, but you are relying on these files being generated properly to understand the code.
But this is just another form of wanting VA to do its best when we can assume the code does not compile most of the time, since you are actively editing it.
For the code checking, just taking a random example from the Find References Results list, from my search for "UTransBuffer::Reset", one of the results is in the file "EditorAutomationTests.cpp", and is the line:
GEditor->Trans->Reset( NSLOCTEXT( "UnrealEd.Test", "ConvertToValidationClear", "ConvertToValidation Clear" ) );
here we need to work out the type of both "GEditor" and "Trans" before we can draw any conclusions. Alt-G on "Trans" tells me this is:
TObjectPtr<class UTransactor> Trans;
so all of this needs to be worked out and considered.
For a direct call to "Reset()" in a class member function, you need to check the class the member belongs to, etc.
Once you start digging into edge cases for Find References, you can find some rather confusing code, I assure you 
Now, having said all of this, I restarted Visual Studio 2022 today, to re-run the Find References on "UTransBuffer::Reset" and the find seemed to run a lot faster. I didn't time it, since I left it running in the background, but it does look like various things are being cached.
At a guess, template knowledge is being stored in our symbol database.
Now, assuming this is the case, an important consideration comes up. When Visual Assist detects that the IDE crashed, it automatically re-builds its symbol database. This is going to clear some cached information. I mention this since I am currently trying, and failing, to set up a separate test for Unreal Engine. So far today I must have watched VS2022 crash at least 10 times. And this is without even having VA installed.
So if you run into crashes in Visual Studio, this is going to complicate matters. |
zen is the art of being at one with the two'ness |
 |
|
CliffyP
Ketchup Master
   
63 Posts |
Posted - Mar 03 2025 : 3:42:52 PM
|
"how UE is compiled"
The files have the .generated file type prefix, there is generated.h and generated.cpp files cached out. Such files are only created for thing that are using the reflection system, so anything that uses the UClass or UStruct macros and has the #include for the generated header in it would have the corresponding generated files created for it.
"But this is just another form of wanting VA to do its best when we can assume the code does not compile most of the time, since you are actively editing it."
But its not really? Find Refs is for code navigation/comprehension. Most of the time I spend using it the project is not in an uncompilable or uncompiled state.
Like when I run Find Refs I'm not then actively modifying the very thing I'm trying to find refs on, or even related things.
" just taking a random example from the Find References Results list"
Yah but the problem isn't so much the quality of the results list, its the speed at which it takes to complete it. Like what is its starting point and how does it filter down?
"So if you run into crashes in Visual Studio, this is going to complicate matters."
I am using VS 2022 but not had any crashes that I can remember, has been stable. I don't know if it makes a difference but I'm not on latest version of VA, I only just recently updated it to 2530.
|
 |
|
feline
Whole Tomato Software
    
United Kingdom
19147 Posts |
Posted - Mar 04 2025 : 08:53:02 AM
|
It depends what you are using Find References on, but yes, I can certainly see that a lot of the time you will be using it on stable code.
But back to speeding it up, the only obvious method I am seeing here is to index all of the code more fully before hand. The concerns with this are still the time and CPU load to do so, and the storage space. With Unreal Engine especially, recent versions of VA have produced major improvements in parsing time, which are quite important sometimes. It is easy to dismiss storage space as a concern, but it is something we need to keep a vague eye on.
So I am wary of suggesting we do a much bigger index parse. But I am not sure how else we can try to speed up Find References significantly on a large code base.
Do you restart Visual Studio every day / night, or does it just stay open? I am wondering how helpful cloning the Find References Results window is for you, to keep a copy of results you will need to go back to and re-check later on. Are you aware you can right click in the Find References Results window, and use "Copy All" from the context menu, to copy out and "back up" the results list? If you use the filter field first, you only get the filtered results.
I am not suggesting that this is a fix or a solution, but if there are certain symbols you need to do a find on, and then remember the results to re-check over time, this is an option that can help. But obviously it is of no help when you want information on a symbol that has never been searched for before.
Crashes, its a very individual problem. Some people report that the system is rock solid with Unreal Engine, while others report a lot of crashes. Yesterday I gave up after over 20 crashes in a row with Unreal Engine, and that was a clean system with no Visual Assist installed. It turns out I needed to add more RAM to the VM to stop the endless crashes, but it put the thought very firmly in my mind. |
zen is the art of being at one with the two'ness |
 |
|
CliffyP
Ketchup Master
   
63 Posts |
Posted - Mar 04 2025 : 7:07:42 PM
|
"and the storage space"
I can buy more storage space, as working with UE5 has required multiple times (it is such bloatware), what I can't buy is more time. Trading storage space for time is a good deal. Perhaps it should be an option.
"Do you restart Visual Studio every day"
Yep.
"It turns out I needed to add more RAM"
If you think that's bad, try actually using UE5. I have 64 GB of ram and the only way I could stop getting OOM crashes is to have managed page files on all my drives. Just yesterday I recorded the UE5 editor using 200 GB of memory.
So yes UE5 is a monolith of bloat, sadly I also have to use it to earn a living.
|
Edited by - CliffyP on Mar 04 2025 7:08:04 PM |
 |
|
feline
Whole Tomato Software
    
United Kingdom
19147 Posts |
Posted - Mar 05 2025 : 10:33:08 AM
|
Having a hunt, it turns out we do have a feature request for a form of indexing of the solution, specifically for Find References. I am not sure how likely this is to happen, but I have added your points to the case. Unreal Engine, and these search times, makes for a compelling argument:
case=149275 |
zen is the art of being at one with the two'ness |
 |
|
|
Topic  |
|
|
|