Skip to content
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

Performance fixes #2610

Merged
merged 7 commits into from Jan 30, 2019

Conversation

Projects
None yet
2 participants
@brainplot
Copy link
Contributor

commented Jan 17, 2019

Type of change

  • Bug fix (non-breaking change which fixes an issue)

Description and Context

Just a few more performance improvements spotted thanks to Clang-Tidy and Clazy.

  • Use QFileInfo's exists() static method
    According to the docs, this static method is faster than the instance method of the same class. I simply replaced it accordingly.

  • Replace QMap with QHash when the key is a pointer:
    In a map where the key is a pointer, hash-based lookups are faster than tree-based lookups, as you only have to compute the hash of a number which is an O(1) operation, as opposed to the O(log(n)) complexity of the Red-Black tree of QMaps.

  • Avoid copying QSharedPointers when not needed
    Many QSharedPointers were passed by value even though they did not modify the object pointed to in any way. They have been changed to const QSharedPointer<*>&. Also a few copies were avoided thanks to std::move().
    Actually I took a while to inspect the code a little more carefully and to me it feels like they can all be QScopedPonters or std::unique_ptrs passed by const reference (i.e. without taking ownership) but I didn't want to change that because I thought I may be missing something so I'm just bringing this up for now waiting for your feedback.

  • Avoid creation of temporary containers
    I know we've discussed this already but I couldn't figure out why the static analyzer kept complaining about the creation of temporary containers. It turns out that Qt containers may detach when used as rvalues in a loop. These code examples show that containers must be used as a const lvalue to make sure they won't detach. Basically, by simply storing them in a const variable did the trick in the case of rvalues, using asConst in core/Global.h worked for lvalues; now the static analyzer no longer shows the warnings about temporary containers.
    To prove that, I set up Qt in a local instance of Compiler Explorer and gave it this test code:

#include <QtGlobal>
#include <QMap>
#include <QString>

static const QMap<QString, QString> deprecationMap = {
    // >2.3.4
    {"security/hidepassworddetails", "security/HidePasswordPreviewPanel"},
    // >2.3.4
    {"GUI/HideDetailsView", "GUI/HidePreviewPanel"},
    // >2.3.4
    {"GUI/DetailSplitterState", "GUI/PreviewSplitterState"},
    // >2.3.4
    {"security/IconDownloadFallbackToGoogle", "security/IconDownloadFallback"},
};

void upgrade()
{
    const auto keys = deprecationMap.keys(); // <--
    for (const auto& setting : keys) {
        qWarning("%s\n", setting);
    }
}

The Assembly produced by this was 50 lines shorter than the same code using deprecationMap.keys() in the loop directly. (compiled with gcc -O3)

  • Wrap static literal strings with QStringLiteral
    The QStrings in the deprecation map were implicitly constructed with the const char* constructor which creates a dynamically-allocated string. The map, however, is used in read-only mode and the values are all known at compile time so they can be allocated statically with QStringLiteral.

Testing strategy

I ran all existing tests and they all passed.

Checklist:

  • I have read the CONTRIBUTING document. [REQUIRED]
  • My code follows the code style of this project. [REQUIRED]
  • All new and existing tests passed. [REQUIRED]
  • I have compiled and verified my code with -DWITH_ASAN=ON. [REQUIRED]
@droidmonkey

This comment has been minimized.

Copy link
Member

commented Jan 29, 2019

Can you please rebase this on the newly formatted code. Make sure to run "make format" before you push.

@droidmonkey droidmonkey added this to the v2.4.0 milestone Jan 29, 2019

@brainplot brainplot force-pushed the brainplot:performance-fixes branch 2 times, most recently from 98968f3 to 8eb934b Jan 29, 2019

@brainplot

This comment has been minimized.

Copy link
Contributor Author

commented Jan 29, 2019

Done! 👍

brainplot added some commits Jan 17, 2019

Use QFileInfo's exists() static method
The exists() static method is documented to be faster than its
equivalent member method.

See https://doc.qt.io/qt-5/qfileinfo.html#exists-1
Replace QMap with QHash when the key is a pointer
QHash gives faster lookups than QMap when the key is a pointer.
Wrap static literal strings with QStringLiteral
The strings in the deprecation map are never modified in the program and
they're known at compile time. An internal resizable buffer is not
needed for these strings so we can allocate them statically.

@droidmonkey droidmonkey force-pushed the brainplot:performance-fixes branch from 8eb934b to 0dac53d Jan 30, 2019

@droidmonkey droidmonkey merged commit 7f3ce65 into keepassxreboot:develop Jan 30, 2019

3 of 4 checks passed

Windows 10 (KeepassXC) TeamCity build failed
Details
CodeFactor No issues found.
Details
MacOS (KeepassXC) TeamCity build finished
Details
Ubuntu Linux (KeepassXC) TeamCity build finished
Details

@brainplot brainplot deleted the brainplot:performance-fixes branch Jan 30, 2019

droidmonkey added a commit that referenced this pull request Mar 19, 2019

Release 2.4.0
- New Database Wizard [#1952]
- Advanced Search [#1797]
- Automatic update checker [#2648]
- KeeShare database synchronization [#2109, #1992, #2738, #2742, #2746, #2739]
- Improve favicon fetching; transition to Duck-Duck-Go [#2795, #2011, #2439]
- Remove KeePassHttp support [#1752]
- CLI: output info to stderr for easier scripting [#2558]
- CLI: Add --quiet option [#2507]
- CLI: Add create command [#2540]
- CLI: Add recursive listing of entries [#2345]
- CLI: Fix stdin/stdout encoding on Windows [#2425]
- SSH Agent: Support OpenSSH for Windows [#1994]
- macOS: TouchID Quick Unlock [#1851]
- macOS: Multiple improvements; include CLI in DMG [#2165, #2331, #2583]
- Linux: Prevent Klipper from storing secrets in clipboard [#1969]
- Linux: Use polling based file watching for NFS [#2171]
- Linux: Enable use of browser plugin in Snap build [#2802]
- TOTP QR Code Generator [#1167]
- High-DPI Scaling for 4k screens [#2404]
- Make keyboard shortcuts more consistent [#2431]
- Warn user if deleting referenced entries [#1744]
- Allow toolbar to be hidden and repositioned [#1819, #2357]
- Increase max allowed database timeout to 12 hours [#2173]
- Password generator uses existing password length by default [#2318]
- Improve alert message box button labels [#2376]
- Show message when a database merge makes no changes [#2551]
- Browser Integration Enhancements [#1497, #2253, #1904, #2232, #1850, #2218, #2391, #2396, #2542, #2622, #2637, #2790]
- Overall Code Improvements [#2316, #2284, #2351, #2402, #2410, #2419, #2422, #2443, #2491, #2506, #2610, #2667, #2709, #2731]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.