Skip to content

Commit

Permalink
Enable optimisations by default
Browse files Browse the repository at this point in the history
While we don't actually have any optimisations set up yet, the compiler
is now set up such that in the future we'd apply a balanced amount of
optimisations, instead of requiring some sort of --release flag. This
makes it less likely for users to produce a slow build by accident, and
forces us to better think about balancing compile times and runtime
performance.

Optimisations can still be controlled using `inko build --opt LEVEL`,
where LEVEL is "none" for no optimisations, "balanced" for a balanced
amount/the default, and "aggressive" for a future mode where we favour
runtime performance over compile times.

This fixes #541.

Changelog: other
  • Loading branch information
yorickpeterse committed May 27, 2023
1 parent 773957a commit 8a56fd2
Show file tree
Hide file tree
Showing 4 changed files with 64 additions and 29 deletions.
60 changes: 40 additions & 20 deletions compiler/src/config.rs
Expand Up @@ -51,7 +51,11 @@ pub(crate) struct BuildDirectories {

impl BuildDirectories {
pub(crate) fn new(config: &Config) -> BuildDirectories {
let build = config.build.join(config.mode.directory_name());
let build = config
.opt
.directory_name()
.map_or(config.build.clone(), |p| config.build.join(p));

let objects = build.join("objects");
let dot = build.join("dot");
let bin = build.clone();
Expand All @@ -71,26 +75,26 @@ impl BuildDirectories {
}

/// A type describing to what degree a program should be optimised.
#[derive(Clone, Copy)]
pub enum Mode {
/// A mode suitable for development and debugging.
///
/// This mode favours fast compile times over runtime performance. For
/// releases/deployments you should use the dedicated release mode.
Debug,

/// A mode suitable for releases.
///
/// In this mode a reasonable number of optimisations is enabled, such that
/// there's a healthy balance between runtime performance and compile times.
Release,
#[derive(Copy, Clone)]
pub enum Opt {
/// No optimisations are applied.
None,

/// A decent number of optimisations is applied, providing a good balance
/// between runtime performance and compile times.
Balanced,

/// An aggressive number of optimisations is applied, favouring runtime
/// performance over compile times.
Aggressive,
}

impl Mode {
pub(crate) fn directory_name(self) -> &'static str {
impl Opt {
pub(crate) fn directory_name(self) -> Option<&'static str> {
match self {
Mode::Debug => "debug",
Mode::Release => "release",
Opt::None => Some("none"),
Opt::Balanced => None,
Opt::Aggressive => Some("aggressive"),
}
}
}
Expand Down Expand Up @@ -139,7 +143,7 @@ pub struct Config {
pub output: Output,

/// The optimisation mode to apply when compiling code.
pub mode: Mode,
pub opt: Opt,

/// The presenter to use for displaying diagnostics.
pub(crate) presenter: Box<dyn Presenter>,
Expand Down Expand Up @@ -171,7 +175,7 @@ impl Config {
implicit_imports: vec![],
output: Output::Derive,
target: Target::native(),
mode: Mode::Debug,
opt: Opt::Balanced,
dot: false,
}
}
Expand Down Expand Up @@ -214,6 +218,22 @@ impl Config {
}
}

pub fn set_opt(&mut self, name: &str) -> Result<(), String> {
self.opt = match name {
"none" => Opt::None,
"balanced" => Opt::Balanced,
"aggressive" => Opt::Aggressive,
_ => {
return Err(format!(
"The optimisation level '{}' isn't supported",
name
))
}
};

Ok(())
}

pub(crate) fn main_source_module(&self) -> PathBuf {
let mut main_file = self.source.join(MAIN_MODULE);

Expand Down
17 changes: 13 additions & 4 deletions docs/source/getting-started/cli.md
Expand Up @@ -31,14 +31,23 @@ using the `inko build` command:
inko build hello.inko
```

By default this produces a debug build, located in `./build/debug/hello`. To
produce a release build instead, run the following:
The resulting executable is located at `./build/hello`. By default the compiler
enables a reasonable number of optimisations, without sacrificing compile times.
You can either disable optimisations entirely, of enable more aggressively
optimisations at the cost of compile times increasing:

```bash
inko build --release hello.inko
inko build --opt none hello.inko # No optimisations
inko build --opt aggressive hello.inko # Aggressive optimisations
```

The resulting executable is now located in `./build/release/hello`.
For `--opt none` the executable is placed in `./build/none/hello`, and
`./build/aggressive/hello` for `--opt aggressive`.

!!! tip
Only use `--opt aggressive` if you have determined the increase in compile
times is worth the increase in runtime performance. Most users will want to
avoid this option entirely.

You can specify an alternative output path using the `-o` option:

Expand Down
13 changes: 10 additions & 3 deletions inko/src/command/build.rs
@@ -1,7 +1,7 @@
use crate::error::Error;
use crate::options::print_usage;
use compiler::compiler::{CompileError, Compiler};
use compiler::config::{Config, Mode, Output};
use compiler::config::{Config, Output};
use getopts::Options;
use std::path::PathBuf;

Expand Down Expand Up @@ -52,6 +52,13 @@ pub(crate) fn run(arguments: &[String]) -> Result<i32, Error> {
"PATH",
);

options.optmulti(
"",
"opt",
"The amount of optimisations to apply",
"none,balanced,aggressive",
);

options.optflag("", "dot", "Output the MIR of every module as DOT files");

let matches = options.parse(arguments)?;
Expand All @@ -71,8 +78,8 @@ pub(crate) fn run(arguments: &[String]) -> Result<i32, Error> {
config.set_target(&val)?;
}

if matches.opt_present("release") {
config.mode = Mode::Release;
if let Some(val) = matches.opt_str("opt") {
config.set_opt(&val)?;
}

if matches.opt_present("dot") {
Expand Down
3 changes: 1 addition & 2 deletions inko/src/command/run.rs
@@ -1,7 +1,7 @@
use crate::error::Error;
use crate::options::print_usage;
use compiler::compiler::{CompileError, Compiler};
use compiler::config::{Config, Mode};
use compiler::config::Config;
use getopts::{Options, ParsingStyle};
use std::env::temp_dir;
use std::fs::{create_dir, remove_dir_all};
Expand Down Expand Up @@ -82,7 +82,6 @@ pub(crate) fn run(arguments: &[String]) -> Result<i32, Error> {
}

config.build = build_dir.clone();
config.mode = Mode::Release;

let mut compiler = Compiler::new(config);
let file = matches.free.get(0).map(PathBuf::from);
Expand Down

0 comments on commit 8a56fd2

Please sign in to comment.