Merge pull request #93 from greatest-ape/work-2022-09-25

Use Rust 1.64 workspace inheritance; udp&http: don't return response peers if announce event is stopped; fix anti-avx512 script issues
This commit is contained in:
Joakim Frostegård 2022-09-25 12:22:19 +02:00 committed by GitHub
commit 4b3f186c31
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
22 changed files with 200 additions and 163 deletions

View file

@ -14,22 +14,28 @@
### Changed
* Rename request workers to swarm workers
* Switch to thin LTO
* Switch to thin LTO for faster compile times
* Use proper workspace path declarations and remove workspace patch section
* Reduce space taken by ValidUntil struct from 128 to 32 bits
* Use [Rust 1.64 workspace inheritance](https://blog.rust-lang.org/2022/09/22/Rust-1.64.0.html)
* Reduce space taken by ValidUntil struct from 128 to 32 bits, reducing memory
consumtion for each stored peer by same amount
* Use regular (non-amortized) IndexMap for peer and pending scrape response maps (but not for torrent maps)
* Improve privilege dropping
* Quit whole program if any thread panics
* Update dependencies
* _aquatic_udp_: replace ConnectionMap with BLAKE3-based connection validator
* _aquatic_udp_: replace ConnectionMap with BLAKE3-based connection validator,
greatly decreasing memory consumtion
* _aquatic_udp_: don't return any response peers if announce event is stopped
* _aquatic_udp_: ignore requests with source port value of zero
* _aquatic_http_: don't return any response peers if announce event is stopped
* _aquatic_ws_: reduce size of various structs
* _aquatic_ws_: make TLS optional
* _aquatic_ws_: support reverse proxies
### Fixed
* Fail on unrecognized config keys
* Forbid unrecognized keys when parsing config files
* Fix warnings from invalid avx512 key included in `./scripts/env-native-cpu-without-avx-512`
* _aquatic_http_protocol_: explicity check for /scrape path
* _aquatic_http_protocol_: return NeedMoreData until headers are fully parsed
* _aquatic_http_protocol_: fix issues with ScrapeRequest::write and AnnounceRequest::write

24
Cargo.lock generated
View file

@ -1893,9 +1893,9 @@ dependencies = [
[[package]]
name = "once_cell"
version = "1.14.0"
version = "1.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2f7254b99e31cad77da24b08ebf628882739a608578bb1bcdfc1f9c21260d7c0"
checksum = "e82dad04139b71a90c080c8463fe0dc7902db5192d939bd0950f074d014339e1"
[[package]]
name = "oorandom"
@ -2114,9 +2114,9 @@ dependencies = [
[[package]]
name = "proc-macro2"
version = "1.0.43"
version = "1.0.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0a2ca2c61bc9f3d74d2886294ab7b9853abd9c1ad903a3ac7815c58989bb7bab"
checksum = "7bd7356a8122b6c4a24a82b278680c73357984ca2fc79a0f9fa6dea7dced7c58"
dependencies = [
"unicode-ident",
]
@ -2369,9 +2369,9 @@ dependencies = [
[[package]]
name = "serde"
version = "1.0.144"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860"
checksum = "728eb6351430bccb993660dfffc5a72f91ccc1295abaa8ce19b27ebe4f75568b"
dependencies = [
"serde_derive",
]
@ -2407,9 +2407,9 @@ dependencies = [
[[package]]
name = "serde_derive"
version = "1.0.144"
version = "1.0.145"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00"
checksum = "81fa1584d3d1bcacd84c277a0dfe21f5b0f6accf4a23d04d4c6d61f1af522b4c"
dependencies = [
"proc-macro2",
"quote",
@ -2761,18 +2761,18 @@ dependencies = [
[[package]]
name = "thiserror"
version = "1.0.35"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c53f98874615aea268107765aa1ed8f6116782501d18e53d08b471733bea6c85"
checksum = "0a99cb8c4b9a8ef0e7907cd3b617cc8dc04d571c4e73c8ae403d80ac160bb122"
dependencies = [
"thiserror-impl",
]
[[package]]
name = "thiserror-impl"
version = "1.0.35"
version = "1.0.36"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f8b463991b4eab2d801e724172285ec4195c650e8ec79b149e6c2a8e6dd3f783"
checksum = "3a891860d3c8d66fec8e73ddb3765f90082374dbaaa833407b904a94f1a7eb43"
dependencies = [
"proc-macro2",
"quote",

View file

@ -1,5 +1,4 @@
[workspace]
members = [
"aquatic",
"aquatic_common",
@ -18,6 +17,26 @@ members = [
"aquatic_ws_protocol",
]
[workspace.package]
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/greatest-ape/aquatic"
readme = "./README.md"
rust-version = "1.64"
[workspace.dependencies]
aquatic_common = { version = "0.2.0", path = "./aquatic_common" }
aquatic_http_protocol = { version = "0.2.0", path = "./aquatic_http_protocol" }
aquatic_http = { version = "0.2.0", path = "./aquatic_http" }
aquatic_toml_config = { version = "0.2.0", path = "./aquatic_toml_config" }
aquatic_toml_config_derive = { version = "0.2.0", path = "./aquatic_toml_config_derive" }
aquatic_udp_protocol = { version = "0.2.0", path = "./aquatic_udp_protocol" }
aquatic_udp = { version = "0.2.0", path = "./aquatic_udp" }
aquatic_ws_protocol = { version = "0.2.0", path = "./aquatic_ws_protocol" }
aquatic_ws = { version = "0.2.0", path = "./aquatic_ws" }
[patch.crates-io]
membarrier = { git = "https://github.com/glommer/membarrier-rs.git", branch = "issue-22" }

View file

@ -1,20 +1,21 @@
[package]
name = "aquatic"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "High-performance open BitTorrent tracker (UDP, HTTP, WebTorrent)"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["bittorrent", "torrent", "webtorrent"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[[bin]]
name = "aquatic"
[dependencies]
aquatic_common = { version = "0.2.0", path = "../aquatic_common" }
aquatic_http = { version = "0.2.0", path = "../aquatic_http" }
aquatic_udp = { version = "0.2.0", path = "../aquatic_udp" }
aquatic_ws = { version = "0.2.0", path = "../aquatic_ws" }
aquatic_common.workspace = true
aquatic_http.workspace = true
aquatic_udp.workspace = true
aquatic_ws.workspace = true
mimalloc = { version = "0.1", default-features = false }

View file

@ -1,12 +1,13 @@
[package]
name = "aquatic_common"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "aquatic BitTorrent tracker common code"
repository = "https://github.com/greatest-ape/aquatic"
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[lib]
name = "aquatic_common"
@ -15,7 +16,7 @@ name = "aquatic_common"
rustls = ["dep:rustls", "rustls-pemfile"]
[dependencies]
aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" }
aquatic_toml_config.workspace = true
ahash = "0.8"
anyhow = "1"

View file

@ -1,13 +1,14 @@
[package]
name = "aquatic_http"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "High-performance open BitTorrent tracker (HTTP over TLS)"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["http", "server", "peer-to-peer", "torrent", "bittorrent"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[lib]
name = "aquatic_http"
@ -16,9 +17,9 @@ name = "aquatic_http"
name = "aquatic_http"
[dependencies]
aquatic_common = { version = "0.2.0", path = "../aquatic_common", features = ["rustls", "glommio"] }
aquatic_http_protocol = { version = "0.2.0", path = "../aquatic_http_protocol" }
aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" }
aquatic_common = { workspace = true, features = ["rustls", "glommio"] }
aquatic_http_protocol.workspace = true
aquatic_toml_config.workspace = true
anyhow = "1"
cfg-if = "1"

View file

@ -248,17 +248,15 @@ impl Connection {
match Request::from_bytes(&self.request_buffer[..self.request_buffer_position]) {
Ok(request) => {
::log::debug!("received request: {:?}", request);
return Ok(Either::Right(request));
}
Err(RequestParseError::Invalid(err)) => {
::log::debug!("invalid request: {:?}", err);
let response = FailureResponse {
failure_reason: "Invalid request".into(),
};
::log::debug!("Invalid request: {:#}", err);
return Ok(Either::Left(response));
}
Err(RequestParseError::NeedMoreData) => {

View file

@ -344,8 +344,6 @@ pub fn upsert_peer_and_get_response_peers<I: Ip>(
valid_until,
};
::log::debug!("peer: {:?}", peer);
let ip_or_key = request
.key
.map(Either::Right)
@ -356,8 +354,6 @@ pub fn upsert_peer_and_get_response_peers<I: Ip>(
ip_or_key,
};
::log::debug!("peer map key: {:?}", peer_map_key);
let opt_removed_peer = match peer_status {
PeerStatus::Leeching => {
torrent_data.num_leechers += 1;
@ -372,8 +368,6 @@ pub fn upsert_peer_and_get_response_peers<I: Ip>(
PeerStatus::Stopped => torrent_data.peers.remove(&peer_map_key),
};
::log::debug!("opt_removed_peer: {:?}", opt_removed_peer);
match opt_removed_peer.map(|peer| peer.status) {
Some(PeerStatus::Leeching) => {
torrent_data.num_leechers -= 1;
@ -384,21 +378,23 @@ pub fn upsert_peer_and_get_response_peers<I: Ip>(
_ => {}
}
::log::debug!("peer request numwant: {:?}", request.numwant);
let response_peers = if let PeerStatus::Stopped = peer_status {
Vec::new()
} else {
let max_num_peers_to_take = match request.numwant {
Some(0) | None => config.protocol.max_peers,
Some(numwant) => numwant.min(config.protocol.max_peers),
};
let max_num_peers_to_take = match request.numwant {
Some(0) | None => config.protocol.max_peers,
Some(numwant) => numwant.min(config.protocol.max_peers),
extract_response_peers(
rng,
&torrent_data.peers,
max_num_peers_to_take,
peer_map_key,
Peer::to_response_peer,
)
};
let response_peers: Vec<ResponsePeer<I>> = extract_response_peers(
rng,
&torrent_data.peers,
max_num_peers_to_take,
peer_map_key,
Peer::to_response_peer,
);
(
torrent_data.num_seeders,
torrent_data.num_leechers,

View file

@ -1,21 +1,22 @@
[package]
name = "aquatic_http_load_test"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "BitTorrent (HTTP over TLS) load tester"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["http", "benchmark", "peer-to-peer", "torrent", "bittorrent"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[[bin]]
name = "aquatic_http_load_test"
[dependencies]
aquatic_common = { version = "0.2.0", path = "../aquatic_common", features = ["glommio"] }
aquatic_http_protocol = { version = "0.2.0", path = "../aquatic_http_protocol" }
aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" }
aquatic_common = { workspace = true, features = ["glommio"] }
aquatic_http_protocol.workspace = true
aquatic_toml_config.workspace = true
anyhow = "1"
futures-lite = "1"

View file

@ -1,11 +1,13 @@
[package]
name = "aquatic_http_private"
version = "0.2.0"
edition = "2021"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
license = "Apache-2.0"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["http", "benchmark", "peer-to-peer", "torrent", "bittorrent"]
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[lib]
name = "aquatic_http_private"
@ -14,9 +16,9 @@ name = "aquatic_http_private"
name = "aquatic_http_private"
[dependencies]
aquatic_common = { version = "0.2.0", path = "../aquatic_common", features = ["rustls"] }
aquatic_http_protocol = { version = "0.2.0", path = "../aquatic_http_protocol", features = ["axum"] }
aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" }
aquatic_common = { workspace = true, features = ["rustls"] }
aquatic_http_protocol = { workspace = true, features = ["axum"] }
aquatic_toml_config.workspace = true
anyhow = "1"
axum = { version = "0.5", default-features = false, features = ["headers", "http1", "matched-path", "original-uri"] }

View file

@ -1,13 +1,14 @@
[package]
name = "aquatic_http_protocol"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/greatest-ape/aquatic"
description = "HTTP BitTorrent tracker protocol"
keywords = ["http", "protocol", "peer-to-peer", "torrent", "bittorrent"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[lib]
name = "aquatic_http_protocol"

View file

@ -1,20 +1,21 @@
[package]
name = "aquatic_toml_config"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "Serialize toml with comments"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["toml"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[lib]
name = "aquatic_toml_config"
[dependencies]
toml = "0.5"
aquatic_toml_config_derive = { version = "0.2.0", path = "../aquatic_toml_config_derive" }
aquatic_toml_config_derive.workspace = true
[dev-dependencies]
serde = { version = "1.0", features = ["derive"] }

View file

@ -1,14 +1,15 @@
[package]
name = "aquatic_toml_config_derive"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "Serialize toml with comments"
repository = "https://github.com/greatest-ape/aquatic"
exclude = ["target"]
keywords = ["toml"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[lib]
proc-macro = true

View file

@ -1,14 +1,14 @@
[package]
name = "aquatic_udp"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "High-performance open UDP BitTorrent tracker"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["udp", "server", "peer-to-peer", "torrent", "bittorrent"]
readme = "../README.md"
rust-version = "1.62"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[lib]
name = "aquatic_udp"
@ -20,9 +20,9 @@ name = "aquatic_udp"
cpu-pinning = ["aquatic_common/hwloc"]
[dependencies]
aquatic_common = { version = "0.2.0", path = "../aquatic_common" }
aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" }
aquatic_udp_protocol = { version = "0.2.0", path = "../aquatic_udp_protocol" }
aquatic_common.workspace = true
aquatic_toml_config.workspace = true
aquatic_udp_protocol.workspace = true
anyhow = "1"
blake3 = "1"

View file

@ -157,8 +157,11 @@ fn handle_announce_request<I: Ip>(
peer_valid_until,
);
let response_peers =
torrent_data.extract_response_peers(rng, request.peer_id, max_num_peers_to_take);
let response_peers = if let PeerStatus::Stopped = peer_status {
Vec::new()
} else {
torrent_data.extract_response_peers(rng, request.peer_id, max_num_peers_to_take)
};
AnnounceResponse {
transaction_id: request.transaction_id,

View file

@ -1,20 +1,21 @@
[package]
name = "aquatic_udp_bench"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
repository = "https://github.com/greatest-ape/aquatic"
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[[bin]]
name = "aquatic_udp_bench"
[dependencies]
aquatic_common = { version = "0.2.0", path = "../aquatic_common" }
aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" }
aquatic_udp = { version = "0.2.0", path = "../aquatic_udp" }
aquatic_udp_protocol = { version = "0.2.0", path = "../aquatic_udp_protocol" }
aquatic_common.workspace = true
aquatic_toml_config.workspace = true
aquatic_udp.workspace = true
aquatic_udp_protocol.workspace = true
anyhow = "1"
crossbeam-channel = "0.5"

View file

@ -1,13 +1,14 @@
[package]
name = "aquatic_udp_load_test"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "BitTorrent (UDP) load tester"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["udp", "benchmark", "peer-to-peer", "torrent", "bittorrent"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[features]
cpu-pinning = ["aquatic_common/hwloc"]
@ -16,9 +17,9 @@ cpu-pinning = ["aquatic_common/hwloc"]
name = "aquatic_udp_load_test"
[dependencies]
aquatic_common = { version = "0.2.0", path = "../aquatic_common" }
aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" }
aquatic_udp_protocol = { version = "0.2.0", path = "../aquatic_udp_protocol" }
aquatic_common.workspace = true
aquatic_toml_config.workspace = true
aquatic_udp_protocol.workspace = true
anyhow = "1"
hashbrown = "0.12"

View file

@ -1,13 +1,14 @@
[package]
name = "aquatic_udp_protocol"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "UDP BitTorrent tracker protocol"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["udp", "protocol", "peer-to-peer", "torrent", "bittorrent"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[dependencies]
byteorder = "1"

View file

@ -1,13 +1,14 @@
[package]
name = "aquatic_ws"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "High-performance open WebTorrent tracker"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["webtorrent", "websocket", "peer-to-peer", "torrent", "bittorrent"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[lib]
name = "aquatic_ws"
@ -16,9 +17,9 @@ name = "aquatic_ws"
name = "aquatic_ws"
[dependencies]
aquatic_common = { version = "0.2.0", path = "../aquatic_common", features = ["rustls", "glommio"] }
aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" }
aquatic_ws_protocol = { version = "0.2.0", path = "../aquatic_ws_protocol" }
aquatic_common = { workspace = true, features = ["rustls", "glommio"] }
aquatic_toml_config.workspace = true
aquatic_ws_protocol.workspace = true
anyhow = "1"
async-tungstenite = "0.17"

View file

@ -1,21 +1,22 @@
[package]
name = "aquatic_ws_load_test"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "WebTorrent over TLS load tester"
repository = "https://github.com/greatest-ape/aquatic"
keywords = ["webtorrent", "websocket", "benchmark", "torrent", "bittorrent"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[[bin]]
name = "aquatic_ws_load_test"
[dependencies]
aquatic_common = { version = "0.2.0", path = "../aquatic_common", features = ["glommio"] }
aquatic_toml_config = { version = "0.2.0", path = "../aquatic_toml_config" }
aquatic_ws_protocol = { version = "0.2.0", path = "../aquatic_ws_protocol" }
aquatic_common = { workspace = true, features = ["glommio"] }
aquatic_toml_config.workspace = true
aquatic_ws_protocol.workspace = true
anyhow = "1"
async-tungstenite = "0.17"

View file

@ -1,14 +1,15 @@
[package]
name = "aquatic_ws_protocol"
version = "0.2.0"
authors = ["Joakim Frostegård <joakim.frostegard@gmail.com>"]
edition = "2021"
license = "Apache-2.0"
description = "WebTorrent tracker protocol"
repository = "https://github.com/greatest-ape/aquatic"
exclude = ["target"]
keywords = ["webtorrent", "protocol", "peer-to-peer", "torrent", "bittorrent"]
readme = "../README.md"
version.workspace = true
authors.workspace = true
edition.workspace = true
license.workspace = true
repository.workspace = true
readme.workspace = true
rust-version.workspace = true
[lib]
name = "aquatic_ws_protocol"

View file

@ -3,7 +3,7 @@
# Compile with target-cpu=native but without AVX512 features, since they
# decrease performance.
DISABLE_AVX512=$(rustc --print target-features | grep " avx512" |
DISABLE_AVX512=$(rustc --print target-features | grep " avx512" | grep -v "avx512fp16" |
awk '{print $1}' | sed 's/^/-C target-feature=-/' | xargs)
export RUSTFLAGS="-C target-cpu=native $DISABLE_AVX512"