← Назад к вопросам

Как оценить быстродействие приложения на Node.js?

1.8 Middle🔥 191 комментариев
#Node.js и JavaScript#Кэширование и производительность

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Оценка быстродействия Node.js приложения

Производительность — это не один метрик, а комплекс измерений. Расскажу о всех уровнях анализа:

1. Основные метрики производительности

Response Time (Latency):

  • Время ответа на запрос
  • Percentiles: p50, p95, p99 (более важны, чем average)
  • Чем ниже, тем лучше

Throughput (RPS):

  • Requests Per Second — сколько запросов в секунду обрабатываешь
  • Растёт с оптимизацией

Memory Usage:

  • Базовое потребление памяти
  • Утечки (memory leaks)
  • Garbage Collection паузы

CPU Usage:

  • Сколько процессорных мощностей требует приложение
  • Связано с Event Loop

2. Node.js встроенные tools

Простое логирование времени:

const startTime = Date.now();
await someAsyncOperation();
const duration = Date.now() - startTime;
console.log(`Operation took ${duration}ms`);

// ИЛИ более элегантно
console.time('operationName');
await someAsyncOperation();
console.timeEnd('operationName');
// Output: operationName: 1234ms

Встроенный profiler:

node --prof app.js
node --prof-process isolate-*.log > processed.txt

Inspector API (для real-time профилирования):

const inspector = require('inspector');

const session = new inspector.Session();
session.connect();

session.post('Profiler.enable', () => {
  session.post('Profiler.start', () => {
    // Твой код
    setTimeout(() => {
      session.post('Profiler.stop', (err, { profile }) => {
        console.log(JSON.stringify(profile, null, 2));
        session.disconnect();
      });
    }, 5000);
  });
});

3. Нагрузочное тестирование

Apache Bench:

ab -n 10000 -c 100 http://localhost:3000/

wrk (профессиональный инструмент):

# 4 потока, 100 соединений, 30 секунд
wrk -t4 -c100 -d30s http://localhost:3000/

# С кастомным скриптом
wrk -t4 -c100 -d30s -s script.lua http://localhost:3000/

k6 (современный инструмент):

import http from 'k6/http';
import { check, sleep } from 'k6';

export let options = {
  stages: [
    { duration: '2m', target: 100 },  // Рамп-ап
    { duration: '5m', target: 100 },  // Стабилизация
    { duration: '2m', target: 0 },    // Рамп-даун
  ],
};

export default function() {
  let res = http.get('http://localhost:3000/');
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 500ms': (r) => r.timings.duration < 500,
  });
  sleep(1);
}

4. Memory Profiling

Найти утечки памяти:

const v8 = require('v8');
const fs = require('fs');

// Снимок памяти в начале
const snapshot1 = v8.writeHeapSnapshot();

// После операции
await runOperations();

// Снимок памяти в конце
const snapshot2 = v8.writeHeapSnapshot();

// Анализируешь в Chrome DevTools
// chrome://inspect -> Memory -> Load heap snapshots

Мониторинг памяти:

const formatBytes = (bytes) => {
  return (bytes / 1024 / 1024).toFixed(2) + ' MB';
};

setInterval(() => {
  const usage = process.memoryUsage();
  console.log('Memory Usage:');
  console.log(`  RSS: ${formatBytes(usage.rss)}`);
  console.log(`  Heap Total: ${formatBytes(usage.heapTotal)}`);
  console.log(`  Heap Used: ${formatBytes(usage.heapUsed)}`);
  console.log(`  External: ${formatBytes(usage.external)}`);
}, 5000);

5. CPU Profiling

Найти bottleneck:

node --prof app.js
node --prof-process isolate-*-v8.log > profile.txt
cat profile.txt | grep -A 5 'Summary'

Chrome DevTools для профилирования:

node --inspect-brk app.js
# Открываешь chrome://inspect
# Performance tab -> Record

6. APM Tools (для production мониторинга)

New Relic:

require('newrelic');
const express = require('express');
const app = express();
// New Relic автоматически будет профилировать

DataDog:

const tracer = require('dd-trace').init();
const express = require('express');

Prometheus + Grafana:

const promClient = require('prom-client');

const httpDuration = new promClient.Histogram({
  name: 'http_request_duration_ms',
  help: 'Duration of HTTP requests in ms',
  buckets: [0.1, 5, 15, 50, 100, 500],
});

app.use((req, res, next) => {
  const start = Date.now();
  res.on('finish', () => {
    const duration = Date.now() - start;
    httpDuration.observe(duration);
  });
  next();
});

app.get('/metrics', async (req, res) => {
  res.set('Content-Type', promClient.register.contentType);
  res.end(await promClient.register.metrics());
});

7. Типичные проблемы и решения

Проблема 1: Event Loop блокируется

// ПЛОХО: синхронная операция
const data = fs.readFileSync('large-file.json');

// ХОРОШО: асинхронная
const data = await fs.promises.readFile('large-file.json');

// Мониторинг Event Loop lag
const lag = require('event-loop-lag');
console.log(`Event loop lag: ${lag()}ms`);

Проблема 2: N+1 queries

// ПЛОХО
const users = await User.find();
for (const user of users) {
  user.posts = await Post.find({ userId: user.id });
}

// ХОРОШО
const users = await User.find().populate('posts');

Проблема 3: Неоптимизированные SQL queries

// Включи query logging
const queryDuration = new promClient.Histogram({
  name: 'db_query_duration_ms',
  help: 'Database query duration',
  buckets: [10, 50, 100, 500, 1000],
});

db.on('query', (sql) => {
  console.time(sql);
});
db.on('query-done', (sql, duration) => {
  queryDuration.observe(duration);
  if (duration > 1000) {
    logger.warn('Slow query', { sql, duration });
  }
});

8. Чеклист производительности

  • Базовые метрики залогированы (response time, memory, CPU)
  • Нагрузочное тестирование проведено
  • Memory leaks найдены и исправлены
  • Slow queries оптимизированы (с EXPLAIN)
  • Event Loop не блокируется
  • Используется caching (Redis для часто запрашиваемых данных)
  • Connection pooling настроен
  • Образы Docker оптимизированы

Итог

Производительность — это процесс, не событие. Измеряй постоянно, профилируй регулярно, мониторь в production. Маленькие оптимизации, сделанные на ранних стадиях, дают 10x результат.

Как оценить быстродействие приложения на Node.js? | PrepBro