2024-01-01 14:58:21 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
2020-08-28 09:03:50 -04:00
|
|
|
|
2024-05-08 22:45:06 -04:00
|
|
|
#![allow(clippy::print_stdout)]
|
|
|
|
#![allow(clippy::print_stderr)]
|
|
|
|
|
2021-01-27 22:50:14 -05:00
|
|
|
use deno_core::error::AnyError;
|
2021-02-25 00:14:17 -05:00
|
|
|
use deno_core::serde_json;
|
|
|
|
use deno_core::serde_json::Value;
|
|
|
|
use std::collections::HashMap;
|
|
|
|
use std::convert::From;
|
|
|
|
use std::env;
|
|
|
|
use std::fs;
|
2021-03-25 14:17:37 -04:00
|
|
|
use std::path::Path;
|
2021-02-25 00:14:17 -05:00
|
|
|
use std::path::PathBuf;
|
|
|
|
use std::process::Command;
|
|
|
|
use std::process::Stdio;
|
2021-01-17 11:40:29 -05:00
|
|
|
use std::time::SystemTime;
|
2023-06-10 11:09:45 -04:00
|
|
|
use test_util::PathRef;
|
2020-08-28 09:03:50 -04:00
|
|
|
|
2021-02-25 00:14:17 -05:00
|
|
|
mod lsp;
|
2020-08-28 09:03:50 -04:00
|
|
|
|
2023-06-10 11:09:45 -04:00
|
|
|
fn read_json(filename: &Path) -> Result<Value> {
|
2020-08-28 09:03:50 -04:00
|
|
|
let f = fs::File::open(filename)?;
|
|
|
|
Ok(serde_json::from_reader(f)?)
|
|
|
|
}
|
|
|
|
|
2023-06-10 11:09:45 -04:00
|
|
|
fn write_json(filename: &Path, value: &Value) -> Result<()> {
|
2020-08-28 09:03:50 -04:00
|
|
|
let f = fs::File::create(filename)?;
|
|
|
|
serde_json::to_writer(f, value)?;
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
/// The list of the tuples of the benchmark name, arguments and return code
|
|
|
|
const EXEC_TIME_BENCHMARKS: &[(&str, &[&str], Option<i32>)] = &[
|
2020-10-01 06:32:05 -04:00
|
|
|
// we need to run the cold_* benchmarks before the _warm_ ones as they ensure
|
|
|
|
// the cache is properly populated, instead of other tests possibly
|
|
|
|
// invalidating that cache.
|
2020-08-28 09:03:50 -04:00
|
|
|
(
|
|
|
|
"cold_hello",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
&["run", "--reload", "tests/testdata/run/002_hello.ts"],
|
2020-08-28 09:03:50 -04:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"cold_relative_import",
|
2021-08-11 10:20:47 -04:00
|
|
|
&[
|
|
|
|
"run",
|
|
|
|
"--reload",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
"tests/testdata/run/003_relative_import.ts",
|
2021-08-11 10:20:47 -04:00
|
|
|
],
|
2020-08-28 09:03:50 -04:00
|
|
|
None,
|
|
|
|
),
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
("hello", &["run", "tests/testdata/run/002_hello.ts"], None),
|
2020-10-01 06:32:05 -04:00
|
|
|
(
|
|
|
|
"relative_import",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
&["run", "tests/testdata/run/003_relative_import.ts"],
|
2020-10-01 06:32:05 -04:00
|
|
|
None,
|
|
|
|
),
|
2021-08-11 10:20:47 -04:00
|
|
|
(
|
|
|
|
"error_001",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
&["run", "tests/testdata/run/error_001.ts"],
|
2021-08-11 10:20:47 -04:00
|
|
|
Some(1),
|
|
|
|
),
|
2020-09-14 06:25:06 -04:00
|
|
|
(
|
|
|
|
"no_check_hello",
|
2021-08-11 10:20:47 -04:00
|
|
|
&[
|
|
|
|
"run",
|
|
|
|
"--reload",
|
|
|
|
"--no-check",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
"tests/testdata/run/002_hello.ts",
|
2021-08-11 10:20:47 -04:00
|
|
|
],
|
2020-09-14 06:25:06 -04:00
|
|
|
None,
|
|
|
|
),
|
2020-08-28 09:03:50 -04:00
|
|
|
(
|
|
|
|
"workers_startup",
|
2021-08-11 10:20:47 -04:00
|
|
|
&[
|
|
|
|
"run",
|
|
|
|
"--allow-read",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
"tests/testdata/workers/bench_startup.ts",
|
2021-08-11 10:20:47 -04:00
|
|
|
],
|
2020-08-28 09:03:50 -04:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"workers_round_robin",
|
|
|
|
&[
|
|
|
|
"run",
|
|
|
|
"--allow-read",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
"tests/testdata/workers/bench_round_robin.ts",
|
2020-08-28 09:03:50 -04:00
|
|
|
],
|
|
|
|
None,
|
|
|
|
),
|
2021-02-23 07:08:50 -05:00
|
|
|
(
|
|
|
|
"workers_large_message",
|
|
|
|
&[
|
|
|
|
"run",
|
|
|
|
"--allow-read",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
"tests/testdata/workers/bench_large_message.ts",
|
2021-02-23 07:08:50 -05:00
|
|
|
],
|
|
|
|
None,
|
|
|
|
),
|
2020-08-28 09:03:50 -04:00
|
|
|
(
|
|
|
|
"text_decoder",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
&["run", "tests/testdata/benches/text_decoder_perf.js"],
|
2020-08-28 09:03:50 -04:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"text_encoder",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
&["run", "tests/testdata/benches/text_encoder_perf.js"],
|
2020-08-28 09:03:50 -04:00
|
|
|
None,
|
|
|
|
),
|
2021-05-08 17:31:40 -04:00
|
|
|
(
|
|
|
|
"text_encoder_into",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
&["run", "tests/testdata/benches/text_encoder_into_perf.js"],
|
2021-05-08 17:31:40 -04:00
|
|
|
None,
|
|
|
|
),
|
2021-09-25 09:30:31 -04:00
|
|
|
(
|
|
|
|
"response_string",
|
chore: move cli/tests/ -> tests/ (#22369)
This looks like a massive PR, but it's only a move from cli/tests ->
tests, and updates of relative paths for files.
This is the first step towards aggregate all of the integration test
files under tests/, which will lead to a set of integration tests that
can run without the CLI binary being built.
While we could leave these tests under `cli`, it would require us to
keep a more complex directory structure for the various test runners. In
addition, we have a lot of complexity to ignore various test files in
the `cli` project itself (cargo publish exclusion rules, autotests =
false, etc).
And finally, the `tests/` folder will eventually house the `test_ffi`,
`test_napi` and other testing code, reducing the size of the root repo
directory.
For easier review, the extremely large and noisy "move" is in the first
commit (with no changes -- just a move), while the remainder of the
changes to actual files is in the second commit.
2024-02-10 15:22:13 -05:00
|
|
|
&["run", "tests/testdata/benches/response_string_perf.js"],
|
2021-09-25 09:30:31 -04:00
|
|
|
None,
|
|
|
|
),
|
2020-08-28 09:03:50 -04:00
|
|
|
(
|
|
|
|
"check",
|
2021-02-02 06:05:46 -05:00
|
|
|
&[
|
2022-06-20 10:37:24 -04:00
|
|
|
"check",
|
2021-02-02 06:05:46 -05:00
|
|
|
"--reload",
|
2022-05-25 15:53:53 -04:00
|
|
|
"--unstable",
|
2024-07-25 19:53:52 -04:00
|
|
|
"--config",
|
|
|
|
"tests/config/deno.json",
|
2024-02-13 11:22:49 -05:00
|
|
|
"tests/util/std/http/file_server_test.ts",
|
2021-02-02 06:05:46 -05:00
|
|
|
],
|
2020-08-28 09:03:50 -04:00
|
|
|
None,
|
|
|
|
),
|
|
|
|
(
|
|
|
|
"no_check",
|
|
|
|
&[
|
|
|
|
"cache",
|
|
|
|
"--reload",
|
|
|
|
"--no-check",
|
2022-05-25 15:53:53 -04:00
|
|
|
"--unstable",
|
2024-07-25 19:53:52 -04:00
|
|
|
"--config",
|
|
|
|
"tests/config/deno.json",
|
2024-02-13 11:22:49 -05:00
|
|
|
"tests/util/std/http/file_server_test.ts",
|
2020-08-28 09:03:50 -04:00
|
|
|
],
|
|
|
|
None,
|
|
|
|
),
|
|
|
|
];
|
|
|
|
|
|
|
|
const RESULT_KEYS: &[&str] =
|
|
|
|
&["mean", "stddev", "user", "system", "min", "max"];
|
2021-01-17 11:40:29 -05:00
|
|
|
fn run_exec_time(
|
2021-03-25 14:17:37 -04:00
|
|
|
deno_exe: &Path,
|
2023-06-10 11:09:45 -04:00
|
|
|
target_dir: &PathRef,
|
2022-07-11 14:58:32 -04:00
|
|
|
) -> Result<HashMap<String, HashMap<String, f64>>> {
|
2023-06-10 11:09:45 -04:00
|
|
|
let hyperfine_exe = test_util::prebuilt_tool_path("hyperfine").to_string();
|
2020-08-28 09:03:50 -04:00
|
|
|
|
|
|
|
let benchmark_file = target_dir.join("hyperfine_results.json");
|
2023-06-10 11:09:45 -04:00
|
|
|
let benchmark_file_str = benchmark_file.to_string();
|
2020-08-28 09:03:50 -04:00
|
|
|
|
|
|
|
let mut command = [
|
2023-06-10 11:09:45 -04:00
|
|
|
hyperfine_exe.as_str(),
|
2020-08-28 09:03:50 -04:00
|
|
|
"--export-json",
|
2023-06-10 11:09:45 -04:00
|
|
|
benchmark_file_str.as_str(),
|
2020-08-28 09:03:50 -04:00
|
|
|
"--warmup",
|
|
|
|
"3",
|
|
|
|
]
|
|
|
|
.iter()
|
|
|
|
.map(|s| s.to_string())
|
|
|
|
.collect::<Vec<_>>();
|
|
|
|
|
|
|
|
for (_, args, return_code) in EXEC_TIME_BENCHMARKS {
|
|
|
|
let ret_code_test = if let Some(code) = return_code {
|
|
|
|
// Bash test which asserts the return code value of the previous command
|
|
|
|
// $? contains the return code of the previous command
|
2023-01-27 10:43:16 -05:00
|
|
|
format!("; test $? -eq {code}")
|
2020-08-28 09:03:50 -04:00
|
|
|
} else {
|
|
|
|
"".to_string()
|
|
|
|
};
|
|
|
|
command.push(format!(
|
|
|
|
"{} {} {}",
|
|
|
|
deno_exe.to_str().unwrap(),
|
|
|
|
args.join(" "),
|
|
|
|
ret_code_test
|
|
|
|
));
|
|
|
|
}
|
|
|
|
|
|
|
|
test_util::run(
|
|
|
|
&command.iter().map(|s| s.as_ref()).collect::<Vec<_>>(),
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
true,
|
|
|
|
);
|
|
|
|
|
2022-07-11 14:58:32 -04:00
|
|
|
let mut results = HashMap::<String, HashMap<String, f64>>::new();
|
2023-06-10 11:09:45 -04:00
|
|
|
let hyperfine_results = read_json(benchmark_file.as_path())?;
|
2020-08-28 09:03:50 -04:00
|
|
|
for ((name, _, _), data) in EXEC_TIME_BENCHMARKS.iter().zip(
|
|
|
|
hyperfine_results
|
|
|
|
.as_object()
|
|
|
|
.unwrap()
|
|
|
|
.get("results")
|
|
|
|
.unwrap()
|
|
|
|
.as_array()
|
|
|
|
.unwrap(),
|
|
|
|
) {
|
|
|
|
let data = data.as_object().unwrap().clone();
|
|
|
|
results.insert(
|
|
|
|
name.to_string(),
|
2021-01-17 11:40:29 -05:00
|
|
|
data
|
|
|
|
.into_iter()
|
|
|
|
.filter(|(key, _)| RESULT_KEYS.contains(&key.as_str()))
|
2022-07-11 14:58:32 -04:00
|
|
|
.map(|(key, val)| (key, val.as_f64().unwrap()))
|
2021-01-17 11:40:29 -05:00
|
|
|
.collect(),
|
2020-08-28 09:03:50 -04:00
|
|
|
);
|
|
|
|
}
|
|
|
|
|
2021-01-17 11:40:29 -05:00
|
|
|
Ok(results)
|
2020-08-28 09:03:50 -04:00
|
|
|
}
|
|
|
|
|
2022-06-28 08:21:05 -04:00
|
|
|
fn rlib_size(target_dir: &std::path::Path, prefix: &str) -> i64 {
|
2021-01-05 16:28:51 -05:00
|
|
|
let mut size = 0;
|
|
|
|
let mut seen = std::collections::HashSet::new();
|
|
|
|
for entry in std::fs::read_dir(target_dir.join("deps")).unwrap() {
|
|
|
|
let entry = entry.unwrap();
|
|
|
|
let os_str = entry.file_name();
|
|
|
|
let name = os_str.to_str().unwrap();
|
|
|
|
if name.starts_with(prefix) && name.ends_with(".rlib") {
|
|
|
|
let start = name.split('-').next().unwrap().to_string();
|
|
|
|
if seen.contains(&start) {
|
2023-01-27 10:43:16 -05:00
|
|
|
println!("skip {name}");
|
2021-01-05 16:28:51 -05:00
|
|
|
} else {
|
|
|
|
seen.insert(start);
|
|
|
|
size += entry.metadata().unwrap().len();
|
2023-01-27 10:43:16 -05:00
|
|
|
println!("check size {name} {size}");
|
2021-01-05 16:28:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
assert!(size > 0);
|
2022-06-28 08:21:05 -04:00
|
|
|
size as i64
|
2021-01-05 16:28:51 -05:00
|
|
|
}
|
|
|
|
|
2023-03-18 16:00:00 -04:00
|
|
|
const BINARY_TARGET_FILES: &[&str] = &[
|
|
|
|
"CLI_SNAPSHOT.bin",
|
|
|
|
"RUNTIME_SNAPSHOT.bin",
|
|
|
|
"COMPILER_SNAPSHOT.bin",
|
|
|
|
];
|
2022-06-28 08:21:05 -04:00
|
|
|
fn get_binary_sizes(target_dir: &Path) -> Result<HashMap<String, i64>> {
|
|
|
|
let mut sizes = HashMap::<String, i64>::new();
|
2021-01-17 11:40:29 -05:00
|
|
|
let mut mtimes = HashMap::<String, SystemTime>::new();
|
2020-08-28 09:03:50 -04:00
|
|
|
|
|
|
|
sizes.insert(
|
|
|
|
"deno".to_string(),
|
2023-06-10 11:09:45 -04:00
|
|
|
test_util::deno_exe_path().as_path().metadata()?.len() as i64,
|
2020-08-28 09:03:50 -04:00
|
|
|
);
|
|
|
|
|
2021-01-05 16:28:51 -05:00
|
|
|
// add up size for everything in target/release/deps/libswc*
|
2021-07-30 09:03:41 -04:00
|
|
|
let swc_size = rlib_size(target_dir, "libswc");
|
2023-01-27 10:43:16 -05:00
|
|
|
println!("swc {swc_size} bytes");
|
2021-01-17 11:40:29 -05:00
|
|
|
sizes.insert("swc_rlib".to_string(), swc_size);
|
2021-01-05 16:28:51 -05:00
|
|
|
|
2021-10-28 06:40:27 -04:00
|
|
|
let v8_size = rlib_size(target_dir, "libv8");
|
2023-01-27 10:43:16 -05:00
|
|
|
println!("v8 {v8_size} bytes");
|
2021-10-28 06:40:27 -04:00
|
|
|
sizes.insert("rusty_v8_rlib".to_string(), v8_size);
|
2021-01-05 16:28:51 -05:00
|
|
|
|
2020-08-28 09:03:50 -04:00
|
|
|
// Because cargo's OUT_DIR is not predictable, search the build tree for
|
|
|
|
// snapshot related files.
|
|
|
|
for file in walkdir::WalkDir::new(target_dir) {
|
2020-11-12 17:17:31 -05:00
|
|
|
let file = match file {
|
|
|
|
Ok(file) => file,
|
|
|
|
Err(_) => continue,
|
|
|
|
};
|
2020-08-28 09:03:50 -04:00
|
|
|
let filename = file.file_name().to_str().unwrap().to_string();
|
|
|
|
|
|
|
|
if !BINARY_TARGET_FILES.contains(&filename.as_str()) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
let meta = file.metadata()?;
|
|
|
|
let file_mtime = meta.modified()?;
|
|
|
|
|
|
|
|
// If multiple copies of a file are found, use the most recent one.
|
|
|
|
if let Some(stored_mtime) = mtimes.get(&filename) {
|
|
|
|
if *stored_mtime > file_mtime {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
mtimes.insert(filename.clone(), file_mtime);
|
2022-06-28 08:21:05 -04:00
|
|
|
sizes.insert(filename, meta.len() as i64);
|
2020-08-28 09:03:50 -04:00
|
|
|
}
|
|
|
|
|
2021-01-17 11:40:29 -05:00
|
|
|
Ok(sizes)
|
2020-08-28 09:03:50 -04:00
|
|
|
}
|
|
|
|
|
2022-06-28 08:21:05 -04:00
|
|
|
fn run_max_mem_benchmark(deno_exe: &Path) -> Result<HashMap<String, i64>> {
|
|
|
|
let mut results = HashMap::<String, i64>::new();
|
2020-08-28 09:03:50 -04:00
|
|
|
|
|
|
|
for (name, args, return_code) in EXEC_TIME_BENCHMARKS {
|
|
|
|
let proc = Command::new("time")
|
2022-11-17 20:59:10 -05:00
|
|
|
.args(["-v", deno_exe.to_str().unwrap()])
|
2020-08-28 09:03:50 -04:00
|
|
|
.args(args.iter())
|
|
|
|
.stdout(Stdio::null())
|
|
|
|
.stderr(Stdio::piped())
|
|
|
|
.spawn()?;
|
|
|
|
|
|
|
|
let proc_result = proc.wait_with_output()?;
|
|
|
|
if let Some(code) = return_code {
|
|
|
|
assert_eq!(proc_result.status.code().unwrap(), *code);
|
|
|
|
}
|
|
|
|
let out = String::from_utf8(proc_result.stderr)?;
|
|
|
|
|
2022-06-28 08:21:05 -04:00
|
|
|
results.insert(
|
|
|
|
name.to_string(),
|
|
|
|
test_util::parse_max_mem(&out).unwrap() as i64,
|
|
|
|
);
|
2020-08-28 09:03:50 -04:00
|
|
|
}
|
|
|
|
|
2021-01-17 11:40:29 -05:00
|
|
|
Ok(results)
|
2020-08-28 09:03:50 -04:00
|
|
|
}
|
|
|
|
|
2021-01-10 08:13:38 -05:00
|
|
|
fn cargo_deps() -> usize {
|
|
|
|
let cargo_lock = test_util::root_path().join("Cargo.lock");
|
|
|
|
let mut count = 0;
|
|
|
|
let file = std::fs::File::open(cargo_lock).unwrap();
|
|
|
|
use std::io::BufRead;
|
|
|
|
for line in std::io::BufReader::new(file).lines() {
|
|
|
|
if line.unwrap().starts_with("[[package]]") {
|
|
|
|
count += 1
|
|
|
|
}
|
|
|
|
}
|
2023-01-27 10:43:16 -05:00
|
|
|
println!("cargo_deps {count}");
|
2021-01-10 08:13:38 -05:00
|
|
|
assert!(count > 10); // Sanity check.
|
|
|
|
count
|
|
|
|
}
|
|
|
|
|
2022-06-28 08:21:05 -04:00
|
|
|
// TODO(@littledivy): Remove this, denoland/benchmark_data is deprecated.
|
|
|
|
#[derive(Default, serde::Serialize)]
|
2021-01-17 11:40:29 -05:00
|
|
|
struct BenchResult {
|
|
|
|
created_at: String,
|
|
|
|
sha1: String,
|
2021-02-25 00:14:17 -05:00
|
|
|
|
2021-01-17 11:40:29 -05:00
|
|
|
// TODO(ry) The "benchmark" benchmark should actually be called "exec_time".
|
|
|
|
// When this is changed, the historical data in gh-pages branch needs to be
|
|
|
|
// changed too.
|
2022-07-11 14:58:32 -04:00
|
|
|
benchmark: HashMap<String, HashMap<String, f64>>,
|
2022-06-28 08:21:05 -04:00
|
|
|
binary_size: HashMap<String, i64>,
|
|
|
|
bundle_size: HashMap<String, i64>,
|
2021-02-25 00:14:17 -05:00
|
|
|
cargo_deps: usize,
|
2024-10-24 17:19:58 -04:00
|
|
|
// TODO(bartlomieju): remove
|
2022-07-11 14:58:32 -04:00
|
|
|
max_latency: HashMap<String, f64>,
|
2022-06-28 08:21:05 -04:00
|
|
|
max_memory: HashMap<String, i64>,
|
|
|
|
lsp_exec_time: HashMap<String, i64>,
|
2024-10-24 17:19:58 -04:00
|
|
|
// TODO(bartlomieju): remove
|
2022-06-28 08:21:05 -04:00
|
|
|
req_per_sec: HashMap<String, i64>,
|
|
|
|
syscall_count: HashMap<String, i64>,
|
|
|
|
thread_count: HashMap<String, i64>,
|
2021-01-17 11:40:29 -05:00
|
|
|
}
|
|
|
|
|
2022-06-28 08:21:05 -04:00
|
|
|
#[tokio::main]
|
|
|
|
async fn main() -> Result<()> {
|
|
|
|
let mut args = env::args();
|
|
|
|
|
|
|
|
let mut benchmarks = vec![
|
|
|
|
"exec_time",
|
|
|
|
"binary_size",
|
|
|
|
"cargo_deps",
|
|
|
|
"lsp",
|
|
|
|
"strace",
|
|
|
|
"mem_usage",
|
|
|
|
];
|
|
|
|
|
|
|
|
let mut found_bench = false;
|
|
|
|
let filter = args.nth(1);
|
|
|
|
if let Some(filter) = filter {
|
|
|
|
if filter != "--bench" {
|
|
|
|
benchmarks.retain(|s| s == &filter);
|
|
|
|
} else {
|
|
|
|
found_bench = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if !found_bench && !args.any(|s| s == "--bench") {
|
2020-08-28 09:03:50 -04:00
|
|
|
return Ok(());
|
|
|
|
}
|
|
|
|
|
|
|
|
println!("Starting Deno benchmark");
|
|
|
|
|
|
|
|
let target_dir = test_util::target_dir();
|
chore(lsp): Add benchmark for performance on a large real-world repo (#23395)
This PR adds a benchmark intended to measure how the LSP handles larger
repos, as well as its performance on a more realistic workload.
The repo being benchmarked is
[deco-cx/apps](https://github.com/deco-cx/apps) which has been vendored
along with its dependencies. It's included as a git submodule as its
fairly large. The LSP requests used in the benchmark are the actual
requests sent by VSCode as I opened, modified, and navigated around a
file (to simulate an actual user interaction).
The main motivation is to have a more realistic benchmark that measures
how we do with a large number of files and dependencies. The
improvements made from 1.42 to 1.42.3 mostly improved performance with
larger repos, so none of our existing benchmarks showed an improvement.
Here are the results for the changes made from 1.42 to 1.42.3 (the new
benchmark is the last one listed):
**1.42.0**
```test
Starting Deno benchmark
-> Start benchmarking lsp
- Simple Startup/Shutdown
(10 runs, mean: 379ms)
- Big Document/Several Edits
(5 runs, mean: 1142ms)
- Find/Replace
(10 runs, mean: 51ms)
- Code Lens
(10 runs, mean: 443ms)
- deco-cx/apps Multiple Edits + Navigation
(5 runs, mean: 25121ms)
<- End benchmarking lsp
```
**1.42.3**
```text
Starting Deno benchmark
-> Start benchmarking lsp
- Simple Startup/Shutdown
(10 runs, mean: 383ms)
- Big Document/Several Edits
(5 runs, mean: 1135ms)
- Find/Replace
(10 runs, mean: 55ms)
- Code Lens
(10 runs, mean: 440ms)
- deco-cx/apps Multiple Edits + Navigation
(5 runs, mean: 11675ms)
<- End benchmarking lsp
```
2024-04-16 15:26:51 -04:00
|
|
|
let deno_exe = if let Ok(p) = std::env::var("DENO_BENCH_EXE") {
|
|
|
|
PathBuf::from(p)
|
|
|
|
} else {
|
|
|
|
test_util::deno_exe_path().to_path_buf()
|
|
|
|
};
|
2022-12-17 17:20:15 -05:00
|
|
|
env::set_current_dir(test_util::root_path())?;
|
2020-08-28 09:03:50 -04:00
|
|
|
|
2021-02-25 00:14:17 -05:00
|
|
|
let mut new_data = BenchResult {
|
2024-05-23 07:59:11 -04:00
|
|
|
created_at: chrono::Utc::now()
|
|
|
|
.to_rfc3339_opts(chrono::SecondsFormat::Secs, true),
|
2021-02-25 00:14:17 -05:00
|
|
|
sha1: test_util::run_collect(
|
|
|
|
&["git", "rev-parse", "HEAD"],
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
None,
|
|
|
|
true,
|
|
|
|
)
|
|
|
|
.0
|
|
|
|
.trim()
|
|
|
|
.to_string(),
|
|
|
|
..Default::default()
|
|
|
|
};
|
2020-08-28 09:03:50 -04:00
|
|
|
|
2022-06-28 08:21:05 -04:00
|
|
|
if benchmarks.contains(&"exec_time") {
|
|
|
|
let exec_times = run_exec_time(&deno_exe, &target_dir)?;
|
|
|
|
new_data.benchmark = exec_times;
|
|
|
|
}
|
|
|
|
|
|
|
|
if benchmarks.contains(&"binary_size") {
|
2023-06-10 11:09:45 -04:00
|
|
|
let binary_sizes = get_binary_sizes(target_dir.as_path())?;
|
2022-06-28 08:21:05 -04:00
|
|
|
new_data.binary_size = binary_sizes;
|
|
|
|
}
|
|
|
|
|
|
|
|
if benchmarks.contains(&"cargo_deps") {
|
|
|
|
let cargo_deps = cargo_deps();
|
|
|
|
new_data.cargo_deps = cargo_deps;
|
|
|
|
}
|
|
|
|
|
|
|
|
if benchmarks.contains(&"lsp") {
|
2023-03-09 15:09:03 -05:00
|
|
|
let lsp_exec_times = lsp::benchmarks(&deno_exe);
|
2022-06-28 08:21:05 -04:00
|
|
|
new_data.lsp_exec_time = lsp_exec_times;
|
2020-08-28 09:03:50 -04:00
|
|
|
}
|
|
|
|
|
2022-06-28 08:21:05 -04:00
|
|
|
if cfg!(target_os = "linux") && benchmarks.contains(&"strace") {
|
|
|
|
use std::io::Read;
|
|
|
|
|
|
|
|
let mut thread_count = HashMap::<String, i64>::new();
|
|
|
|
let mut syscall_count = HashMap::<String, i64>::new();
|
|
|
|
|
|
|
|
for (name, args, expected_exit_code) in EXEC_TIME_BENCHMARKS {
|
2023-03-22 14:55:19 -04:00
|
|
|
let mut file = tempfile::NamedTempFile::new()?;
|
2022-06-28 08:21:05 -04:00
|
|
|
|
|
|
|
let exit_status = Command::new("strace")
|
2022-11-17 20:59:10 -05:00
|
|
|
.args([
|
2022-06-28 08:21:05 -04:00
|
|
|
"-c",
|
|
|
|
"-f",
|
|
|
|
"-o",
|
|
|
|
file.path().to_str().unwrap(),
|
|
|
|
deno_exe.to_str().unwrap(),
|
|
|
|
])
|
|
|
|
.args(args.iter())
|
|
|
|
.stdout(Stdio::null())
|
2022-09-27 15:33:17 -04:00
|
|
|
.env("LC_NUMERIC", "C")
|
2022-06-28 08:21:05 -04:00
|
|
|
.spawn()?
|
|
|
|
.wait()?;
|
|
|
|
let expected_exit_code = expected_exit_code.unwrap_or(0);
|
|
|
|
assert_eq!(exit_status.code(), Some(expected_exit_code));
|
|
|
|
|
|
|
|
let mut output = String::new();
|
|
|
|
file.as_file_mut().read_to_string(&mut output)?;
|
|
|
|
|
|
|
|
let strace_result = test_util::parse_strace_output(&output);
|
2023-03-27 10:45:00 -04:00
|
|
|
let clone =
|
|
|
|
strace_result
|
|
|
|
.get("clone")
|
|
|
|
.map(|d| d.calls)
|
|
|
|
.unwrap_or_else(|| {
|
|
|
|
strace_result.get("clone3").map(|d| d.calls).unwrap_or(0)
|
|
|
|
})
|
|
|
|
+ 1;
|
2022-06-28 08:21:05 -04:00
|
|
|
let total = strace_result.get("total").unwrap().calls;
|
|
|
|
thread_count.insert(name.to_string(), clone as i64);
|
|
|
|
syscall_count.insert(name.to_string(), total as i64);
|
|
|
|
}
|
|
|
|
|
|
|
|
new_data.thread_count = thread_count;
|
|
|
|
new_data.syscall_count = syscall_count;
|
|
|
|
}
|
|
|
|
|
|
|
|
if benchmarks.contains(&"mem_usage") {
|
|
|
|
let max_memory = run_max_mem_benchmark(&deno_exe)?;
|
|
|
|
new_data.max_memory = max_memory;
|
|
|
|
}
|
2020-08-28 09:03:50 -04:00
|
|
|
|
2023-06-10 11:09:45 -04:00
|
|
|
write_json(
|
|
|
|
target_dir.join("bench.json").as_path(),
|
|
|
|
&serde_json::to_value(&new_data)?,
|
|
|
|
)?;
|
2020-08-28 09:03:50 -04:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2022-03-23 09:54:22 -04:00
|
|
|
pub type Result<T> = std::result::Result<T, AnyError>;
|