ARG RUST_VERSION=1.71.0
ARG APP_NAME=project
FROM rust:${RUST_VERSION}-slim-bullseye AS build
ARG APP_NAME
WORKDIR /app
# Build the application.
# Leverage a cache mount to /usr/local/cargo/registry/
# for downloaded dependencies and a cache mount to /app/target/ for
# compiled dependencies which will speed up subsequent builds.
# Leverage a bind mount to the src directory to avoid having to copy the
# source code into the container. Once built, copy the executable to an
# output directory before the cache mounted /app/target is unmounted.
RUN --mount=type=bind,source=src,target=src \
--mount=type=bind,source=Cargo.toml,target=Cargo.toml \
--mount=type=bind,source=Cargo.lock,target=Cargo.lock \
--mount=type=cache,target=/app/target/ \
--mount=type=cache,target=/usr/local/cargo/registry/ \
<<EOF
set -e
cargo build --locked --release
cp ./target/release/$APP_NAME /bin/server
EOF
# FROM, Установка rust и прочих зависимостей
# ...
RUN cargo new /app
COPY app/Cargo.toml /app/
# This step compiles only our dependencies and saves them in a layer. This is the most impactful time savings
# Note the use of --mount=type=cache. On subsequent runs, we'll have the crates already downloaded
WORKDIR /app
RUN --mount=type=cache,target=/usr/local/cargo/registry cargo build --release
COPY ./app /app
# touch нужен, чтобы изменить дату изменения файла
RUN --mount=type=cache,target=/usr/local/cargo/registry \
set -e; \
touch /app/src/main.rs; \
cargo build --release;
let get_albums_response = api.request("video.getAlbums", &mut params).await.unwrap();
let mut items: Vec<&JsonValue> = get_albums_response["response"]["items"].members().collect();
items.sort_by(|a, b| a["title"].as_str().cmp(&b["title"].as_str()));
mod m01;
mod m02;
mod m03;
fn main() {
m01::f1();
m02::f2();
let (i, p) = m03::f3();
println!("i = {:?}", i);
println!("p = {:?}", p);
}
pub fn f1() {
let num: u8 = 12;
println!("num = {:?}", num);
}
pub fn f2() {
let s: String = "abc".to_string();
println!("s = {:?}", s);
}
pub fn f3() -> (u8, String) {
let i: u8 = 88;
let p: String = "xyz".to_string();
(i, p)
}
macro_rules! f4 {
() => {
let i: u8 = 88;
let p: String = "xyz".to_string();
}
}
macro_rules! f4 {
($a: ident, $b: ident) => {
let $a: u8 = 88;
let $b: String = "xyz".to_string();
}
}
fn main() {
f4!(i, p);
println!("{} {}", i, p);
}
1 - есть ли что-то быстрее, чем tokio
2 - правильно ли я использую tokio
3 - насколько хорошая с точки зрения производительности идея использовать Arc
4 - можно ли ускорить саму по себе структуру HashMap или только переписывать?
pub struct DashMap<K, V, S = RandomState> {
shift: usize,
shards: Box<[RwLock<HashMap<K, V, S>>]>,
hasher: S,
}
hashmap_no_capacity_format_key__3M
time: [1.4810 s 1.5362 s 1.5952 s]
hashmap_set_capacity_format_key__3M
time: [1.0688 s 1.0744 s 1.0804 s]
btree_format_key__3M time: [754.93 ms 843.10 ms 933.95 ms]
vec_set_apacity__3M time: [1.7122 ms 1.7309 ms 1.7655 ms]
dashmap_rayon_format_key__3M
time: [294.76 ms 303.70 ms 316.85 ms]
btree_known_key__3M time: [554.56 ms 556.18 ms 558.41 ms]
use std::{
collections::{BTreeMap, HashMap},
time::Instant,
};
use criterion::{black_box, criterion_group, criterion_main, Criterion};
fn hashmap_no_capacity_format_key(n: usize) -> HashMap<String, usize> {
let mut map = HashMap::new();
for i in 0..n {
let key = format!("key_{i}");
map.insert(key, i);
}
map
}
fn hashmap_set_capacity_format_key(n: usize) -> HashMap<String, usize> {
let mut map = HashMap::with_capacity(n + 1);
for i in 0..n {
let key = format!("key_{i}");
map.insert(key, i);
}
map
}
fn btreemap_format_key(n: usize) -> BTreeMap<String, usize> {
let mut map = BTreeMap::new();
for i in 0..n {
let key = format!("key_{i}");
map.insert(key, i);
}
map
}
fn vec_set_capacity(n: usize) -> Vec<usize> {
let mut vector = Vec::with_capacity(n);
for i in 0..n {
vector.push(i);
}
vector
}
fn btreemap_known_key(keys: impl Iterator<Item = (String, usize)>) -> usize {
let mut map = BTreeMap::new();
for (k, v) in keys {
map.insert(k, v);
}
map.len()
}
fn dashmap_rayon_format_key(n: usize) -> dashmap::DashMap<String, usize> {
use rayon::prelude::*;
let map = dashmap::DashMap::with_capacity(n);
(0..n).into_par_iter().for_each(|i| {
let key = format!("key_{i}");
map.insert(key, i);
});
map
}
fn bench(c: &mut Criterion) {
c.bench_function("hashmap_no_capacity_format_key__3M", |b| {
b.iter(|| hashmap_no_capacity_format_key(black_box(3_000_000)))
});
c.bench_function("hashmap_set_capacity_format_key__3M", |b| {
b.iter(|| hashmap_set_capacity_format_key(black_box(3_000_000)))
});
c.bench_function("btree_format_key__3M", |b| {
b.iter(|| btreemap_format_key(black_box(3_000_000)))
});
c.bench_function("vec_set_apacity__3M", |b| {
b.iter(|| vec_set_capacity(black_box(3_000_000)))
});
c.bench_function("dashmap_rayon_format_key__3M", |b| {
b.iter(|| dashmap_rayon_format_key(black_box(3_000_000)))
});
c.bench_function("btree_known_key__3M", |b| {
b.iter_custom(|times| {
let mut total = vec![];
for _ in 0..times {
let mut keys = Vec::with_capacity(3_000_000);
for i in 0..3_000_000 {
keys.push((format!("key_{i}"), i));
}
let start = Instant::now();
black_box(btreemap_known_key(black_box(keys.drain(..))));
total.push(start.elapsed());
}
total.iter().sum()
});
});
}
criterion_group! {
name = benches;
config = Criterion::default().sample_size(10);
targets = bench
}
criterion_main!(benches);
fn main() {
let funcs = {
// Можно использовать не FnOnce, а что-то другое. Например Fn или FnMut. Но в любом случае придётся использовать dyn, тк наша лямбда берёт что-то из окружающего контекста.
let mut funcs: Vec<Box<dyn FnOnce() -> usize>> = Vec::with_capacity(3);
for i in 0..3 {
let i_copy = i.clone(); // вообще clone() тут не нужен, тк usize реализует трейт Copy. Оставлено для примера
funcs.push(Box::new(move || i_copy));
}
funcs
};
for func in funcs {
let result = func();
println!("{result}");
}
}
#[derive(Copy, Clone, Debug)]
struct Something(usize);
impl Something {
fn value(&self) -> usize {
self.0
}
}
fn main() {
let items = {
let mut items = Vec::with_capacity(3);
for i in 0..3 {
items.push(Something(i));
}
items
};
for item in items {
let result = item.value();
println!("{result}");
}
}
.\rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain stable --profile default
RUSTUP_INIT_SKIP_EXISTENCE_CHECKS=yes
cargo build --offline
cargo fetch
или cargo vendor
cargo init
cargo add rand
cargo vendor
(с доступом в интернет).cargo/config.toml
с содержимым [source.crates-io]
replace-with = "vendored-sources"
[source.vendored-sources]
directory = "vendor"
fn main() {
let x: i32 = rand::random();
println!("{}", x);
}
cargo build --release --offline
(без доступа в интернет)
Особенно там, где был использован язык Си или С++
Наш Процессинговый Центр занимается разработкой финансовых систем, критичных к даунтайму и времени обработки. Изначально мы делали все свои продукты либо на чистом Си, либо на плюсах (C++14), однако пару лет назад мы переписали большой кусок нашего бэкенда на Rust, и нам настолько понравилось, что теперь все наши новые процессинговые сервисы пишутся на нём.
Мне бы хотелось видеть какое-то сравнение, что вот так стало сильно лучше и безопаснее, а вот было так написано изначально на оригинальном языке
ну тут все-равно unsafe
ну, нам еще нужен подсчет ссылок
Compiling playground v0.0.1 (/playground)
error[E0502]: cannot borrow `counter` as immutable because it is also borrowed as mutable
--> src/main.rs:11:30
|
7 | let mut increase = || {
| -- mutable borrow occurs here
8 | counter += INCR;
| ------- first borrow occurs due to use of `counter` in closure
...
11 | println!("counter = {}", counter);
| ^^^^^^^ immutable borrow occurs here
...
14 | increase();
| -------- mutable borrow later used here
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0502]: cannot borrow `counter` as immutable because it is also borrowed as mutable
--> src/main.rs:16:34
|
7 | let mut increase = || {
| -- mutable borrow occurs here
8 | counter += INCR;
| ------- first borrow occurs due to use of `counter` in closure
...
14 | increase();
| -------- mutable borrow later used here
15 |
16 | println!("counter = {}", counter);
| ^^^^^^^ immutable borrow occurs here
|
= note: this error originates in the macro `$crate::format_args_nl` which comes from the expansion of the macro `println` (in Nightly builds, run with -Z macro-backtrace for more info)
error[E0503]: cannot use `counter` because it was mutably borrowed
--> src/main.rs:18:12
|
7 | let mut increase = || {
| -- `counter` is borrowed here
8 | counter += INCR;
| ------- borrow occurs due to use of `counter` in closure
...
14 | increase();
| -------- borrow later used here
...
18 | if counter == STOP {
| ^^^^^^^ use of borrowed `counter`
Some errors have detailed explanations: E0502, E0503.
For more information about an error, try `rustc --explain E0502`.
error: could not compile `playground` due to 3 previous errors
fn chto_to(&self) -> impl StringAnalyzer;
fn lexing<T>(&self) -> T where T: StringAnalyzer;
pub trait NewTrait {
type AssociatedType: ExistingTrait;
fn function() -> Self::AssociatedType;
}
rustup update stable
mkdir cross_comp
cd cross_comp
cargo init --bin
cargo target add aarch64-unknown-linux-gnu
sudo apt install g++-aarch64-linux-gnu libc6-dev-arm64-cross
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc \
CC_aarch64_unknown_linux_gnu=aarch64-linux-gnu-gcc \
CXX_aarch64_unknown_linux_gnu=aarch64-linux-gnu-g++ \
cargo build --target=aarch64-unknown-linux-gnu
rustup update stable
mkdir cross_comp
cd cross_comp
cargo init --bin
cargo target add aarch64-unknown-linux-gnu
&'static str
(собственно то, что ты в panic и засунул)Err(err) => {
println!("{}", err.is::<&'static str>());
let value = err.downcast::<&'static str>().unwrap();
println!("{}", value); // Выводит строку failed to spawn
}
Или возвращатьBoxплохая идея, а нужно засовывать другие ошибки внутрь своего кастомного типа?