Code based on pull/5804. Tested only on macOS 10.13.3 and should support 10.9+.
What macOS versions bitcoin core currently supports?
Code based on pull/5804. Tested only on macOS 10.13.3 and should support 10.9+.
What macOS versions bitcoin core currently supports?
5 | +#include <Foundation/Foundation.h> 6 | + 7 | +class CAppNapInhibitorInt 8 | +{ 9 | +public: 10 | + id<NSObject> activityId;
Is there a difference in using NSObject *activityId?
17 | + (NSActivityUserInitiatedAllowingIdleSystemSleep | 18 | + NSActivityLatencyCritical) & 19 | + ~(NSActivitySuddenTerminationDisabled | 20 | + NSActivityAutomaticTerminationDisabled); 21 | + 22 | + if ([[NSProcessInfo processInfo] respondsToSelector:@selector(beginActivityWithOptions:reason:)])
nit: code styling, use brackets {}
28 | +{ 29 | +#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 30 | + if ([[NSProcessInfo processInfo] respondsToSelector:@selector(endActivity:)]) 31 | + [[NSProcessInfo processInfo] endActivity:priv->activityId]; 32 | +#endif 33 | + delete priv;
Since we are only holding a NSObject pointer, is this deallocation really required or could it even be messing with the autorelease pool?
utACK e41bb4a4568e08fe75ab8af7de7db1a2684cd989
Will review later. Good question regarding which macOS version to support. The release notes state 10.8+, but I wonder how true that is. Apple pushes macOS updates quite aggressively and the lack of VM's make downgrades impractical. So unless any of the active devs here still runs an older version, I don't think it's realistic to support anything but the current macOS release and maybe one earlier version .
We do currently support 10.8+ and I have VMs for all OSX versions from 10.5 upwards. I do test the RC regularly in 10.8 till 10.x VMs.
@jonasschnelli ok, that's great to know. Any hints for setting up a 10.8 VM on an iMac?
Concept ACK. Should appnap always be disabled, or just during initial sync? It's something that could be done later, but worth thinking about I think.
I think it's reasonable* to expect bitcoind users to understand their OS power management.
how to i squash all my commits in PR they contain merging commits from upstream/master :confused:
Squashed all my commits into single one.
OS X Mountain Lion 10.8 not supported by Apple anymore. Mozilla/Google don't support 10.8 either in their web browsers. Qt 5.7 (currently used in bitcoin-qt0.16.0) support expired in June 15, 2017. Qt 5.8 supports only 10.9+. Qt 5.9 only 10.10+. So OS X 10.8 support in bitcoin-qt pretty much pointless since it requires Qt 5.6/5.7 and very old XCode to build.
How about using this for bitcoin-qt only ?
Would make sense to me. Would (for me) be preferable to having objective C in the core code.
I think it's reasonable* to expect bitcoind users to understand their OS power management.
Virtually no one uses bitcoind on MacOSX. For a long time, we didn't even build it, and there was about one person that requested it :)
48 | + NSObject* activityId; 49 | +}; 50 | + 51 | +CAppNapInhibitor::CAppNapInhibitor(const char* strReason) : d(new Private) 52 | +{ 53 | + const NSActivityOptions activityOptions =
Since this isn't defined for < MAC_OS_X_VERSION_10_9, does it need a runtime check?
No idea, i can't setup 10.8 build vm to test code properly, so pre 10.9 support removed.
Started doing some testing.
Using master (979f59850c72624137d25f80be4188c3ba6b5fa0) I can make bitcoin-qt and Bitcoin Core (app bundle) enter app nap quite quickly just by starting and then minimising the app window.
You can check App Nap status using Activity Monitor -> Energy.

Using https://github.com/bitcoin/bitcoin/pull/12783/commits/c975861a7cf407cfd6910da691a38c4fe6491530, neither process seems to go into App Nap:

Concept ACK. What's the point of MacOSIdleInhibitor though? In #5804, CIdleInhibitor was introduced as a generic object that could used to be hold any/all platform-specific inhibitors. Here, MacOSIdleInhibitor seems to just be an extra level of indirection.
Well windows and linux can't lower cpu performance per application, on windows user can only change system-wide power plans. This thing pretty much only macos specific, MacOSIdleInhibitor change reverted anyways.
262 | @@ -259,6 +263,21 @@ public Q_SLOTS: 263 | void startThread(); 264 | }; 265 | 266 | +#if defined(Q_OS_MACOS) 267 | +// A RAII wrapper around calls to forbid and re-allow entering into 268 | +// low-priority states, specifically OSX's app-nap. For the scope of
nit: macOS instead of OSX
0 | @@ -0,0 +1,44 @@ 1 | +#include "macos_appnap.h"
This is missing a copyright header
// Copyright (c) 2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
0 | @@ -0,0 +1,19 @@ 1 | +// Copyright (c) 2009-2010 Satoshi Nakamoto 2 | +// Copyright (c) 2009-2018 The Bitcoin Core developers
You can just use:
// Copyright (c) 2018 The Bitcoin Core developers
// Distributed under the MIT software license, see the accompanying
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
as the copyright header here
CIdleInhibitor is still there, maybe an issue with the rebase? BitcoinCore::BitcoinCore can just create a CAppNapInhibitor.
Why is LSAppNapIsDisabled insufficient?
Retested 192b9e7 on macOS 10.13.5. Cannot make Bitcoin Core enter app nap:

Master (f532d52) still enters app nap fairly quickly:

For a future PR it would be nice to disable app nap only during sync, as @laanwj points out.
Currently the choice is between having initial sync grind (master) to a halt or wasting (a little) battery life for people who leave QT on for a long time (this PR). I think this PR is the better alternative, since it's more realistic to exit the application to save energy than it is to keep it in the foreground to keep sync going.
Tested: master goes into app nap after a few minutes (on battery), this branch doesn't: <img width="730" alt="master" src="https://user-images.githubusercontent.com/10217/42341829-47339256-808c-11e8-8cbc-9e3656eb5a0c.png">
<img width="701" alt="nonapp" src="https://user-images.githubusercontent.com/10217/42342599-74f14a2e-808e-11e8-85f8-a86b51092a64.png">
The code looks pretty complicated, which generally suggests that Apple doesn't like this. Do we have some confidence that we're not using API's that can get deprecated on short notice?
If they changed api then code won't even start
if ([processInfo respondsToSelector:@selector(beginActivityWithOptions:reason:)]) {
https://i.imgur.com/g3uKu0g.png
it would be nice to disable app nap only during sync
Agree, but i can't find any signal in src/qt about "sync/initial sync" state changed. Only: BlockTipChanged and NotifyNetworkActiveChanged doesn't seem right.
96 | @@ -97,9 +97,6 @@ 97 | <key>NSHighResolutionCapable</key> 98 | <string>True</string> 99 | 100 | - <key>LSAppNapIsDisabled</key> 101 | - <string>True</string> 102 | -
Even if it doesn't work in latest versions, why not keep it for older ones?
17 | +CAppNapInhibitor::CAppNapInhibitor(const char* strReason) : d(new Private) 18 | +{ 19 | +#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1090 20 | + const NSActivityOptions activityOptions = 21 | + (NSActivityUserInitiatedAllowingIdleSystemSleep | 22 | + NSActivityLatencyCritical) &
Why latency critical?
14 | + NSObject* activityId; 15 | +}; 16 | + 17 | +CAppNapInhibitor::CAppNapInhibitor(const char* strReason) : d(new Private) 18 | +{ 19 | +#if defined(MAC_OS_X_VERSION_MAX_ALLOWED) && MAC_OS_X_VERSION_MAX_ALLOWED >= 1090
These if defs should no longer be required now that we only support 10.10+.
Added to the 0.18 milestone (not sure if we can add this to 0.17.1?). @krab has done a good job of keeping this rebased/updated. I've also done some rudimentary benchmarking, and have seen a ~20% detriment in sync times if Core falls into App Nap, which seems worth addressing.
6 | +#define BITCOIN_QT_MACOS_APPNAP_H 7 | + 8 | +class CAppNapInhibitor 9 | +{ 10 | +public: 11 | + CAppNapInhibitor(const char* strReason);
Should be explicit? :-)
Retested that 663efef doesn't enter app-nap. master (1d14174) still does after a short period of window minimisation. Also added needs gitian build label.
10 | +public: 11 | + explicit CAppNapInhibitor(const char* strReason); 12 | + ~CAppNapInhibitor(); 13 | +private: 14 | + class Private; 15 | + Private *d;
nit Private* d; or std::unique_ptr<Private> d;
0 | @@ -0,0 +1,18 @@ 1 | +// Copyright (c) 2011-2018 The Bitcoin Core developers 2 | +// Distributed under the MIT software license, see the accompanying 3 | +// file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 | + 5 | +#ifndef BITCOIN_QT_MACOS_APPNAP_H 6 | +#define BITCOIN_QT_MACOS_APPNAP_H 7 | + 8 | +class CAppNapInhibitor
nit, final?
<!--a722867cd34abeea1fadc8d60700f111-->
Gitian builds for commit 1d1417430c829a0c21bf5a2fe4a5b2f592a9423f (master):
a5be6400a8e93da53877a84ed34f1291... bitcoin-0.17.99-aarch64-linux-gnu-debug.tar.gz6227401a7521db83b8f3c9fe19702b4d... bitcoin-0.17.99-aarch64-linux-gnu.tar.gzf8f25e2b4f9dd9e3a2279b218b63f943... bitcoin-0.17.99-arm-linux-gnueabihf-debug.tar.gz0af29c3cf1f87d572b9d5967404c3c20... bitcoin-0.17.99-arm-linux-gnueabihf.tar.gzc561b2355f62af3fefa81a626ed2af27... bitcoin-0.17.99-i686-pc-linux-gnu-debug.tar.gzc2fbfff9e38760703cbc921ec2faed87... bitcoin-0.17.99-i686-pc-linux-gnu.tar.gzcc411c05c4f1fe2d34bd2edc324af6a5... bitcoin-0.17.99-osx-unsigned.dmga44085a2856f44e11ae3d165af2bc599... bitcoin-0.17.99-osx64.tar.gz1d8abbd9559609f1634b98e47d35bc8b... bitcoin-0.17.99-riscv64-linux-gnu-debug.tar.gz85caa0cb1e1303669416398ac1c6c320... bitcoin-0.17.99-riscv64-linux-gnu.tar.gz440880e725a985c50ec41d9a8e3c22b8... bitcoin-0.17.99-win32-debug.zip3431c11d2ee5128676c239cd362889ce... bitcoin-0.17.99-win32-setup-unsigned.exe31560814449cc8b8ef8143abded21b1e... bitcoin-0.17.99-win32.zip3c10e52a273d9f643dca91224c1b9622... bitcoin-0.17.99-win64-debug.zip10fbf3fc506e0987351f93a4907edf5c... bitcoin-0.17.99-win64-setup-unsigned.exe16f0e17d7b62a12b440161b8c7c62466... bitcoin-0.17.99-win64.zip4d2485ec7bfdc869d1b9a8449856a9de... bitcoin-0.17.99-x86_64-linux-gnu-debug.tar.gzf080de120316a7c4c8ab8ef1b0b576c0... bitcoin-0.17.99-x86_64-linux-gnu.tar.gz56b7652a723a48938d8ac519b0539af1... bitcoin-0.17.99.tar.gz7793d03b9cdd517d91a727859185789c... bitcoin-linux-0.18-res.yml4e68c43d1b7aa6bea470ecebffa43bed... bitcoin-linux-build.log759fbc280ff667f94f263ffda7cf9d12... bitcoin-osx-0.18-res.yml246a690ad523eae3d16f4ced75ceb377... bitcoin-osx-build.logbeeb4b17114b1d1f25de0244a3f484df... bitcoin-win-0.18-res.yml27147bd9b8da3d92c1c9728f44d14b94... bitcoin-win-build.logGitian builds for commit 99e54e799f7187b97d6486e95b7544148c44a5d2 (master and this pull):
a1137e054232d465979c27e2c6d6a252... bitcoin-0.17.99-aarch64-linux-gnu-debug.tar.gz7a23800f7e64aafa9694882edbc387a1... bitcoin-0.17.99-aarch64-linux-gnu.tar.gz4179da1d9d57b449b5b24eb3b7361d7e... bitcoin-0.17.99-arm-linux-gnueabihf-debug.tar.gz5090d7ea4a71f34c4749f437a8b1685d... bitcoin-0.17.99-arm-linux-gnueabihf.tar.gzee6377193a0011df41b07e916da4dd41... bitcoin-0.17.99-i686-pc-linux-gnu-debug.tar.gz6226e11a47329acfff61c8051e9d8f20... bitcoin-0.17.99-i686-pc-linux-gnu.tar.gz0386d12901263d5fe5024b5862a8fc47... bitcoin-0.17.99-osx-unsigned.dmg70b4cd861970f00e593911c22ab1cc65... bitcoin-0.17.99-osx64.tar.gza0c7b7fe9dd56b44ef76b121138754b4... bitcoin-0.17.99-riscv64-linux-gnu-debug.tar.gzf8cdf9d7039b697965057d5301ef25cd... bitcoin-0.17.99-riscv64-linux-gnu.tar.gz5889bed0f2c94e3c704eea7082849589... bitcoin-0.17.99-win32-debug.zipd59ff6c73c9f8a53915511ca9f951bc6... bitcoin-0.17.99-win32-setup-unsigned.exe244d557107a734f60a1291da7846358c... bitcoin-0.17.99-win32.zip7a2107b03c67965d7792424050bf340c... bitcoin-0.17.99-win64-debug.zip30e3a7d5b11b76a4beb8abc0bdca64ca... bitcoin-0.17.99-win64-setup-unsigned.exe1e1dc0d8f3f2b4ea0e1c06433412378a... bitcoin-0.17.99-win64.zipbed5deea8b0512f9ec20b2ade437cdcd... bitcoin-0.17.99-x86_64-linux-gnu-debug.tar.gz7683c9656d07680a90f291b905ec6709... bitcoin-0.17.99-x86_64-linux-gnu.tar.gz4b2aad2d60e4fe851d80344df91afbe2... bitcoin-0.17.99.tar.gz02d44648ed85e11a06f11a0037a14df4... bitcoin-linux-0.18-res.ymla13b6f7547364e28907177534984d6cd... bitcoin-linux-build.log42ff011f9794aa5e05a5a3f1d05751e1... bitcoin-osx-0.18-res.ymlbf1d7944956321034b2a462c6f76d726... bitcoin-osx-build.loge9e4f4161fa8ee85fd4009efb1342757... bitcoin-win-0.18-res.ymle84637ef2754dae4151ef79cc3f24b64... bitcoin-win-build.log146 | @@ -143,6 +147,10 @@ class BitcoinGUI : public QMainWindow 147 | HelpMessageDialog* helpMessageDialog = nullptr; 148 | ModalOverlay* modalOverlay = nullptr; 149 | 150 | +#ifdef Q_OS_MAC 151 | + CAppNapInhibitor* appNapInhibitor = nullptr;
Should be deleted? Maybe use std::unique. nit, m_app_nap_inhibitor;
Delete what and why? 🤔
Concept ACK.
Rebased against master branch. A bit less code in bitcoingui.cpp. macos_appnap.mm/h in pimpl style. Fixed checks for activityId. activityId = nil; required if we want reuse same pointer.
<!--e57a25ab6845829454e8d69fc972939a-->
The following sections might be updated with supplementary metadata relevant to reviewers and maintainers.
<!--174a7506f384e20aa4161008e828411d-->
Reviewers, this pull request conflicts with the following ones:
If you consider this pull request important, please also help to review the conflicting pull requests. Ideally, start with the one that should be merged first.
tACK 2a14df1 on macOS 10.14 (in July I tested on 10.13)
I previously wrote:
it would be nice to disable app nap only during sync,
This works now. With the app in the background, it enters app nap after a minute or so. If however I rewind the chain a bit e.g. with invalidateblock & reconsiderblock and wait for resync, it won't enter app nap.
It does enter app nap during expensive RPC operations (invalidateblock grinds to a halt), but let's improve that some other time. Conversely, we could also make QT (or a future headless node) conserve energy better when the user is on battery.
I also wrote:
The code looks pretty complicated, which generally suggests that Apple doesn't like this.
The current solution looks much cleaner. E.g. it got rid of the undocumented plist option, and instead uses the documented NSActivityOptions. Some relevant Apple docs:
For future reference, I suggest renaming the PR to "macOS: disable AppNap during sync"
Related upstream ticket QTBUG-43861. If we're lucky, one day Qt might expose an API for this functionality, so we don't have to ship the Objective-C ourselves.
Signed-off-by: Alexey Ivanov <alexey.ivanes@gmail.com>
utACK 1e0f3c4 (rebased)
utACK 1e0f3c44992fb82e6bf36c2ef9277b0759c17c4c
Milestone
0.18.0