ReSharper has just started an Early Access Program for v2019.1 and there are plenty of great things we plan to add or improve. The ReSharper C++ team has started this year putting the pedal to the metal on performance optimizations in Unreal Engine 4 codebases. The changes include faster cold startup times, better memory utilization, and new settings to tweak ReSharper’s indexing behavior.
Depending on the CPU in your workstation, you may expect cold startup to become 5.5 to 6 times faster. This is the time between opening the solution and getting access to the full functionality of ReSharper C++.
A number of things have contributed to these speedups:
Algorithmic improvements in code indexing.
Skipping plugins and third-party code when indexing an Unreal Engine 4 project by default.
Faster cache serialization.
The options that affect code indexing in Unreal Engine 4 solutions are grouped under a new options page at ReSharper | Options | Code Editing | C++ | Unreal Engine.
Clear the Index third party code and Index plugins checkboxes if you want to skip source files under “Plugins” and “ThirdParty” folders from indexing, or Index Unreal Engine source files to skip the indexing of the engine code altogether.
Note that ReSharper C++ indexes engine code in the background by default. This was already implemented in 2018.3, so here’s just a friendly reminder that you can start working with your game logic code long before the engine code is fully processed. If you turn off background indexing using the Enable background indexing checkbox, this will result in a faster but more intrusive initial indexing.
Let’s make a test!
The following performance test proves the numbers we’ve mentioned above. Using Unreal Engine v4.20.3 and the “Shooter Game” project from the Epic Games Library, we measured the cold startup time for parsing game code and Unreal Engine code, respectively:
Intel i7-8700k: ReSharper C++ cold start time
Game code: 30 sec
Unreal Engine code: 23 min 00 sec
Total time: 23 min 30 sec
Game code: 30 sec (no change)
Unreal Engine code: 3 min 39 sec (6.3 times faster than before)
Total time: 4 min 12 sec (5.59 times faster)
AMD Threadripper 1950x: ReSharper C++ cold start time
Game code: 1 min
Unreal Engine code: 29 min 30 sec
Total time: 30 min 30 sec
Game code: 50 sec
(1.2 times faster than before)
Unreal Engine code: 4 min 16 sec (6.76 times faster)
Total time: 5 min 6 sec (6.08 times faster)
The numbers speak for themselves! Feel free to get the EAP build and take your own measurements on your own Unreal Engine project.
Smaller memory footprint
Besides faster initial indexing, our team has implemented many memory usage optimizations. Both the memory traffic during initial indexing and the memory footprint afterwards have been improved in order to make the IDE more responsive.
Check out the latest ReSharper C++ 2019.1 EAP build and let us know if the IDE performance has improved for you in Unreal Engine 4 projects! As always, your feedback will be greatly appreciated. And there are more goodies coming in this area, so don’t change the channel!
Join us at Game Developers Conference 2019 later in March and chat about Unreal Engine 4 support in our tools!
Please welcome the third release of ReSharper C++ this year! v2018.1 brought debug step filters and includes analyzer, while v2018.2 came with the initial C++/CLI support and better understanding of C++17 and C++20 standards. The just released v2018.3 tunes literally every smart feature the product has, making them work more precisely on modern C++ code.
C++/CLI support has been improved with several new context and generate actions for C++/CLI code.
Solutions are loaded a lot faster, especially those that use the Unreal Engine. The main catch is that ReSharper C++ only parses non-engine projects during the initial indexing; the engine files are indexed in the background later.
Predefined naming schemes for common C++ code standards were introduced.
Refactorings, code generation, formatting, and other areas have been enhanced in various ways.
Among these improved areas, there’s one we’d like to talk about in more detail. The error annotator in ReSharper C++. These improvements are available in the recently published 2018.3 EAP 6 build. Let’s see what it’s all about! Continue reading →
While ReSharper C++ 2018.1 introduced two major new features, debug step filters and includes analyzer, ReSharper C++ 2018.2 is focused on improving its understanding of the C++ language. The biggest highlight is its long-awaited support for C++/CLI. In addition, many important features from C++17 and even the upcoming C++20 have been implemented. Code analysis is enhanced with spell-checking inspections powered by the newly bundled ReSpeller plugin, as well as formatting inspections to help you maintain a consistent code style.
ReSharper C++ joined the ReSharper fold back in 2015 to bring the power of ReSharper to the world of C++ – and has been getting better ever since! For most people this has rounded out the ReSharper story within Visual Studio. However an odd gap remains. Odd because the worlds of C++ and C# are bridged by the interop language, C++/CLI, yet this has remained unsupported by the ReSharper family.
Until now, that is!
From 2018.2 (available now in the EAP) ReSharper C++ has initial support for C++/CLI. There are some limitations, so read on to find out more. Support is enabled by default, but can be disabled by going to ReSharper | Options | Code Editing | C++ | Inspections, and unchecking “Enable C++/CLI support”. But we hope you won’t do that – especially as we’re also looking for user feedback and greater field experience.
A peculiar beast
As a rule nobody uses C++/CLI as a primary language. That’s not what it’s been designed for. While C# is a highly productive language, and is no slouch when it comes to performance, there are many reasons that we may also have a parts of our project written in pure C++. C++/CLI is an answer to the question, “how do I get to, or from, my pure C++ from C# (or any .NET language)?”. If you just need to call into C++, and it exposes a C API, P/Invoke may be the simplest way to go. But for more complex cases – where you want to model richer types and class hierarchies – C++/CLI let’s you do that. But it comes at the cost of a more complex language, with curious syntactic additions and sometimes tricky lifetime issues. So any help we can get from our tools while writing and maintaining this code is very welcome.
What is supported?
ReSharper C++ 2018.2 gives us initial support for C++/CLI projects. What does that mean? Well first it means that the parser and resolver now finally understand the extension system, with ^’s for CLR references, gcnew for allocating on the managed heap, etc. It also means that many static analysis features now work and can give us valuable insight. Note that, at time of this writing, there may still be a few limitations here. Please report these in our issue tracker so we can address them as quickly as possible.
Within C++/CLI code we have access to all the same great refactorings and intention actions as in pure C++ code. For example postfix templates are a great way to rewrite statements around a value. Where applicable these should work across C++/CLI and pure C++ codebases – for example you can rename a pure C++ symbol, or even a C# symbol, from within a C++/CLI usage. Again, some limitations may apply.
We can also navigate between C# and C++/CLI worlds. For example if we place the caret over a C++/CLI method name in some C# code you can now navigate to the definition in the C++/CLI code (note that this is referred to as “Go to declaration” in the menu, due to how these terms are used in C#). You can do the same going the other way, too.
For now there are some known limitations here. For instance from a C# project in the same solution, renaming a C++/CLI symbol is not an option. From the C++/CLI project, renaming a symbol referred to by the C# project wll rename it within the C++/CLI code, but not in the C# project. As mentioned already, renaming a native C++ symbol from a C++/CLI project works as expected, however.
Code generation is also limited for now, as generators for C++/CLI specific constructs, such as ref classes, have not yet been written. And the #using directive (for importing metadata in directly from a dll) is not supported at all – meaning both the use of the #using directive, as well as any symbols referenced from the dll, will currently be flagged as errors by the analyser.
We need your help
C++/CLI is unique in many ways. Software projects that make use of it tend to be larger enterprise style projects of in-house code bases that cannot be shared outside the organisation. There is very little in the way of non-trivial open source projects using C++/CLI. Here at JetBrains we only use it in some small ways internally to the ReShaper C++ implementation. So it is particularly difficult to build realistic test cases. As we move to expand our coverage we’ll rely a lot more on the community to tell us what’s not working (of course we’d also love to hear what’s working, too!) so we can do our best to address it and make our C++/CLI support first class.
Last week we published a detailed overview of ReSharper C++ 2018.1 changes. One of the major features for this release is Includes analyzer, a tool for locating and eliminating unnecessary header dependencies and thus upping compilation speeds. You can read about it in detail in this blog post. Today though, we’d like to give you a short demo recorded by Phil Nash, our C++ tools developer advocate. Watch the Includes analyzer in action and download the free 30-day trial of ReSharper C++ to try it on your project:
If you find Includes analyzer useful or have questions or comments about it, please use the comment section below or our issue tracker to share your feedback with us. We’ll be glad to know what you think!
We are pleased to introduce ReSharper C++ 2018.1, our first major update this year!
This release comes with two new important features. First, Debug Step Filters lets you avoid stepping into specific functions during debugging. Second, Includes Analyzer helps investigate the dependencies between header files that affect build times. Read on for more details about these features and other highlights of the 2018.1 release:
When you invoke Step Into, the Visual Studio debugger will normally step into all the functions that are called from the current statement. However, there are functions (like simple getters, setters, or dereference operators), which are either trivial or so well tested that you never want to step into them. This is where step filters come in: with this feature, you can specify the functions that should always be stepped over.
A step filter is defined by a regular expression, which is matched against the name of the function that the debugger is stepping into. You can inspect, configure, disable, or enable back step filters on the Tools | Debugging | C++ options page, which lists all the available filters.
ReSharper C++ comes with a predefined collection of step filters for the standard library, but you can easily add your own. You can come up with a custom regular expression that matches the names of functions to step over and manually add a filter from the options page. Or you can have ReSharper C++ automatically create one during a debugging session.
When you step into a function and decide that you want to step over it in the future, you can use a context action to quickly add a new step filter. For template functions, there are separate context actions to add either only the current instantiation of the function template or all of its instantiations. If a matching filter has already been added to the list but was temporarily disabled, a context action will be available to enable it back.
The filters are stored using ReSharper’s layered settings. By default, the action to add a new filter follows the Smart Save logic, but you can use the action’s submenu to choose the layer to which the filter should be saved to. For example, you can use the Solution team-shared layer to make the new filter available to your teammates.
You might remember that Visual Studio has a built-in way to customize stepping behavior in C++, which is a part of C++ Just My Code. However, no user interface is provided for configuring this feature from the IDE, so you need to manually edit .natstepfilter XML configuration files to change existing or add new rules. Furthermore, there is no way to add solution-specific rules, since the configuration files are global. Please note that at the moment Visual Studio’s support for .natstepfilter files gets disabled if ReSharper C++ is installed.
Long build times is one of the biggest problems in large real-world C++ projects. ReSharper C++ already has a few tricks up its sleeve to aid you. For example, it will mark unused #include directives or automatically create forward declarations for unresolved names instead of simply including the headers with the required declarations.
ReSharper C++ 2018.1 introduces Includes Analyzer, a brand new code inspection tool that helps you speed up the compilation process.
Includes Analyzer is meant to help you locate and eliminate unnecessary header dependencies. A typical project might contain many thousands of #include directives, and it’s not clear which of them are worth investigating. Includes Analyzer attempts to estimate the contribution of each header file to the build time, based on the number of lines of code that it adds to the total compilation workload. While this is not a precise metric, it’s a useful starting criterion which can help you find and prioritize the most included header files.
After you identify the header dependencies that potentially have the biggest impact, you can try getting rid of them one by one via the standard approaches. These include: using forward declarations wherever possible, removing unneeded #include directives, applying the Pimpl idiom, splitting header files into smaller ones, and so on.
To start the analysis, invoke one of the ReSharper | Inspect | Analyze Includes in… actions from the main menu, or select Analyze Includes from the Solution Explorer context menu.
ReSharper C++ will analyze the files in the given scope and present a report in a dedicated tool window, where you can explore the dependencies between the files. The Includes analysis window provides two separate views, Includees and Includers, both of which present include dependencies as a tree where each node corresponds to a file. You can switch between the views via the corresponding toolbar buttons, or by navigating to the same file in the other view from the context menu.
The Includees view helps you understand how many lines of code the header file in a top-level tree node contributes to all source files that directly or indirectly include it. Child nodes in this view represent files that include the file from the parent node. Consider the following analysis of the entire Catch2 solution:
There are three metrics for each node in the tree:
Times included shows how many source files include the header in the top-level node through the path to the current node. In the example above, catch_common.h was included into 75 source files in total, of which 26 included catch_common.h through the #include "catch_common.h" directive in catch_tag_alias_autoregistrar.h.
Line contribution shows how many lines of code the header in the top-level node contributed through the path to the current node by itself, without transitively included files. catch_common.h contributed 4,050 lines of code in total, which is 75 (the number of source files that include it) times 54 (the number of lines of code in the file). Out of 4,050 in total, 1,404 lines were contributed because of #include "catch_common.h" in catch_tag_alias_autoregistrar.h.
Line contribution inclusive is similar to Line contribution, but this metric takes into account all headers transitively included into the file in the top-level node. E.g. catch_common.h, together with the headers included into it, contributes 2,654,938 lines in total during compilation of the entire solution. 1,017,626 of those lines were contributed because of #include "catch_common.h" in catch_tag_alias_autoregistrar.h. Line contribution inclusive is the default and arguably the most useful sorting criteria.
The Includers view is similar to the Includees view, but acts in the opposite way: the child nodes inside the tree represent files which are included into the file from the parent node.
This view shows how many lines of code are transitively included into the file in a top-level node as if it was compiled as a standalone source file (e.g. catch_common.h together with all headers included into it comprises 42,365 lines of code, of which 27,046 were brought with #include <string>). The metrics that this view provides are Includee count (the number of included files), Line count (the size of the file itself), and Line count inclusive (the size of the file with all the header files it includes).
One important limitation of Includes Analyzer is that ReSharper C++ does not actually run a full preprocessing stage in order to speed up the analysis process. This means that the line count does not in fact include the results of macro expansions, and that include guards do not get handled as well. Instead, ReSharper C++ assumes that each header file starts with an include guard or a #pragma once directive, and gets included at most once in any source file. Each successive include of the same header does not count towards its number of contributed lines, which means that sometimes you may encounter Times included and other metrics equal to zero next to an internal tree node.
In addition to navigation controls and the refresh button, the toolbar in the Includes analysis window lets you change two options:
Show only root nodes belonging to some project will hide top-level tree nodes that correspond to files not belonging to any project. This is a quick way to filter out library files if you want to concentrate only on headers inside your solution.
By default, ReSharper C++ skips blank lines and comments during an analysis. The Count blank and comment lines button lets you change this behavior.
We would like to give a shout-out to Header Hero, which inspired our own implementation of the same underlying idea. Check out the Caring by Sharing: Header Hero blog post, which introduces this great little tool and gives a few tips for improving project build times.
ReSharper C++ 2018.1’s biggest navigation update is the redesigned Go to File Member (Alt+\) dialog.
We have updated the dialog in several ways:
Class members in the open file are now grouped by their containing class in the results list.
With no search string active, file members are sorted in the order of their declarations inside the file.
The scrolling list with the results accommodates more items.
Together, these updates make the dialog more usable as they provide clearer insight into the structure of the current file.
In all Go to dialogs and several other places, ReSharper C++ now attempts to shorten symbol names that are excessively long, by omitting function and template parameters.
When you perform a search using the Recent Files dialog (Ctrl+,), Go to File search results are also appended to the results list after the Recent File items.
Finally, the option to remember the last search in the Search Everywhere dialog is now on by default. You can revert to the old behavior through the Environment | Search & Navigation | Remember last search setting.
Command-line code cleanup
ReSharper Command Line Tools, a free standalone collection of tools that can be used from the command line or as part of the continuous integration process, can now perform code formatting and cleanup in C++ projects. This instantly eliminates code style violations in a project or solution, and helps ensure a uniform code base.
To run the code cleanup tool on your solution, invoke cleanupcode.x86.exe from the command-line tools distribution with the path to the solution file. It will automatically reformat your code, fix common code style violations, remove redundant code, and optionally apply Clang-Tidy fix-its.
By default, command-line tools will use the predefined Full Cleanup profile, which includes the formatting stage and most (though not all) fixes for common code style issues, but skips the Clang-Tidy analysis stage. The other built-in profile is Reformat Code, which will apply only code formatting preferences. To use it, pass the profile name via the --profile command-line argument of cleanupcode.x86.exe:
ReSharper 2018.1 also fixes bogus errors which were output by the InspectCode tool on x64 projects. In addition, the upcoming 2018.1 release of TeamCity is able to run InspectCode on C++ projects (see TW-48978 for details).
ReSharper C++ 2018.1 adds several new built-in inspections:
A new inspection (with a corresponding fix and a code cleanup item) suggests replacing if statements with if constexpr when the condition is a compile-time constant expression.
Attempted usages of deleted functions are now diagnosed as errors, including usages via implicit function calls.
A new inspection warns about overriding destructors without the override specifier. There’s still debate in the C++ community whether destructors should ever be marked with override (for example, C++ Core Guidelines recommend against doing that), so the inspection is turned off by default. If you wish to use this inspection, please enable it on the Code Inspection | Inspection Severity options page.
Control flow and usage checking analyses have been updated to handle lambdas. This means that all the related inspections (unused variables and function parameters, unreachable code, redundant jumps, and many others), that previously worked only with functions, are also now available inside lambda bodies.
Finally, a minor change fixes the interaction between the Declarator is never used inspection and C++17 structured binding declarations. Previously, ReSharper C++ warned you about each unused structured binding separately from all the other bindings in the same declaration. We’ve changed this behavior so that if at least one of the structured bindings is used, the inspection does not trigger on any of the bindings.
Now all the major C++ compilers follow this logic, including MSVC starting with the update shipped in Visual Studio 15.7. If none of the bindings are used, you can still use the [[maybe_unused]] attribute to silence the inspection, but in practice you probably won’t ever need to.
More ways to configure inspection severity
In previous ReSharper C++ releases, inspection severity could only be set for the entire solution. But it is often required to be able to configure severity settings independently in different parts of the codebase, for example in legacy or test projects. In ReSharper С++ 2018.1, you can optionally enable the ability to have separate severity settings via the Read settings from EditorConfig and project settings option on the Code Inspection | Settings | General options page.
With this option turned on, you can set custom inspection severity using one of two approaches:
EditorConfig files. ReSharper C++ inspection severity can be specified inside an EditorConfig file using resharper_[severity id]_highlighting properties, where [severity id] is the name of the severity spelled in lower case with underscores. Depending on your needs, you can assign any value of do_not_show, hint, suggestion, warning or error to the property.
EditorConfig supports wildcard patterns in filenames, which means that inspection severity can be set independently even for specific files. A previous blog post entitled Configuring inspection severity with EditorConfig goes into more detail about using EditorConfig files, but do remember that you need to enable the option Code Editing | General Formatter Style | Enable EditorConfig support in order to have EditorConfig available.
Please note that enabling granular inspection severity might have a noticeable performance impact on the speed of code analysis, depending on your configuration and the number of issues in a given file.
Clang-Tidy integration updates
Clang 6.0 was released this March. To keep up, we have updated the Clang-Tidy binary bundled with ReSharper C++, with several user-visible changes:
The following checks have changed their prefix from misc- to bugprone-: misc-argument-comment, misc-assert-side-effect, misc-bool-pointer-implicit-conversion, misc-dangling-handle, misc-fold-init-type, misc-forward-declaration-namespace, misc-inaccurate-erase, misc-move-forwarding-reference, misc-multiple-statement-macro, misc-string-constructor, misc-use-after-move, misc-virtual-near-miss.
The following checks have changed their prefix from misc- to performance-: misc-inefficient-algorithm, misc-move-const-arg, misc-move-constructor-init, misc-noexcept-move-constructor.
Another new Clang-Tidy feature from the 6.0 release is the extended syntax of the NOLINT comment, which now accepts an optional list of check names to silence. ReSharper C++ adds a new inspection action that utilizes the new syntax and lets you disable a specific Clang-Tidy diagnostic on the current line:
We have also received several reports of Clang-Tidy crashes, with Windows displaying crash notifications as a result. While the ReSharper C++ team cannot fix the crashes themselves, we have changed the default error reporting mode used by the clang-tidy binary to prevent the annoying message boxes.
Unit testing support includes two minor updates:
ReSharper C++ 2018.1.1 fixes compatibility with Boost.Test from Boost 1.67 (which was broken because of a bug in Boost.Test).
The new setting Tools | Unit Testing | C++ Tests | Use command-line arguments… lets you manage whether ReSharper C++ should use the value of the Debugging | Local Windows Debugger | Command Arguments project property when running unit tests.
Other changes to ReSharper C++ include:
The #include_next preprocessor directive is now supported, for better compatibility with compilers that implement this GNU extension.
Typing assistance in C++ files automatically removes trailing whitespaces on Enter in order to keep your code clean of redundant whitespaces.
If you select an expression and open the Quick Documentation window, it will show various information about the selected expression, such as its type, value, and value category. You can use this ability, for example, to quickly evaluate a type trait for a specific type:
The /Y- (ignore precompiled header options) and /Zc:__cplusplus (enable the updated value of the __cplusplus macro) command-line MSVC compiler arguments are supported.
The performance of the completion pop-up and start-up time have been improved in several cases.
If you’d like to learn more about how C++ tools can improve your development workflow, Anastasia Kazakova (C++ tools PMM at JetBrains) recently gave a talk at the ACCU 2018 conference entitled Debug C++ Without Running. In her talk, Anastasia discusses a few peculiarities of the C++ language that contribute to its notorious complexity and demonstrates some helpful features from ReSharper C++, CLion, and other C++ tools.
Why do you need step filters? Well, the illustration below explains pretty much everything:
Some functions never need to be stepped into because they are either very simple or very well tested. But the problem is that the debugger cannot tell which functions are worth debugging and which aren’t, and therefore Step Into will not miss any user function on its way.
Visual Studio’s Just My Code functionality takes basic care of this problem by ignoring non-user code and letting you customize ignored symbols using text config files.
However with ReSharper C++, you can now visually maintain step filters — a list of function masks that tells the debugger what should be skipped on stepping. By default, this list includes a lot of library functions and it can be extended.
Of course, ReSharper wouldn’t be ReSharper without having some handy goodies here: to quickly add a function to the filters, you can press Alt+Enter on that function while debugging and pick the corresponding action:
The filters are stored using ReSharper’s layered settings. By default, the action saves the filter in the ‘Solution personal’ layer, but you can use the action’s submenu to choose where the filter should be saved — e.g in the ‘Solution team-shared’ layer, so that this filter will be also available to your teammates.
You can study and further configure step filters on the Tools | Debugging | C++ options page: