Skip to content

Instantly share code, notes, and snippets.

@brson
Last active November 9, 2016 17:01
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save brson/1beda7c9eef6c6d1d33e3ba587da21af to your computer and use it in GitHub Desktop.
Save brson/1beda7c9eef6c6d1d33e3ba587da21af to your computer and use it in GitHub Desktop.

Themes

  • New features: ?, type macros, attributes on statements.
  • Compiler performance
  • Diagnostics
  • Cargo rustdoc bugfixes
  • New libs features

Important notes

  • release notes: rust-lang/rust#37600
  • removing old trans removes drop flags. do we have numbers? this means that Drop can be implemented on FFI types.
  • msvc abi is default
  • cargo security updates
  • errata: cargo version naming bug
  • errata: armv7 hard float bug

New features: ?, type macros, statement attributes

The big new feature in this release is ?. It's a small feature that makes Rust code a lot more pleasant to write and to read. As described in RFC 243, ? fills the same role as try! but with a smaller, less-intrusive syntax.

TODO: blah, blah, blah

Let's look at the following real-world example (see a diff of them side by side).

fn aggressive_rm_rf(&self, path: &Path) -> io::Result<()> {
    for e in try!(path.read_dir()) {
        let entry = try!(e);
        let path = entry.path();
        if try!(entry.file_type()).is_dir() {
            try!(self.aggressive_rm_rf(&path));
        } else {
            // Remove readonly files as well on windows (by default we can't)
            try!(fs::remove_file(&path).or_else(|e| {
                if cfg!(windows) && e.kind() == io::ErrorKind::PermissionDenied {
                    let mut meta = try!(entry.metadata()).permissions();
                    meta.set_readonly(false);
                    try!(fs::set_permissions(&path, meta));
                    fs::remove_file(&path)
                } else {
                    Err(e)
                }
            }))
        }
    }
    fs::remove_dir(path)
}
fn aggressive_rm_rf(&self, path: &Path) -> io::Result<()> {
    for e in path.read_dir()? {
        let entry = e?;
        let path = entry.path();
        if entry.file_type()?.is_dir() {
            self.aggressive_rm_rf(&path)?;
        } else {
            // Remove readonly files as well on windows (by default we can't)
            fs::remove_file(&path).or_else(|e| {
                if cfg!(windows) && e.kind() == io::ErrorKind::PermissionDenied {
                    let mut meta = entry.metadata()?.permissions();
                    meta.set_readonly(false);
                    fs::set_permissions(&path, meta)?;
                    fs::remove_file(&path)
                } else {
                    Err(e)
                }
            })?;
        }
    }
    fs::remove_dir(path)
}                                                                                                                                                                                                                                                                                                                                            }

Focus on compiler performance

There has bee a lot of focus on compiler performance lately. There's good news in this release, and more to come.

Mark Simulacrum and Nick Cameron have been refining perf.rust-lang.org, our tool for tracking compiler performance. It runs the rustc-benchmarks suite regularly, on dedicated hardware, and tracks the results over time. This tool records the results for each pass in the compiler and is used by the compiler developers to narrow commit ranges of performance regressions. It's an important part of our toolbox!

We can use this tool to look at a graph of performance over the 1.13 development cycle. This cycle covered the dates from August 16 through September 29 (the graph begins from Augest 25th though and is filtered in a few ways to eliminate bogus, incomplete, or confusing results). There appear to be some big reductions, which are quantified on the corresponding statistics page.

The big improvement demonstrated in the graphs, on September 1, is from an optimization from Niko to cache normalized projections during translation. That is to say, during generation of LLVM IR, the compiler no longer recomputes concrete instances of associated types each time they are needed, but instead reuses previously-computed values. This optimization doesn't affect all code bases, but in code bases that exhibit certain patterns, like futures-rs, where debug mode build-time improved by up to 40%, you'll notice the difference.

Another such optimization, that doesn't affect every crate but does affect some in a big way, came from Michael Woerister, and improves compile time for crates that export many inline functions. When a function is marked #[inline], in addition to translating that function for use by the current crate, the compiler stores its MIR representation in the crate rlib, and translates the function to LLVM IR in every crate that calls it. The optimization Michael did is obvious in retrospect: there are some cases where inline functions are only for the consumption of other crates, and never called from the crate in which they are defined; so the compiler doesn't need to translate code for inline functions in the crate they are defined unless they are called directly. This saves the cost of rustc converting the function to LLVM IR and LLVM optimizing and converting the function to machine code (TODO is this right about converting to machine code - were these functions public before?).

In some cases this results in dramatic improvements. Build times for the ndarray crate improved by 50%, and in the (unreleased) winapi 0.3 crate, which is nothing but inline functions, rustc now generates the following LLVM IR:

; ModuleID = 'winapi.cgu-0.rs'
source_filename = "winapi.cgu-0.rs"
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"

!llvm.dbg.cu = !{!0}
!llvm.module.flags = !{!3, !4}

!0 = distinct !DICompileUnit(language: DW_LANG_Rust, file: !1, producer: "rustc version 1.13.0-dev (cf976fe2c 2016-09-15)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
!1 = !DIFile(filename: ".\5Csrc\5Clib.rs", directory: "C:\5Cmsys64\5Chome\5CPeter\5Cwinapi-rs")
!2 = !{}
!3 = !{i32 2, !"CodeView", i32 1}
!4 = !{i32 2, !"Debug Info Version", i32 3}

You're eyes don't deceive you. This crate contains no code at all, and it's not going to pay for what it doesn't use.

But wait, there's more still! Nick Nethercote has turned his focus to compiler performance as well, focusing on profiling and micro-optimizations. This release contains several fruits of his work, and there are more in the pipeline for 1.14. And work toward incremental compilation continues.

Other changes and errata

As described on the download page, Rust for windows can run on and target either the GNU ABI or the MSVC ABI. The MSVC port is sufficiently mature that we recommend it for general use. Working with the MSVC port of Rust continues to require an installation of the MSVC build tools. If you install Rust via [rustup], it will automatically use the MSVC toolchain if it is available.

This release contains important security updates to Cargo, which depends on curl and OpenSSL, which both published security updates recently. For more information see the respective announcements for curl 7.51.0 and OpenSSL 1.0.2j.

This release contains two bugs discovered late:

  • Cargo reports its version number as cargo 0.13.0-nightly (eca9e15 2016-11-01). It is actually version 0.14.
  • The armv7-unknown-linux-gnueabihf target contains a serious bug in code generation. The full scope of the problem is unclear, but may affect all ARM targets using hardware floating point.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment