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

Cleanup code by using forward declarations and other methods... #2767

Merged
merged 1 commit into from
Nov 10, 2013

Conversation

brandondahler
Copy link
Contributor

... of avoiding unnecessary header includes. Additionally alphabetizes and groups includes and forward declarations.

Note: there are a large amount of changes that have been rebased onto the most recent master. I did my best to ensure that no code was functionally changed; however, a code review of all my changes would be advised.

Theory

By using forward declarations, compilation speed can be increased in both incremental and full builds.

Forward declarations suffice over having the full declaration in cases where the type that is being forward declared is only used as a reference or being pointed to, and the usage is not an lvalue.

By making these modifications, the total number of header files needed to compile any .cpp file is reduced. Fewer header files being included reduces the total amount of code that needs to be compiled for each .cpp file.

Quantitative Results

How much time does this actually account for?

For bitcoind:
Bitcoind Results

This spreadsheet shows detailed results for each of the different builds (note that there are multiple sheets in the spreadsheet), along with the interesting stats and graph for each.

This data was generated automatically via the scripts here.

Method

  • Go through each file, group each #include by type (see Order) and sort alphabetically
  • Using doxygen with the graphviz dots extension
    • Go through each header, comment each #include individually and all headers that indirectly include the commented one
    • See if it can build with the #include commented, analyze errors to understand if they can actually be solved with forward declares
    • Remove, keep, or add a direct header to the required type, as needed.

Order

Most Generic

// License text as first
// lines

#if defined(HAVE_CONFIG_H)
#include "bitcoin-config.h"
#endif

#include "matching_file.h"

#include "local_file1.h"
#include "local_file2.h"

#include "file_in_other_dir1.h"
#include "file_in_other_dir2.h"

#include <system1.h>
#include <system2.h>

#ifdef SOMETHING1
#include <system3.h>
#endif

#include "json/a_file.h"
#include <library1.h>
#include <library2.h>

#ifdef SOMETHING2
#include <library3.h>
#endif

class ForwardDeclare1;
class ForwardDeclare2;

namespace SomeNamespace {
    class ForwardDeclare3;
}

...

Example1 - No matching file, no file_in_other_dir, no ifdefs

// License text as first
// lines

#include "local_file1.h"
#include "local_file2.h"

#include <system1.h>
#include <system2.h>

#include "json/a_file.h"
#include <library1.h>
#include <library2.h>

class ForwardDeclare1;
class ForwardDeclare2;

...

@gmaxwell
Copy link
Contributor

And how do you prevent very bad thing from happening when one of the many duplicated definitions gets desynchronized?

@brandondahler
Copy link
Contributor Author

Rebasing conflicts on the actual code changes made (one actual, moving some definitions from a header to the code file). Due diligence was taken on my part to ensure that the conflicts were resolved correctly, I would still recommend someone bite the bullet and look at all the changes that are not adding/removing/reordering header files.

Rebasing additionally conflicted on include files being added/removed usually because most of the includes were re-ordered, these were easy to resolve.

@laanwj
Copy link
Member

laanwj commented Jun 14, 2013

@gmaxwell From what I understand this does not duplicate anything. It does pre-declare classes, but that only consists of the name and nothing more.

At first glance this seems like a lot of changes, but it's almost entirely restricted to the #include portion of files. The only substantial code move is moving WalletDB.h functions to its implementation file.

There's problems with compiling the tests after this, though (see pulltester output).

test/script_tests.cpp: In function 'CScript ParseScript(std::string)':
test/script_tests.cpp:47: error: 'replace_first' was not declared in this scope



#include <cstdio>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this needed for?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "printf"s on lines 406, 422, and 428.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

printf is #define'd in util.h to be OutputDebugStringF.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, printf is our own macro.

@sipa
Copy link
Member

sipa commented Jun 14, 2013

I'm generally in favor of cleanups like this, and it indeed seems pure code movement + include changes.

However:

  • Some changes seem not up-to-date with recent refactors (see inline comments)
  • I'm not sure I like the increased use of forward declarations. They don't remove actual code dependencies, but they hide them. Of course we're already using them, and the compilation performance improvements it gives may be worth it. Other devs opinions?
  • Regarding uint64 and int64: I'd prefer including stdint.h and using int64_t and uint64_t instead, over redeclaring them all over the place.

@CodeShark Mind taking a look at this? Does it interfere with the dependencies cleanup?

@laanwj
Copy link
Member

laanwj commented Jun 14, 2013

Getting rid of code dependencies is even better, but in the general case if it is possible do forward declarations instead of an #include in a header I'm in favor of that. It generates a flatter include hierarchy, let's not give the C++ compiler more work than need be.

Re: uint64_t/int32_t I agree. If available, they should be used, as they take the burden of determining data type sizes from us, at least on most platforms.

@brandondahler
Copy link
Contributor Author

Addressed the specific problems references inline.

Hopefully should pass build, don't know why it built on my machine to be honest.

@brandondahler
Copy link
Contributor Author

Delt with cstdio problems. Also normalized all [u]int64 types to [u]int64_t values from stdint.h, alongside replacing PRI64[xdu] with PRI[xdu]64 from inttypes.h .

@luke-jr
Copy link
Member

luke-jr commented Jun 17, 2013

@brandondahler Simply replacing [u]int64 types with stdint will probably break something - we tried this like a year ago and had to revert it :(

@brandondahler
Copy link
Contributor Author

@luke-jr It was a non-negligable change, but it did compile and pass tests on my linux machine. Was the issue with compiling on other architectures?

@luke-jr
Copy link
Member

luke-jr commented Jul 16, 2013

@brandondahler Reviewing logs, it looks like it didn't build on 64-bit Fedora. I don't believe we ever fully diagnosed the reason, but:

[Wednesday, December 21, 2011] [3:15:25 PM] <jgarzik>   serialize.h: In function ‘unsigned int GetSerializeSize(int64
_t, int, int)’:
[Wednesday, December 21, 2011] [3:15:26 PM] <jgarzik>   serialize.h:139:21: error: redefinition of ‘unsigned int GetS
erializeSize(int64_t, int, int)’
[Wednesday, December 21, 2011] [3:15:26 PM] <jgarzik>   serialize.h:137:21: error: ‘unsigned int GetSerializeSize(lon
g int, int, int)’ previously defined here
[Wednesday, December 21, 2011] [3:15:38 PM] <jgarzik>   tree is full of broken
[Wednesday, December 21, 2011] [3:16:18 PM] Join        larsivi has joined this channel (~quassel@188.113.74.106).
[Wednesday, December 21, 2011] [3:16:25 PM] <jgarzik>   luke-jr: ^^
[Wednesday, December 21, 2011] [3:16:29 PM] <luke-jr>   jgarzik: works fine here…
[Wednesday, December 21, 2011] [3:16:56 PM] <jgarzik>   luke-jr: totally broke Fedora build (g++ 4.6.1)
[Wednesday, December 21, 2011] [3:17:05 PM] <jgarzik>   luke-jr: on 64-bit
[Wednesday, December 21, 2011] [3:17:32 PM] <jgarzik>   luke-jr: breakage is obvious.  64-bit platforms define int64_t==long int
[Wednesday, December 21, 2011] [3:17:49 PM] <luke-jr>   jgarzik: 4.5.3 here
[Wednesday, December 21, 2011] [3:18:31 PM] <jgarzik>   'int foo(int64_t)' is the same as 'int foo(long)'

#include <mswsock.h>
#include <winsock2.h>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

winsock2.h must be included before mswsock.h or build fails.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also get a MinGW compiler warning that winsock2.h should be included before windows.h from this file in current master.

d:\mingw\mingw32\i686-w64-mingw32\include\winsock2.h:15: Warnung:#warning Please include winsock2.h before windows.h [-Wcpp]
 #warning Please include winsock2.h before windows.h
  ^

@sipa
Copy link
Member

sipa commented Jul 29, 2013

I think most other refactors that were in the pipeline are merged now. Care to rebase this?

@brandondahler
Copy link
Contributor Author

Rebased branch onto master.

#include <QMenu>
#include <QSortFilterProxyModel>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this needed, as we include it in addressbookpage.h?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is not included in addressbookpage.h--there is only forward declare (see below).

QT_BEGIN_NAMESPACE
...
class QSortFilterProxyModel;
...
QT_END_NAMESPACE

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My fault, I didn't look correctly, sorry :).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No problems at all, thanks for reviewing the changes :)

@jgarzik
Copy link
Contributor

jgarzik commented Aug 25, 2013

It would be nice to collapse the commits, and merge in the [u]int64_t change first.

Looks pretty good overall, though I do worry there is a subtle compiler detail being missed in the int64/int64_t type changes.

Very much like seeing use of stdint.h and int64_t, rather than using our own type.

@Diapolo
Copy link

Diapolo commented Aug 29, 2013

I also like the intention of this pull, can you rebase and perhaps follow @jgarzik so we can differentiate the type-changes and the cleanup changes :).

Edit: Also a merge-speedup is possible, if you create a Qt-only and a core-only pull, as @laanwj is able to merge Qt-pulls much faster than core changes.

Edit 2: @laanwj Any objection, to start using quint64 or qint64 in Qt code? Perhaps that could also be a scope of a separate Qt pull.

@@ -2,29 +2,36 @@
* W.J. van der Laan 2011-2012
*/


Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: remove this new-line.

@Diapolo
Copy link

Diapolo commented Sep 7, 2013

I really hope to see PullTester happy and some final ACKs for your great work here.

@brandondahler
Copy link
Contributor Author

Rebased and squashed small commits (made sure that the resuting rebased version is equivalent to the previously merged version).

I plan on going over the source again to re-alphabetize etc.

@gavinandresen
Copy link
Contributor

Pull-tester is fixed, so if it is complaining there is something wrong with your pull. See the test.log to debug.


class CBlock;
class CBlockHeader;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to forward declare this; CBlockHeader is defined in core, which is included.

@brandondahler
Copy link
Contributor Author

Address @sipa comments. I think most of the main.h problems were caused by rebasing/merging so many times.

@@ -17,6 +16,15 @@
#include "txdb.h"
#include "txmempool.h"
#include "ui_interface.h"
#include "util.h"
#include "wallet.h"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since #3115, this shouldn't be needed anymore.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this is my fault: it was supposed to remove setpwalletRegistered and its critical section, but apparently didn't. In any case, they're obsolete now, and that can remove the dependency on CWallet.

@sipa
Copy link
Member

sipa commented Nov 10, 2013

ACK, apart from my nits above.

sipa added a commit to sipa/bitcoin that referenced this pull request Nov 10, 2013
625188f Cleanup code using forward declarations. (Brandon Dahler)
@sipa
Copy link
Member

sipa commented Nov 10, 2013

Some suggested changes, which seem to work: sipa/bitcoin@0762f57

Use misc methods of avoiding unnecesary header includes.
Replace int typedefs with int##_t from stdint.h.
Replace PRI64[xdu] with PRI[xdu]64 from inttypes.h.
Normalize QT_VERSION ifs where possible.
Resolve some indirect dependencies as direct ones.
Remove extern declarations from .cpp files.
@brandondahler
Copy link
Contributor Author

Merged sipa/bitcoin@header-cleanup (sipa/bitcoin@0762f57)

@BitcoinPullTester
Copy link

Automatic sanity-testing: PASSED, see http://jenkins.bluematt.me/pull-tester/51ed9ec971614aebdbfbd9527aba365dd0afd437 for binaries and test log.
This test script verifies pulls every time they are updated. It, however, dies sometimes and fails to test properly. If you are waiting on a test, please check timestamps to verify that the test.log is moving at http://jenkins.bluematt.me/pull-tester/current/
Contact BlueMatt on freenode if something looks broken.

@sipa
Copy link
Member

sipa commented Nov 10, 2013

ACK. Thanks a lot for the effort of writing this, and maintaining it.

sipa added a commit that referenced this pull request Nov 10, 2013
51ed9ec Cleanup code using forward declarations. (Brandon Dahler)
@sipa sipa merged commit 51ed9ec into bitcoin:master Nov 10, 2013
@brandondahler brandondahler deleted the header-cleanup branch November 11, 2013 01:22
Bushstar pushed a commit to Bushstar/omnicore that referenced this pull request Apr 5, 2019
Rewrite `if (var =  func())` in a less confusing way
@bitcoin bitcoin locked as resolved and limited conversation to collaborators Sep 8, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

9 participants