purejava / keepassxc-cryptomator

Plug-in for Cryptomator to store vault passwords in KeePassXC
https://plugin.purejava.org
MIT License
96 stars 4 forks source link

High CPU usage and power usage #8

Closed tobiaskarch closed 2 years ago

tobiaskarch commented 2 years ago

Please agree to the following

Summary

Cryptomator has a high CPU usage and power usage at idle when this plugin is installed

What software is involved?

Steps to Reproduce

  1. Copy keepassxc-cryptomator-1.1.2.jar into %homepath%\AppData\Roaming\Cryptomator\Plugins
  2. Launch KeePassXC
  3. Launch Cryptomator

Expected Behavior

Barely or no difference in CPU usage and power usage at idle compared to Cryptomator without this plugin installed

Actual Behavior

Cryptomator has a high CPU usage and power usage at idle

image

Reproducibility

Always

Relevant Log Output

01:04:23.673 [main] INFO  org.cryptomator.launcher.Cryptomator - Starting Cryptomator 1.6.9 on Windows 10 10.0 (amd64)
01:04:23.680 [main] DEBUG org.cryptomator.logging.DebugMode - Debug mode enabled
01:04:23.681 [main] DEBUG o.c.launcher.SupportedLanguages - Using system locale
01:04:23.721 [main] INFO  org.cryptomator.ipc.Server - Spawning IPC server listening on socket C:\Users\tobias\AppData\Roaming\Cryptomator\ipc.socket
01:04:23.771 [main] DEBUG o.c.launcher.IpcMessageHandler - Received launch args: 
01:04:23.772 [main] DEBUG org.cryptomator.launcher.Cryptomator - Did not find running application instance. Launching GUI...
01:04:24.044 [JavaFX Application Thread] INFO  org.cryptomator.launcher.Cryptomator - JavaFX runtime started after 557ms
01:04:24.053 [JavaFX Application Thread] DEBUG o.c.i.common.ClassLoaderFactory - Found jars in cryptomator.pluginDir: /C:/Users/tobias/AppData/Roaming/Cryptomator/Plugins/keepassxc-cryptomator-1.1.2.jar
01:04:24.196 [JavaFX Application Thread] DEBUG org.cryptomator.common.CommonsModule - Starting App Scheduled Executor 01
01:04:24.199 [App Scheduled Executor 01] DEBUG org.cryptomator.common.CommonsModule - Starting App Scheduled Executor 02
01:04:24.199 [JavaFX Application Thread] DEBUG o.c.i.common.ClassLoaderFactory - Found jars in cryptomator.pluginDir: /C:/Users/tobias/AppData/Roaming/Cryptomator/Plugins/keepassxc-cryptomator-1.1.2.jar
01:04:24.200 [JavaFX Application Thread] DEBUG o.c.i.common.IntegrationsLoader - UiAppearanceProvider: Found implementation: org.cryptomator.windows.uiappearance.WinUiAppearanceProvider in jar /C:/Program%20Files/Cryptomator/app/mods/integrations-win-1.1.0.jar
01:04:24.209 [JavaFX Application Thread] DEBUG o.c.i.common.IntegrationsLoader - UiAppearanceProvider: Implementation is available: org.cryptomator.windows.uiappearance.WinUiAppearanceProvider
01:04:24.262 [JavaFX Application Thread] TRACE o.cryptomator.ui.fxapp.FxApplication - FxApplication.start()
01:04:24.320 [JavaFX Application Thread] DEBUG o.c.ui.fxapp.FxApplicationTerminator - Enabling sudden termination
01:04:24.322 [JavaFX Application Thread] DEBUG o.c.i.common.ClassLoaderFactory - Found jars in cryptomator.pluginDir: /C:/Users/tobias/AppData/Roaming/Cryptomator/Plugins/keepassxc-cryptomator-1.1.2.jar
01:04:24.323 [JavaFX Application Thread] DEBUG o.c.i.common.IntegrationsLoader - TrayMenuController: Found implementation: org.cryptomator.ui.traymenu.AwtTrayMenuController in jar /C:/Program%20Files/Cryptomator/app/mods/cryptomator-1.6.9.jar
01:04:24.328 [JavaFX Application Thread] DEBUG o.c.i.common.IntegrationsLoader - TrayMenuController: Implementation is available: org.cryptomator.ui.traymenu.AwtTrayMenuController
01:04:24.442 [JavaFX Application Thread] DEBUG o.c.u.traymenu.AwtTrayMenuController - initialized tray icon
01:04:24.449 [JavaFX Application Thread] DEBUG org.cryptomator.common.CommonsModule - Starting App Background Thread 001
01:04:24.794 [JavaFX Application Thread] DEBUG org.cryptomator.ui.common.FontLoader - Loaded family: Font Awesome 5 Free Solid
01:04:24.810 [JavaFX Application Thread] TRACE o.c.u.m.MainWindowTitleController - init MainWindowTitleController
01:04:24.831 [JavaFX Application Thread] DEBUG o.c.i.common.ClassLoaderFactory - Found jars in cryptomator.pluginDir: /C:/Users/tobias/AppData/Roaming/Cryptomator/Plugins/keepassxc-cryptomator-1.1.2.jar
01:04:24.833 [JavaFX Application Thread] DEBUG o.c.i.common.IntegrationsLoader - KeychainAccessProvider: Found implementation: org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess in jar /C:/Program%20Files/Cryptomator/app/mods/integrations-win-1.1.0.jar
01:04:24.836 [JavaFX Application Thread] DEBUG o.c.i.common.IntegrationsLoader - KeychainAccessProvider: Found implementation: org.purejava.integrations.keychain.KeePassXCAccess in jar /C:/Users/tobias/AppData/Roaming/Cryptomator/Plugins/keepassxc-cryptomator-1.1.2.jar
01:04:24.838 [JavaFX Application Thread] DEBUG o.c.i.common.IntegrationsLoader - KeychainAccessProvider: Implementation is available: org.cryptomator.windows.keychain.WindowsProtectedKeychainAccess
01:04:24.855 [JavaFX Application Thread] DEBUG o.c.i.common.IntegrationsLoader - KeychainAccessProvider: Implementation is available: org.purejava.integrations.keychain.KeePassXCAccess
01:04:25.091 [JavaFX Application Thread] TRACE o.c.ui.mainwindow.ResizeController - init ResizeController
01:04:25.095 [JavaFX Application Thread] TRACE o.c.u.m.MainWindowController - init MainWindowController
01:04:25.472 [JavaFX Application Thread] DEBUG o.cryptomator.ui.fxapp.FxApplication - Main window initialized after 1985ms
01:04:29.814 [JavaFX Application Thread] DEBUG org.cryptomator.common.CommonsModule - Starting App Background Thread 002
01:04:29.815 [JavaFX Application Thread] DEBUG o.cryptomator.ui.fxapp.UpdateChecker - Checking for updates...
01:04:30.151 [JavaFX Application Thread] INFO  o.cryptomator.ui.fxapp.UpdateChecker - Current version: 1.6.9, lastest version: 1.6.9

Anything else?

Without the plugin installed: image

purejava commented 2 years ago

Yes, it's true. Unfortunately, there's nothing that can be done about it right now. Let me elaborate a litte on this: A less power consuming solution would be to get notified, when a message / answer from KeePassXC arrives at the plugin. These are notifications like when the KeePassXC database was locked or unlocked or answers to requests sent by the plugin.

Notifications of that kind require an underlying framwork / protocol handler that inludes these. Whereas the Mac and Linux implementation of the protocol handler provide these, the Windows implementation does not. So, unless KeePassXC uses something different than a named pipe to connect KeePassXC and a client, the only way to listen on the established connection for incoming messages is to launch a thread, that listens on the connection. This is consuming RAM and power.

When you let the thread sleep for a certain time, the power consumption would go down, but the whole communcation towards the KeePassXC backend would slow down and the Cryptomator UI woud become more unresponsive.

dico-hubnc commented 2 years ago

Hello, I was happy to find a solution to unlock my vault by using KeePassXC, but after some hours I discovered the same trouble (nearly 20% CPU on idle with no vault open, and no file access to the vault of 1.25GB). My fan makes noise all the time. So, I simply remove this plugin. I read your comment above (purejava) about explanations but I'm not convinced. Even if you have a constant connection between KeePassXC and Cryptomator, there is nothing to do 99% of time....it's just to pull if messages are present. Moreover, as I'm also on Windows 10 21H1 (Cryptomator 1.6.10) with Edge, Firefox and Thunderbird that have KeePassXC plugin also, they are open all the day in parallel with KeePassXC unlocked, and absolutely no issue with CPU. I do not know how they develop their plugin but on Windows is possible to avoid wasted CPU. Hope you will find a solution. Regards, Dico

purejava commented 2 years ago

I read your comment above (purejava) about explanations but I'm not convinced. Even if you have a constant connection between KeePassXC and Cryptomator, there is nothing to do 99% of time....it's just to pull if messages are present.

Is that so? I am always wondering how people can insist on something without any understanding of the topic.

Moreover, as I'm also on Windows 10 21H1 (Cryptomator 1.6.10) with Edge, Firefox and Thunderbird that have KeePassXC plugin also, they are open all the day in parallel with KeePassXC unlocked, and absolutely no issue with CPU. I do not know how they develop their plugin but on Windows is possible to avoid wasted CPU. Hope you will find a solution.

You are asking for an asynchronous notification mechanism, as soon, as a new message arrives. KeePassXC talks to browser extensions via Native Messaging, which is exactly that. And which is only available to browsers. The Thunderbird plug-in relies on Native Messaging too.

When you are outside of the browser world or Thunderbirds browser engine, Native Messaging is not available.

If you are aware of a way to use Native Messaging outside of a browser from a desktop application, please let me know and I‘ll be happy to implement it.

droidmonkey commented 2 years ago

Hello, I can confirm this CPU usage is crazy. You must be running an incredibly tight loop checking for messages every nanosecond. You could keep your current implementation and just add a small delay (1 second?) to prevent such a usage of CPU. However, that should not be necessary at all because we implemented the browser integration to be request/response. You request something to happen (unlock database, retrieve entry, etc) and we respond to that. 99.999% of the time you are not doing anything with KeePassXC.

Native Messaging is a browser specific term that means an application spawned by the browser process can transfer information via STDIN. Talking to KeePassXC itself is done through sockets (in the browser, the proxy application handles this), for this plugin you use direct socket communication, no need for the STDIN portion.

I don't have the time to setup a full debug flow for this plugin, but it appears your error is in this loop:

https://github.com/purejava/keepassxc-proxy-access/blob/7e4e447d1e1948e9df3e03d0f3e8e0fe0a3c96e1/src/main/java/org/keepassxc/Connection.java#L87-L110

You have no waits or sleeps in here at all, also there is likely no information to retrieve from the socket so you are constantly considering that an "error" and disconnecting and reconnecting the socket. That is not an appropriate assumption.

This is the KeePassXC Proxy reference implementation: https://github.com/keepassxreboot/keepassxc/blob/15b9e82f93971a1cd2f63f3b21eafcf3601ec70c/src/proxy/NativeMessagingProxy.cpp#L92-L105

Now we are using Qt socket implementation but we don't attempt to say there is a socket error when there is nothing to read (that is not an error), we wait until something appears in the socket buffer then read it.

purejava commented 2 years ago

Thanks @droidmonkey for your effort and explanations.

Hello, I can confirm this CPU usage is crazy. You must be running an incredibly tight loop checking for messages every nanosecond. You could keep your current implementation and just add a small delay (1 second?) to prevent such a usage of CPU. However, that should not be necessary at all because we implemented the browser integration to be request/response. You request something to happen (unlock database, retrieve entry, etc) and we respond to that. 99.999% of the time you are not doing anything with KeePassXC.

Your are right: in the end it was my implementation that caused the high CPU usage, as a check to wait for an asynchronous response was too tight.

As I elaborated earlier, the plugin does use the request/response procedure to communicate with the KeePassXC backend.

Native Messaging is a browser specific term that means an application spawned by the browser process can transfer information via STDIN. Talking to KeePassXC itself is done through sockets (in the browser, the proxy application handles this), for this plugin you use direct socket communication, no need for the STDIN portion.

Yes, I know. I read through the Mozilla documentation on Native Messaging and checked KeePassXC's code and KeePassXC's browser extension code on making this plugin.

You have no waits or sleeps in here at all, also there is likely no information to retrieve from the socket so you are constantly considering that an "error" and disconnecting and reconnecting the socket. That is not an appropriate assumption.

That's wrong. This code checks, whether the connection to the KeePassXC backend got lost and pauses the checking for new messages from there, unless the KeePassXC backend is available again. So on using the plugin, when the KeePassXC application gets closed, the plugin handles this case as well as it tests for a possible re-connect every few seconds. When KeePassXC is started again, the plugin continues to communicate with it as before.

purejava commented 2 years ago

Fixed by https://github.com/purejava/keepassxc-proxy-access/commit/b353c02cfb17a052a1db09f6031c70525433debb. The fix was released with keepassxc-cryptomator 1.1.3 yesterday.

droidmonkey commented 2 years ago

Confirm this fixes the problem entirely. Interesting enough, Cryptomator itself idles with some CPU usage at rest with no unlocked vaults (~0.04% on my computer).