Привет, Хабр! Работая с Javascript/Typescript, я давно заметил, что асинхронный API медленнее аналогичного синхронного, и даже знал, что так и должно быть.
Но в последнем проекте узким местом стала асинхронная работа с файловой системой, и я занялся измерениями.
Известно, что Ждите можно использовать только внутри функций или блоков асинхронный , а это означает, что если наш самый низкий уровень API является асинхронным, нам придется использовать асинхронный/ожидание практически везде, даже там, где это явно не нужно.
Например, мы пишем сервисную функцию, которая извлекает объект из хранилища по ключу.
В качестве хранилища мы можем использовать файл, базу данных, микросервис, то есть медленный источник с асинхронным интерфейсом.
Для повышения производительности внутри нашей функции мы кэшируем ранее полученные объекты (помещаем их в карта ).
По мере работы программы реальных обращений к хранилищу становится все меньше, объекты обслуживаются из быстрого кэша, но интерфейс функции остается асинхронным! Какую цену мне придется заплатить за каждый асинхронный вызов? Результаты испытаний удручают. Давайте возьмем простую функцию и назовем ее асинхронный , и мы будем вызывать его в цикле, измеряя общее время и сравнивая его с аналогичным синхронным кодом.
Для сравнения синтаксиса я предоставляю полные тексты на 3-х языках.
Машинопись ( Дено )
Синхронный кодАсинхронный код:const b = Date.now() let j = 0.0 for (let i = 0; i < 1_000_000_000; i++) { j += f(i) } console.log(j + ', ' + (Date.now() - b)/1000 + 's') function f(i: number): number { return i / 3.1415926 }
(async () => {
const b = Date.now()
let j = 0.0
for (let i = 0; i < 1_000_000_000; i++) {
j += await f(i)
}
console.log(j + ', ' + (Date.now() - b)/1000 + 's')
})()
async function f(i: number): Promise<number> {
return i / 3.1415926
}
С# (.
NET Core) Синхронный код using System;
class App {
static void Main(string[] args) {
var b = DateTime.Now;
var j = 0.0;
for (var i = 0L; i < 1_000_000_000L; i++) {
j += f(i);
}
Console.WriteLine(j + ", " + (DateTime.Now - b).
TotalMilliseconds / 1000 + "s");
}
static double f(long i) {
return i / 3.1415926;
}
}
Асинхронный код: using System;
using System.Threading.Tasks;
class App {
static async Task Main(string[] args) {
var b = DateTime.Now;
var j = 0.0;
for (var i = 0L; i < 1_000_000_000L; i++) {
j += await f(i);
}
Console.WriteLine(j + ", " + (DateTime.Now - b).
TotalMilliseconds / 1000 + "s");
}
static async Task<double> f(long i) {
return i / 3.1415926;
}
}
Ржавчина
Синхронный код fn main() {
let tbegin = std::time::SystemTime::now();
let mut j = 0.0;
for i in 0.1_000_000_000i64 {
j += f(i);
}
println!("{:?}, {:?}", j, tbegin.elapsed().
unwrap());
}
fn f(i: i64) -> f64 {
return i as f64 / 3.1415926
}
Асинхронный код:
//[dependencies]
//futures = "0.3"
use futures::executor::block_on;
fn main() {
block_on(async {
let tbegin = std::time::SystemTime::now();
let mut j = 0.0;
for i in 0.1_000_000_000i64 {
j += f(i).
await;
}
println!("{:?}, {:?}", j, tbegin.elapsed().
unwrap());
});
}
async fn f(i: i64) -> f64 {
return i as f64 / 3.1415926
}
Результаты
Язык | Синхронный код (сек.
) |
Асинхронный код (сек.
) |
%% потерь |
Машинопись | 7.48 | 173 | 23 раза |
С# | 7.46 | 76.2 | 10 раз |
Ржавчина | 7.45 | 19.2 | 2,6 раза |
Интересно, какое применение асинхронный/ожидание В большинстве случаев (и даже рекламируемых) стоимость асинхронного вызова просто непомерно высока.
Руст как всегда выиграл гонку, возможно, это главная причина, почему ВЕБ-фреймворк , написанное на нем, стабильно побеждает ориентиры Это не первый год.
Краткое содержание
Не зря разработчики Java не торопись добавление асинхронного синтаксиса непосредственно в язык, и хотя я считаю, что async/await — отличная абстракция, нам необходимо понимать масштаб накладных расходов при его использовании.ПС Спасибо всем, кто указал на возможность ускорения кода за счет кэширования задач/обещаний (вместо кэширования результатов), а также на то, что в C# есть отличная возможность инструмент , который просто решает мою проблему.
Теги: #программирование #Высокая производительность #C++ #JavaScript #Rust #node.js #async/await #бенчмаркинг #нулевая стоимость
-
Домашняя Сеть — Обмен Файлами Стал Проще
19 Oct, 24 -
Егэ – Один Плюс И Два Минуса
19 Oct, 24 -
Никон – Приятные Слухи
19 Oct, 24 -
Обзор Реализаций Округления В Go
19 Oct, 24 -
Непонимание Прошлого
19 Oct, 24 -
W3C Выпускает «Требования К Виджетам 1.0»
19 Oct, 24