nim-lang / RFCs

A repository for your Nim proposals.
135 stars 26 forks source link

Launchtime conditions #501

Closed archnim closed 1 year ago

archnim commented 1 year ago

Abstract

My idea is that, we should think about a way to provide conditions that are checked once for all at the beginning of a program execution, to avoid useless overhead due to repetitive checks. It's just like compile-time conditions (when), but that changes the program after it has already been compiled.

Motivation

Some programs take many flags to adjust their working. To take the flags in account, they have to perform many checks during their execution. But since all the flags are passed at the launch of the program, and don't change until its end, these conditions could be checked only once at the beginning.

Description

For now I have no clear Idea of how to implement such a mechanism. But I would like to know if you find the concept useful, if you know a better way that is already possible, or if you have any idea of how to add this feature to Nim.

Code Examples

# We are creating an API in nim

{.launch.}: # To signify that all what is in this block will be executed before the launchtime checks
  # Let check if the user launched the server with logging activated:
  let logging: bool = checkInProcessArgsOrInConfigFile() 

proc readData() =
  # Reading in the db
  If logging: # if is written differently, it's a launch-time condition
    infoLog("data read !")

proc addData() =
  # Adding data in the db
  If logging: # if is written differently, it's a launch-time condition
    infoLog("data added !")

In this example, if the server is not launched with the option --log:off, then during the program execution, the logs are saved without checking if they are enabled, just as if the programmer knew in advance, what settings the user would choose.

Backwards Compatibility

No response

metagn commented 1 year ago

It's just like compile-time conditions (when), but that changes the program after it has already been compiled.

I don't understand this, false when branches should never be fully compiled. Only exceptions are when nimvm and for generic object fields.

archnim commented 1 year ago

I mentioned when only as an example to illustrate the fact that the checks will be executed Before the rest of the code, and then the whole program will adapt to the conditions, in manner that eliminates the need to check again. To make it clearer, I'm going to edit the issue to introduce a code Example.

SolitudeSF commented 1 year ago

Why? All this complexity to remove if overhead?

metagn commented 1 year ago

The key point you have for this, overhead, is entirely dependent on what implementation you would have. Your example could be optimized by branch prediction. For other cases, you could do something like (obviously generated with a macro):

let logging = ...
let readData =
  if logging:
    proc () =
     ...
     log(...)
  else:
    proc () =
     ...

But I wouldn't know if this is nearly the same performance nor if there is a better way to do it.

archnim commented 1 year ago

@SolitudeSF It's because, in some programs the conditions are included in loops or in procs that are called very often. Recently I opened a PR (https://github.com/nim-lang/Nim/pull/21002) that was rejected by @Araq because of if overheads !

archnim commented 1 year ago

@metagn It's a pretty good approach. In fact, it's the first idea that came to my mind. But for huge and complex programs, this can rapidly become cumbersome, because you have to provide different versions of each part of your program. The more you have conditions, the more you more versions you have to create.

An interesting improvement could be an automatic replacement mechanism that generates the different code versions. The downside of this method would be the important augmentation of size of the executables.

Araq commented 1 year ago

Recently I opened a PR (https://github.com/nim-lang/Nim/pull/21002) that was rejected by @Araq because of if overheads !

Sorry about that but it's not all about the "overhead of an if statement". More code and more features and more code paths add complexity to a codebase. And complexity has already slowed down Nim's development to the point of harming its future.

So I have to say "no" to almost any new feature or API addition.

What would help? Moving async to its own Nimble package might.

archnim commented 1 year ago

@Araq, well understood ๐Ÿ‘๐Ÿผ. Whatever is necessary to make Nim progress, and provide a confortable API to the community, we will always be here to contribute.๐Ÿ™‚