diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-07-07 21:36:18 +0100 |
---|---|---|
committer | GitHub <[email protected]> | 2020-07-07 21:36:18 +0100 |
commit | 56ade20380a028026eeb71af2a8a81e37ede7efb (patch) | |
tree | fbf0e24250cc36eaa122904e78cd7cb50fe1c665 | |
parent | 980a67f44629ed67a54b603aaf9d015a81d61f7a (diff) | |
parent | f92bfb580780cda02f9ba8a935538f984d8a4c0d (diff) |
Merge #4972
4972: Gzip artifacts r=Veetaha a=Veetaha
[Here is the test release](https://github.com/Veetaha/rust-analyzer/releases/tag/2020-06-21)
Change in size: `~ 25 MB -> ~ 8 MB (gzipped)`
The time to gzip during the dist build takes a somewhat considerable amount of time tho.
Having already compiled artifacts this takes in debug mode:
```
~/dev/rust-analyzer (feat/gzip-binaries) $ time cargo xtask dist
Finished dev [unoptimized] target(s) in 0.06s
Running `target/debug/xtask dist`
> cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release
Finished release [optimized] target(s) in 0.05s
> strip ./target/release/rust-analyzer
real 0m34.331s
user 0m34.245s
sys 0m0.078s
```
In release mode this is much faster:
```
~/dev/rust-analyzer (feat/gzip-binaries) $ time cargo run -p xtask --release -- dist
Finished release [optimized] target(s) in 0.04s
Running `target/release/xtask dist`
> cargo build --manifest-path ./crates/rust-analyzer/Cargo.toml --bin rust-analyzer --release
Finished release [optimized] target(s) in 0.06s
> strip ./target/release/rust-analyzer
real 0m2.401s
```
**[UPD]** adding a profile override for `miniz_oxide` does the thing to ensure good performrance
We might need to notify all other ra plugins' maintainers about the change in our GH releases if we merge this PR, or we could leave uncompressed files along with gzipped for a while until everyone migrates.
Co-authored-by: Veetaha <[email protected]>
-rw-r--r-- | Cargo.lock | 22 | ||||
-rw-r--r-- | Cargo.toml | 5 | ||||
-rw-r--r-- | editors/code/src/main.ts | 17 | ||||
-rw-r--r-- | editors/code/src/net.ts | 16 | ||||
-rw-r--r-- | xtask/Cargo.toml | 1 | ||||
-rw-r--r-- | xtask/src/dist.rs | 31 |
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]] |
211 | name = "crc32fast" | ||
212 | version = "1.2.0" | ||
213 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
214 | checksum = "ba125de2af0df55319f41944744ad91c71113bf74a4646efff39afe1f6842db1" | ||
215 | dependencies = [ | ||
216 | "cfg-if", | ||
217 | ] | ||
218 | |||
219 | [[package]] | ||
211 | name = "crossbeam-channel" | 220 | name = "crossbeam-channel" |
212 | version = "0.4.2" | 221 | version = "0.4.2" |
213 | source = "registry+https://github.com/rust-lang/crates.io-index" | 222 | source = "registry+https://github.com/rust-lang/crates.io-index" |
@@ -341,6 +350,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" | |||
341 | checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" | 350 | checksum = "37ab347416e802de484e4d03c7316c48f1ecb56574dfd4a46a80f173ce1de04d" |
342 | 351 | ||
343 | [[package]] | 352 | [[package]] |
353 | name = "flate2" | ||
354 | version = "1.0.16" | ||
355 | source = "registry+https://github.com/rust-lang/crates.io-index" | ||
356 | checksum = "68c90b0fc46cf89d227cc78b40e494ff81287a92dd07631e5af0d06fe3cf885e" | ||
357 | dependencies = [ | ||
358 | "cfg-if", | ||
359 | "crc32fast", | ||
360 | "libc", | ||
361 | "miniz_oxide", | ||
362 | ] | ||
363 | |||
364 | [[package]] | ||
344 | name = "flycheck" | 365 | name = "flycheck" |
345 | version = "0.1.0" | 366 | version = "0.1.0" |
346 | dependencies = [ | 367 | dependencies = [ |
@@ -1993,6 +2014,7 @@ name = "xtask" | |||
1993 | version = "0.1.0" | 2014 | version = "0.1.0" |
1994 | dependencies = [ | 2015 | dependencies = [ |
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] |
30 | opt-level = 0 | 30 | opt-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] | ||
35 | opt-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"; | |||
3 | import * as stream from "stream"; | 3 | import * as stream from "stream"; |
4 | import * as crypto from "crypto"; | 4 | import * as crypto from "crypto"; |
5 | import * as fs from "fs"; | 5 | import * as fs from "fs"; |
6 | import * as zlib from "zlib"; | ||
6 | import * as util from "util"; | 7 | import * as util from "util"; |
7 | import * as path from "path"; | 8 | import * as path from "path"; |
8 | import { log, assert } from "./util"; | 9 | import { 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 | ||
70 | export async function download(opts: DownloadOpts) { | 72 | export 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 | */ | ||
106 | async function downloadFile( | 102 | async 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" | |||
14 | quote = "1.0.2" | 14 | quote = "1.0.2" |
15 | proc-macro2 = "1.0.8" | 15 | proc-macro2 = "1.0.8" |
16 | anyhow = "1.0.26" | 16 | anyhow = "1.0.26" |
17 | flate2 = "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 @@ | |||
1 | use std::path::PathBuf; | 1 | use flate2::{write::GzEncoder, Compression}; |
2 | use std::{ | ||
3 | env, | ||
4 | fs::File, | ||
5 | io, | ||
6 | path::{Path, PathBuf}, | ||
7 | }; | ||
2 | 8 | ||
3 | use anyhow::Result; | 9 | use 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 | ||
49 | fn dist_server(nightly: bool) -> Result<()> { | 55 | fn 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 | ||
86 | fn 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 | ||