Optimizing Performance in TypeScript for I/O-Bound and CPU-Bound Tasks

GeminiHendo
Sign in to confirm0 confirmations

Question

How can you optimize performance in TypeScript applications by addressing I/O-bound and CPU-bound tasks to prevent bottlenecks and improve overall responsiveness?

Answer

To optimize performance in TypeScript, it's crucial to differentiate between I/O-bound and CPU-bound tasks. I/O-bound tasks, such as network requests or file operations, should leverage non-blocking concurrency techniques like using Promise.all for parallel execution or implementing batching/throttling for numerous requests. CPU-bound tasks, involving heavy computations, should be offloaded to separate threads using worker threads in Node.js or Web Workers in the browser to keep the main thread responsive.

typescript
async function fetchUserDataBad(userIds: string[]) {
  const results = [];
  for (const id of userIds) {
    const user = await fetch(`/api/user/${id}`); // Blocks the loop
    results.push(await user.json());
  }
  return results;
}
typescript
async function fetchUserDataGood(userIds: string[]) {
  const promises = userIds.map(async (id) => {
    const res = await fetch(`/api/user/${id}`);
    return res.json();
  });
  
  return await Promise.all(promises); // Waits for all to finish concurrently
}
typescript
import { Worker } from 'worker_threads';
import { resolve } from 'path';

function runHeavyCpuTask(data: any): Promise<any> {
  return new Promise((resolve, reject) => {
    // Spin up the worker file
    const worker = new Worker('./worker.js', { workerData: data });
    
    worker.on('message', resolve);
    worker.on('error', reject);
    worker.on('exit', (code) => {
      if (code !== 0) reject(new Error(`Worker stopped with exit code ${code}`));
    });
  });
}
typescript
import { parentPort, workerData } from 'worker_threads';

// Heavy CPU work goes here
function heavyCalculation(size: number) {
  let count = 0;
  for (let i = 0; i < size * size; i++) {
    count += Math.sqrt(i);
  }
  return count;
}

const result = heavyCalculation(workerData.matrixSize);

// Send data back to main thread
parentPort?.postMessage(result);
typescriptperformanceio-boundcpu-boundconcurrencyi/o