21

I have been told by another fellow C programmer to write large applications in several different .c and .h files, and then compile them together. They say it will run faster.

Does a multifile application run faster than a singlefile one? If so, what makes it run faster? Also, what other benefits are there to multi file programming?

For the purpose of this question suppose I am compiling C with GCC, and I am on the Linux platform.

  • 54
    It is just the build that runs faster, since it can recompile incrementally. The runtime performance will be largely unaffected. – Erik Eidt Nov 21 at 16:09
  • 57
    When people start to argue with performance, in 9 of 10 cases they are arguing about the wrong thing ;-) – Doc Brown Nov 21 at 18:06
  • 29
    Computers are cheap. Humans are expensive. Write your code to be easy to work on, not to be what you think will be "fast". – chrylis -on strike- Nov 22 at 0:51
  • 17
    "write large applications in several different files" larger applications often comprise of thousands of different files. – user622505 Nov 22 at 1:45
  • 71
    By "multi-file programming," do you mean writing software using more than one source code file? That's not really called "multi-file programming," for much the same reason that a brush that has multiple bristles is not called a "multi-bristle brush." – Tanner Swett Nov 22 at 3:26

10 Answers 10

69

There are a lot of technical reasons behind using multiple files when writing large complex systems. All of them are meaningless in the face of the best reason to use multiple files:

Readability.

When I write code that resides in one file I'm presenting what you need to understand to follow how this part of the system works. Every detail not in this file is abstracted away, represented with a good name that should ensure you can still understand what is happening here without poking your nose into the other files.

If I've failed to do that I've written crappy code and you should call me out for it. In cases like that multiple files rarely do you any good.

Without that consideration I can write the whole program in one file. The CPU wont care. It will just make humans miserable when they try to read it.

The traditional technical reason is to separate code into independently deployable units that can change without having to redeploy the whole system. There are cases where that's very important such as when your software is burned on many chips and you don't want to throw away all the chips just because one needs to change.

It's also true that being independently deployable allows compiles to go faster since you only have to recompile what changed.

Even in those cases though, I'd still argue that the biggest benefit is creating a boundary that limits what you expect your readers to hold in their head at any one time.

TL;DR If multi file programs annoy you because you have to keep looking in multiple files to understand them you're simply looking at poorly abstracted code with bad names. That shouldn't be what it feels like. Each file should tell one story from one perspective.

  • 9
    @Asadefa running code is in memory not files. How it gets laid out in memory, and cached, matters durning run time. How it's laid out in files matters when they are being loaded into memory. – candied_orange Nov 21 at 21:59
  • 9
    @candied_orange It actually used to matter a long time ago in the DOS days. Back then if you compiled/linked two different .c/.o files together, calls that went from one file to the other were usually compiled as "far" calls and took more clock cycles for the CPU to perform than "near" calls did. Luckily nobody has needed to seriously worry about 16-bit segmentation for a quarter century. ;) – smitelli Nov 22 at 1:40
  • 1
    @candied_orange Separating those files into separate DLLs can make the program run faster, if it doesn't load a lot of unnecessary parts. I'm not aware of a way to compile a single file into both an executable and separate library part (although I bet it's possible) – Mars Nov 22 at 2:57
  • 25
    Also, if looking at multi file programs annoys you, it's more likely because you're using a crappy editor without a "go to definition" feature :) – Mars Nov 22 at 2:58
  • 1
    @Asadefa in many cases a multi-file program will be very slightly slower than a single-file one, and will also take slightly longer to compile. That's not a sufficient reason not to split up the program once it has become "too large" – pjc50 Nov 22 at 12:54
27

The question falls into same category as why buildings are not build from one piece of rock but a bunch of bricks?

Answer:

  • easier to navigate than scroll through one huge file
  • make recompile works only on files related to the change
  • various parts of the program can be programmed by different people
  • code from some files can be put into libraries for future reuse
  • at compilation time an error will indicate in what file the problem is (easier to find)
  • at compilation time compiler needs much less memory (less requirement to hardware)
  • at compilation time easier for compiler to analyse the code (faster)

This is just from top of my head -- there are definitely more benefits in store.

  • And also when compiling, compiler can compile one file per CPU core increasing the time significantly. This can be further improved with distributed compilation. – Tomáš Zato - Reinstate Monica Nov 22 at 11:01
  • 1
    @TomášZato aren't compilers usually IO bound though anyway – jk. Nov 22 at 13:27
  • @jk. The bottleneck may vary. If you're using precompiled headers, there's less IO. I haven't measured it, but I would say compilation of a single file still takes much longer than just reading the file, at least on SSD. – Tomáš Zato - Reinstate Monica Nov 22 at 13:37
  • 2
    @jk. No - depending on what kind of optimisation level you chose, compilers are CPU bound just as often. – Bergi Nov 23 at 13:32
  • When Richard Stallman have wrote first version of GCC and made it public -- soon enough he found that many people who had 640KB in their computers could not use GCC (He was using a computer with 1MB of RAM). He had to return to 'drawing board' and rewrite parts of the compiler so that it was able to compile programs on any computer. Then came to be 'make' which allowed to split the program on pieces and recompile only parts affected by change. It started new evolution of the code. – Polar Bear Nov 29 at 21:19
21

The other answers are fine, but something they're missing is actual technical limitations.

For example, you can't actually save all of the code for my day-job application in one file - it's bigger than the file size limitations of common file systems. That sort of size also wreaks havoc with editors and compilers and linters since the syntax tree for that code is even larger! And then you get to source control and diffing tools trying to work on dozens of gigs of text in one sitting. Since you're working in C, you also need to worry about your actual binary size. Most OSes have an executable size limit separate from the file system size limit.

This is an outlier of course. Multiple files is primarily to make programmers' lives easier, but I hope this gives you a better feel for what "large applications" can entail.

  • 6
    "it's bigger than the file size limitations of common file systems" I assume you mean only fat32. Most filesystems can hold files multiple TB large – Qwertie Nov 22 at 5:28
  • 10
    @Qwertie I don't know where Telastyn works but Google repo (85 TiB based on googling it) exceeds ext3 and ext4 max file size (2 TiB and 16 TiB respectively). – Maciej Piechotka Nov 22 at 9:15
  • 2
    And here I thought dealing with ~100K lines of code in a single file was a major PITA :-( – jamesqf Nov 23 at 3:08
  • 5
    Editor and compiler constraints are probably going the kick in way before file system limits, so that might be a better lead – Morgen Nov 23 at 3:52
11

I have been told to write large applications in several different files. They say it will run faster. What makes it run faster?

Also does a multifile application ACTUALLY run faster than a singlefile one

In C, there is no reason to assume that a multi-source-file application will run faster, and several reasons why it might be slightly slower. Use of multiple files is for the convenience of the developers.

There are even some build systems which let you write multiple files which are combined into a single huge file before being passed to the compiler. This may be called "unity" or "amalgamation" builds.

The main reason is inlining: replacing a call to a function with a copy of the function. C will not usually inline functions from different source files unless the linker is configured to do so. This feature is called "link time optimisation" in GCC.

Other commentators have mentioned the idea of not loading unused bits of the program. However, the function grouping provided by the source files may not be preserved in the executable; unless you're using an "overlay" system (mostly obsolete), or you have separated some features into "plugins.”

On Linux and other systems with virtual memory, the operating system can unload unused parts of the program on its own.

There are also some minor benefits possible from things like string constant deduplication - again, you can have the linker handle this, but it may not be on by default.

Build speed issues are worth considering. If you split a program into N files, where N might be in the 100-10,000 range, then compiling one file is usually much quicker than compiling all N files. However in some cases gathering all N files into one huge file is faster than compiling them all separately - provided it doesn't crash the compiler. This tends to be more important in C++ where compile times can be much longer.

In practice, developers split source files because it makes them easier to work with. Opinions vary but 1,000 lines is a good guideline number to start considering splitting a file.

  • The only answer to actually answer the question. – pipe Nov 22 at 18:38
2

Advantages of using multiple files for a program are numerous.For instance:

  • if you write code for a class in a separate file, you can use that class in multiple programs. It increases reusability of the code.
  • Furthermore, if you want to change anything in a class, you will only have to change it in that particularly file and the change will be automatically reflected in all the projects referring to this file.
  • Furthermore, it is advisable to write large complex programs in multiple smaller files.
  • And last but not the least, in large organizations, several programmers are working on a project. In such scenarios, each programmer is responsible for designing designated modules; therefore separate files for each programmer, are convenient to code and then subsequently integrate.

You can find more arguments in this article.

  • 1
    This is the oldest answer and seems very relevant. I have added some line separators to facilitate reading, and replaced "document" with "file" for the consistency of the terminology. It would help if you could develop the 3rd bullet. You could also add that in many languages, separate files can be compiled separately, so that only the changed files are recompiled. – Christophe Nov 21 at 22:37
  • 2
    The first 2 are not necessarily true. If you have multiple classes defined in your single file program, you can still import it later in another project. #2 is probably not advisable--you don't want someone to break an unrelated project because they "updated" a class in another project! – Mars Nov 22 at 4:09
  • 1
    The question is asking why #3 is true... – Mars Nov 22 at 4:10
2

Another significant reason to use multiple files that somehow no one has mentioned:

When you work on a software development project with a team, it is very common to use a version control system such as Git. One major hurdle faced by any VCS is merging the work of multiple authors. If you and another developer work on the same file at the same time, your work eventually has to be merged together. In some cases, you may both edit the same part of the same file, which can lead to merge conflicts: situations where the VCS can't automatically determine how to merge the changes, and a human has to do it manually.

When all of your code is in one file, there's an increased risk of merge conflicts. Anyone who is working on the code is working on the same file. This increases the likelihood of editing the same code at the same time or otherwise stepping on each others' toes. Even someone who is working on a different part of the file might inadvertently do something that interferes with your work. For example, they auto-format the entire file, rename a function you're editing, reorganize the code and move functions around, etc.

Breaking the code into logical systems split across multiple files reduces the risk of merge conflicts caused by multiple people working on the same file at the same time. It also makes it easier to resolve merge conflicts, because less code in each file means smaller conflicts that are easier to resolve.

Here's a worst-case scenario which I've unfortunately encountered before: you have a 10,000 line file, which Tom and Sally are working on. They each spend several hours making extensive edits to different parts of the code. At some point, Tom notices an indentation mistake and habitually presses the "auto-format" hotkey, which changes the indentation, line breaks, etc for the entire file. Later, when they both go to commit their code, a merge conflict occurs because Tom's auto-format changed nearly every line of code in the entire file and the VCS can't figure out how to merge the changes. Either Tom or Sally has to now spend hours of time manually merging 10,000 lines of code together. If the code had been split into multiple files, they might not have had a conflict at all, and even if they did it would not have affected the entire codebase.

  • What is git please? – Asadefa Nov 22 at 21:15
  • @Asadefa Git is a version control system for tracking changes to your code. It maintains a history of all edits that any person has made to the code, and additionally has features to automatically merge changes together when possible. It is an industry standard for managing code in software projects, and something you'll probably need to learn if you want to be a professional programmer. See git-scm.com – user45623 Nov 22 at 21:18
  • That is a reason to use a commit-hook forcing autoformatting with the one true style. Sally or Tom could reconcile it by adding manual runs of the autoformatter without too much extra-work anyway. Still not nice. – Deduplicator Nov 22 at 21:21
  • @Deduplicator Yes, I oversimplified for the sake of example. – user45623 Nov 22 at 21:22
  • 1
    As long as nobody reorders stuff, the conflicts with the one big file are exactly the same as with the many small files. You only get increased risk of merge conflicts when one of the authors reorders some functions in the huge file. However, those conflicts may turn out to be next to impossible to sort out, so it's definitely a good-enough reason to use many files. – cmaster Nov 22 at 23:03
0

In general it depends on the context. In addition to the other answers in javascript, python and other languages I am probably not aware of a file imported is loaded only once. Let us say f.e. we need to import a file with 150000 words , which needs approximately 1 sec to be loaded to a variable(or data structure). And then we want to use this file to find if a word is in these 150000 entries. We also need to rerun this whole process 1000 times which means about 1000 seconds needed. However, given we import the 150000 entries file as a variable from another file the whole 1000 steps process lasts about 1 second.

However, please bear in mind that the rest of the answers provide a much more significant reasoning to your question.

0

Even when we have complex code navigation tools like Jump-to-Definition, organizing your project in a tree of files and folders makes it easier to onboard new developers. It makes it easier to find which file you need to start working on a feature.

As for the "faster" concern, most modern compilers support LTO, so even if you use separate compilation units (speeding compilation during debug), the resulting executable will run at the same speed when LTO is turned on.

0

A lot of it just comes down to:

  • You want to be able to easily navigate to different logical parts of your program, and view those parts side-by-side
  • it's easier to create an IDE/programming environment that deals with those separate parts as separate files than it is to create an IDE that keeps all the code for a program in one big file, and has to show parts of that file side by side, etc.

In many cases there would be absolutely no problem in having all your code in one real file on disk if your IDE was easily able to help you navigate around that file, and show different parts of the file side-by-side.

-1

While the program will run at the same speed whether it's one file or one thousand the editor is quite another matter.

Intelligent editors bog down when the files get large. I find it noticeable on any form with a lot of UI elements in it.

  • 1
    This is wrong for C. Once Libraries can be formed, the memory load of large files can be reduced as library code need only be loaded once the library is in use. A smaller memory footprint in can make execution faster on systems with limited resources. OP will need to expand on the target system and the full development process that will be used to let us know if this is the case. – TafT Nov 22 at 9:49
  • @TafT Libraries are a different issue and are pretty much language independent. Besides, nothing says the library even needs to be in the same language as the main program. – Loren Pechtel Nov 23 at 5:12
  • We need to know the toolchain before we can say that libraries could be in another programing language or pre-compiled. The OP mentioend C which includes lots of odd low level behaviour in lots of toolchanins that will/should not apply to general answers about high level languages on general purpose platforms. I have worked on systems where function calls between files were slower (and hard to code) compared to calls within a file and it was all "C" of a kind. – TafT Nov 25 at 12:10

Not the answer you're looking for? Browse other questions tagged or ask your own question.