3

I'm starting new project and need to decide on how to handle configuration. I recently run into suckless project. While it has its own issues, I really liked its approach to configuration - just a header file with static variables.

What are pros and cons of using compile-time options vs run-time options (== config file)? Would it be acceptable for product aimed for more tech-savvy users to use compile-time config? Does it still have benefits on modern systems?

I'm focusing modern desktop/laptops, only supported architecture likely will be amd64. Project is GUI application focused on accesing various informations.

8
  • 3
    It is going to depend solely on your user's needs. By requiring compilation (even if there is an automated system for that), you exclude your product from some operating environments and some non-tech-savvy users. Whether that matters depend on whether you think that (losing that user segment) matters. Your question didn't provide much information to support either way, so I am posting as a comment. TL; DR: It depends.
    – rwong
    Commented Apr 29, 2015 at 14:33
  • I suppose that could be problem on windows.. Does compile-time config have any performance advantages? Or it's mostly negligible on modern systems?
    – graywolf
    Commented Apr 29, 2015 at 14:40
  • Can you be a little more specific as to what the system is about / what are some of its main goals/requirements/constraints? Commented Apr 29, 2015 at 14:42
  • I added "EDIT" section to the question. In practice, there won't me much limitations, I'm just looking into this to see what's better/more efficient
    – graywolf
    Commented Apr 29, 2015 at 14:51
  • 2
    The only performance worth measuring in most cases is "people performance" - what's most convenient for your users. An extra few milliseconds reading a config file every time the app is run will be overwhelmed by the time required to recompile once Commented Apr 29, 2015 at 15:34

4 Answers 4

4

This answer is specific to C++ (as indicated by the tag on this question).


Most other compiled languages (outside C and C++) do not have such consideration, because in those languages there is no benefit in moving configurations to compile-time. Outside of C and C++, conditional compilation is greatly discouraged or simply unsupported. Also, C and C++ compilers apply aggressive dead-code elimination and other compile-time optimizations so that code that are provably excluded by compile-time configuration will not exist in the binary.

This question may also become a non-issue when just-in-time compilation (JIT) is considered. It is widely speculated that JIT will be available to C++ some day.


From a miles-high perspective, there are three main considerations for compile-time vs runtime (or program-launchtime) configuration.


Necessity.

Necessity refers to software, user or legal requirements which are rigid and cannot be worked around, and therefore impacts whether a configuration is required to be compile-time or runtime.

For example, if there is a requirement that a configuration can be changed without restarting an already running application, then obviously that configuration has to be run-time modifiable.

If the project has an optional dependency on a third-party component, and if that component has licensing terms that make it inapplicable to some subset of customers, then you will have to provide a build configuration for including or excluding the linking and use of that third-party component from your project. Obviously that configuration has to be compile-time.


Burden / Overhead.

This includes the time cost and inconvenience cost of everything - user's time recompiling, code execution overhead (conditional check, reading configurations, etc), and many other things.

As Dan Pichelman points out in the comment, the time spent on recompiling will typically greatly surpass the time spent on anything else.

The only exception to this observation is, if for some other reasons, the code is already being recompiled frequently, say, daily or even hourly. This can happen when a continuous-integration (automated builds and deployments) system is already in place. In such environments, putting configuration into compile-time can be effective because there is no additional cost and only a minor latency from change to effect.


Bloat.

Bloat refers to the increase in size, number of build artifacts, or other quantities when one needs to support multiple configurations (whether compile-time or runtime), when compared to the same quantity when only one such configuration is needed.

For example, if one has the choice of using Algorithm A versus Algorithm B for a certain task:

  • Option 1: compile both algorithms into the binary, thus allowing the choice to be made at runtime. The binary size is the sum of the binary size of both algorithms, minus the size of shared binary parts.
  • Option 2: only compile one of the two algorithms into the binary. The choice is fixed at compile-time; the application/user won't be able to choose at runtime.
  • Option 3: make one build (binary) containing only Algorithm A, and another build (binary) containing only Algorithm B. Provide both to the user. A change of choice will require restarting the application using the binary of choice.
  • Option 4: refactor both algorithms into a generalized algorithm model, and maximize the reuse of logic, in the hope of reducing binary size.

It is obvious that Option 3 will have to largest bloat, because a lot of binary logic that is common to both will have to be duplicated. The bloat resulting from Option 1 appears to be reasonable in comparison to Option 3.

Option 2 lacks the runtime choice, so it is subject to the first criteria - necessity - depending on the software's and user's requirements.

Option 4 takes extra programming effort, but will have the least impact to burden and bloat compared to all other options.

1
  • 1
    "Outside of C/C++": there are definitely other compiled languages that support conditional compiling (Ada, Common Lisp, Rust).
    – coredump
    Commented Apr 29, 2015 at 18:05
1

Your decision whether to have code-based configuration or file-based configuration will depend entirely on whether or not you need the flexibility of configuring at runtime vs. compile time. Performance is almost certainly a non-issue, since you can cache the values once they are read from the configuration file.

1

The title hints that the topic is somewhat opinion-based.

However, let's ignore this issue and address the question. I think the pros and cons are fairly obvious, since both methods are just trade offs.

For example, let's say you've implemented a runtime configuration-system. Cons:

  • What do you do if some values are missing in the config / the config itself is missing? You need to define some "compile time values" anyway.

  • You'll have to load and parse the file. These days this isn't a problem any more, since we work with gigahertz processors and gigabytes of RAM. But imagine if you had a device that offers less.

Pros:

  • Flexibility. The user can adapt the values matching his needs. To be honest, in my opinion this outweighs any cons for this you can imagine.

Well, let's take a look at compile time configuration option: Pros:

  • The program starts up faster and so on. But this isn't a problem these days since we have, as already mentioned, really strong computers compared to what we had a couple of years ago.

Cons:

  • Hard Coded values. The values are hard coded and you can hardly change them for debugging, for your personal joy or what so ever.

As mentioned at the beginning, this mostly opinion based, since the pros and cons do not have much weight. If you have already implemented a parser that you can feed with config files, then I would stick to it.

EDIT: Something I forgot to say: Do only expose those configuration values, which you want to be modified. There is no point in giving the user the ability to enable a feature which isn't support on his system.

0

You want all configuration in one place. Making changes in twenty places snd wanting to maintain this is madness.

The “one place” can be a header file, it can be one C++ source file containing a configuration class. Or it can be a JSON file and you have a C++ configuration class reading the JSON file. It’s up to you.

At this point, the number of changes to create a new configuration or change an existing configuration is the same.

Here’s the difference: If you have lots of different configurations, say one per customer, some have problems accepting a recompiled file. That makes a JSON file much easier, and it doesn’t require recompilation.

If you have a configuration call that you modify, the amount of recompilation is not too bad, but you still need to send new compiled versions to everyone.

If your configuration is inside a header file, you can have a huge amount of recompilation on top of everything else.

Configuration in a file gives the least amount of effort distributing new versions.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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