aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVeetaha <[email protected]>2020-06-21 13:58:34 +0100
committerVeetaha <[email protected]>2020-07-07 21:30:11 +0100
commitf92bfb580780cda02f9ba8a935538f984d8a4c0d (patch)
treefbf0e24250cc36eaa122904e78cd7cb50fe1c665
parent980a67f44629ed67a54b603aaf9d015a81d61f7a (diff)
Gzip artifacts
Co-authored-by: bjorn3 <[email protected]> Override miniz_oxide to build it with optimizations Building this crate with optimizations decreases the gzipping part of `cargo xtask dist` from `30-40s` down to `3s`, the overhead for `rustc` to apply optimizations is miserable on this background
-rw-r--r--Cargo.lock22
-rw-r--r--Cargo.toml5
-rw-r--r--editors/code/src/main.ts17
-rw-r--r--editors/code/src/net.ts16
-rw-r--r--xtask/Cargo.toml1
-rw-r--r--xtask/src/dist.rs31
6 files changed, 68 insertions, 24 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 916fc53e0..108403ce6 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -208,6 +208,15 @@ dependencies = [
208] 208]
209 209
210[[package]] 210[[package]]
211name = "crc32fast"
212version = "1.2.0"
213source = "registry+https://github.com/rust-lang/crates.io-index"
214checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1"
215dependencies = [
216 "cfg-if",
217]
218
219[[package]]
211name = "crossbeam-channel" 220name = "crossbeam-channel"
212version = "0.4.2" 221version = "0.4.2"
213source = "registry+https://github.com/rust-lang/crates.io-index" 222source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -341,6 +350,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
341checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" 350checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d"
342 351
343[[package]] 352[[package]]
353name = "flate2"
354version = "1.0.16"
355source = "registry+https://github.com/rust-lang/crates.io-index"
356checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e"
357dependencies = [
358 "cfg-if",
359 "crc32fast",
360 "libc",
361 "miniz_oxide",
362]
363
364[[package]]
344name = "flycheck" 365name = "flycheck"
345version = "0.1.0" 366version = "0.1.0"
346dependencies = [ 367dependencies = [
@@ -1993,6 +2014,7 @@ name = "xtask"
1993version = "0.1.0" 2014version = "0.1.0"
1994dependencies = [ 2015dependencies = [
1995 "anyhow", 2016 "anyhow",
2017 "flate2",
1996 "pico-args", 2018 "pico-args",
1997 "proc-macro2", 2019 "proc-macro2",
1998 "quote", 2020 "quote",
diff --git a/Cargo.toml b/Cargo.toml
index 189f4ea2b..612e6809f 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -29,6 +29,11 @@ opt-level = 0
29[profile.release.package.xtask] 29[profile.release.package.xtask]
30opt-level = 0 30opt-level = 0
31 31
32# Gzipping the artifacts is up to 10 times faster with optimizations (`cargo xtask dist`).
33# `miniz_oxide` is the direct dependency of `flate2` which does all the heavy lifting
34[profile.dev.package.miniz_oxide]
35opt-level = 3
36
32[patch.'crates-io'] 37[patch.'crates-io']
33# rowan = { path = "../rowan" } 38# rowan = { path = "../rowan" }
34 39
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index eda95ae5c..bd99d696a 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -274,13 +274,13 @@ async function getServer(config: Config, state: PersistentState): Promise<string
274 }; 274 };
275 if (config.package.releaseTag === null) return "rust-analyzer"; 275 if (config.package.releaseTag === null) return "rust-analyzer";
276 276
277 let binaryName: string | undefined = undefined; 277 let platform: string | undefined;
278 if (process.arch === "x64" || process.arch === "ia32") { 278 if (process.arch === "x64" || process.arch === "ia32") {
279 if (process.platform === "linux") binaryName = "rust-analyzer-linux"; 279 if (process.platform === "linux") platform = "linux";
280 if (process.platform === "darwin") binaryName = "rust-analyzer-mac"; 280 if (process.platform === "darwin") platform = "mac";
281 if (process.platform === "win32") binaryName = "rust-analyzer-windows.exe"; 281 if (process.platform === "win32") platform = "windows";
282 } 282 }
283 if (binaryName === undefined) { 283 if (platform === undefined) {
284 vscode.window.showErrorMessage( 284 vscode.window.showErrorMessage(
285 "Unfortunately we don't ship binaries for your platform yet. " + 285 "Unfortunately we don't ship binaries for your platform yet. " +
286 "You need to manually clone rust-analyzer repository and " + 286 "You need to manually clone rust-analyzer repository and " +
@@ -291,8 +291,8 @@ async function getServer(config: Config, state: PersistentState): Promise<string
291 ); 291 );
292 return undefined; 292 return undefined;
293 } 293 }
294 294 const ext = platform === "windows" ? ".exe" : "";
295 const dest = path.join(config.globalStoragePath, binaryName); 295 const dest = path.join(config.globalStoragePath, `rust-analyzer-${platform}${ext}`);
296 const exists = await fs.stat(dest).then(() => true, () => false); 296 const exists = await fs.stat(dest).then(() => true, () => false);
297 if (!exists) { 297 if (!exists) {
298 await state.updateServerVersion(undefined); 298 await state.updateServerVersion(undefined);
@@ -309,7 +309,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string
309 } 309 }
310 310
311 const release = await fetchRelease(config.package.releaseTag); 311 const release = await fetchRelease(config.package.releaseTag);
312 const artifact = release.assets.find(artifact => artifact.name === binaryName); 312 const artifact = release.assets.find(artifact => artifact.name === `rust-analyzer-${platform}.gz`);
313 assert(!!artifact, `Bad release: ${JSON.stringify(release)}`); 313 assert(!!artifact, `Bad release: ${JSON.stringify(release)}`);
314 314
315 // Unlinking the exe file before moving new one on its place should prevent ETXTBSY error. 315 // Unlinking the exe file before moving new one on its place should prevent ETXTBSY error.
@@ -321,6 +321,7 @@ async function getServer(config: Config, state: PersistentState): Promise<string
321 url: artifact.browser_download_url, 321 url: artifact.browser_download_url,
322 dest, 322 dest,
323 progressTitle: "Downloading rust-analyzer server", 323 progressTitle: "Downloading rust-analyzer server",
324 gunzip: true,
324 mode: 0o755 325 mode: 0o755
325 }); 326 });
326 327
diff --git a/editors/code/src/net.ts b/editors/code/src/net.ts
index 866092882..53c9e91cd 100644
--- a/editors/code/src/net.ts
+++ b/editors/code/src/net.ts
@@ -3,6 +3,7 @@ import * as vscode from "vscode";
3import * as stream from "stream"; 3import * as stream from "stream";
4import * as crypto from "crypto"; 4import * as crypto from "crypto";
5import * as fs from "fs"; 5import * as fs from "fs";
6import * as zlib from "zlib";
6import * as util from "util"; 7import * as util from "util";
7import * as path from "path"; 8import * as path from "path";
8import { log, assert } from "./util"; 9import { log, assert } from "./util";
@@ -65,6 +66,7 @@ interface DownloadOpts {
65 url: string; 66 url: string;
66 dest: string; 67 dest: string;
67 mode?: number; 68 mode?: number;
69 gunzip?: boolean;
68} 70}
69 71
70export async function download(opts: DownloadOpts) { 72export async function download(opts: DownloadOpts) {
@@ -82,7 +84,7 @@ export async function download(opts: DownloadOpts) {
82 }, 84 },
83 async (progress, _cancellationToken) => { 85 async (progress, _cancellationToken) => {
84 let lastPercentage = 0; 86 let lastPercentage = 0;
85 await downloadFile(opts.url, tempFile, opts.mode, (readBytes, totalBytes) => { 87 await downloadFile(opts.url, tempFile, opts.mode, !!opts.gunzip, (readBytes, totalBytes) => {
86 const newPercentage = (readBytes / totalBytes) * 100; 88 const newPercentage = (readBytes / totalBytes) * 100;
87 progress.report({ 89 progress.report({
88 message: newPercentage.toFixed(0) + "%", 90 message: newPercentage.toFixed(0) + "%",
@@ -97,16 +99,11 @@ export async function download(opts: DownloadOpts) {
97 await fs.promises.rename(tempFile, opts.dest); 99 await fs.promises.rename(tempFile, opts.dest);
98} 100}
99 101
100/**
101 * Downloads file from `url` and stores it at `destFilePath` with `mode` (unix permissions).
102 * `onProgress` callback is called on recieveing each chunk of bytes
103 * to track the progress of downloading, it gets the already read and total
104 * amount of bytes to read as its parameters.
105 */
106async function downloadFile( 102async function downloadFile(
107 url: string, 103 url: string,
108 destFilePath: fs.PathLike, 104 destFilePath: fs.PathLike,
109 mode: number | undefined, 105 mode: number | undefined,
106 gunzip: boolean,
110 onProgress: (readBytes: number, totalBytes: number) => void 107 onProgress: (readBytes: number, totalBytes: number) => void
111): Promise<void> { 108): Promise<void> {
112 const res = await fetch(url); 109 const res = await fetch(url);
@@ -130,7 +127,10 @@ async function downloadFile(
130 }); 127 });
131 128
132 const destFileStream = fs.createWriteStream(destFilePath, { mode }); 129 const destFileStream = fs.createWriteStream(destFilePath, { mode });
133 await pipeline(res.body, destFileStream); 130 const srcStream = gunzip ? res.body.pipe(zlib.createGunzip()) : res.body;
131
132 await pipeline(srcStream, destFileStream);
133
134 await new Promise<void>(resolve => { 134 await new Promise<void>(resolve => {
135 destFileStream.on("close", resolve); 135 destFileStream.on("close", resolve);
136 destFileStream.destroy(); 136 destFileStream.destroy();
diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml
index a8b9b010d..8045a98ea 100644
--- a/xtask/Cargo.toml
+++ b/xtask/Cargo.toml
@@ -14,3 +14,4 @@ pico-args = "0.3.1"
14quote = "1.0.2" 14quote = "1.0.2"
15proc-macro2 = "1.0.8" 15proc-macro2 = "1.0.8"
16anyhow = "1.0.26" 16anyhow = "1.0.26"
17flate2 = "1.0"
diff --git a/xtask/src/dist.rs b/xtask/src/dist.rs
index aef68089e..b8f68027c 100644
--- a/xtask/src/dist.rs
+++ b/xtask/src/dist.rs
@@ -1,4 +1,10 @@
1use std::path::PathBuf; 1use flate2::{write::GzEncoder, Compression};
2use std::{
3 env,
4 fs::File,
5 io,
6 path::{Path, PathBuf},
7};
2 8
3use anyhow::Result; 9use anyhow::Result;
4 10
@@ -16,7 +22,7 @@ pub fn run_dist(nightly: bool, client_version: Option<String>) -> Result<()> {
16 let release_tag = if nightly { "nightly".to_string() } else { date_iso()? }; 22 let release_tag = if nightly { "nightly".to_string() } else { date_iso()? };
17 dist_client(&version, &release_tag)?; 23 dist_client(&version, &release_tag)?;
18 } 24 }
19 dist_server(nightly)?; 25 dist_server()?;
20 Ok(()) 26 Ok(())
21} 27}
22 28
@@ -46,17 +52,14 @@ fn dist_client(version: &str, release_tag: &str) -> Result<()> {
46 Ok(()) 52 Ok(())
47} 53}
48 54
49fn dist_server(nightly: bool) -> Result<()> { 55fn dist_server() -> Result<()> {
50 if cfg!(target_os = "linux") { 56 if cfg!(target_os = "linux") {
51 std::env::set_var("CC", "clang"); 57 env::set_var("CC", "clang");
52 run!( 58 run!(
53 "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release" 59 "cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release"
54 // We'd want to add, but that requires setting the right linker somehow 60 // We'd want to add, but that requires setting the right linker somehow
55 // --features=jemalloc 61 // --features=jemalloc
56 )?; 62 )?;
57 if !nightly {
58 run!("strip ./target/release/rust-analyzer")?;
59 }
60 } else { 63 } else {
61 run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?; 64 run!("cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release")?;
62 } 65 }
@@ -71,8 +74,20 @@ fn dist_server(nightly: bool) -> Result<()> {
71 panic!("Unsupported OS") 74 panic!("Unsupported OS")
72 }; 75 };
73 76
74 fs2::copy(src, dst)?; 77 let src = Path::new(src);
78 let dst = Path::new(dst);
79
80 fs2::copy(&src, &dst)?;
81 gzip(&src, &dst.with_extension("gz"))?;
82
83 Ok(())
84}
75 85
86fn gzip(src_path: &Path, dest_path: &Path) -> Result<()> {
87 let mut encoder = GzEncoder::new(File::create(dest_path)?, Compression::best());
88 let mut input = io::BufReader::new(File::open(src_path)?);
89 io::copy(&mut input, &mut encoder)?;
90 encoder.finish()?;
76 Ok(()) 91 Ok(())
77} 92}
78 93