メインコンテンツまでスキップ

Cursor でのコードパフォーマンス最適化

Code Performance Optimization in Cursor

パフォーマンスは後から考えることではありません。それはモダンなアプリケーションの中核的な要件です。Cursor は AI 駆動の IDE エディタであり、パフォーマンス最適化を反応的なデバッグ作業から能動的な開発プラクティスへと変換します。このガイドでは、Cursor 環境でのプロファイリングテクニック、ボトルネック検出、AI アシストによる高速化のリファクタリング、およびメモリ最適化戦略を探ります。

Cursor でのパフォーマンス最適化入門​

Cursor は AI 機能をエディタに直接統合し、開発者がデプロイ後ではなく記述段階でパフォーマンス問題を特定できるようにします。エディタはコードパターンを分析し、アルゴリズムの改善を提案し、実装の計算複雑性を理解するのを助けます。

Cursor での主要なパフォーマンス最適化ワークフローには以下が含まれます:

  • 関数とアルゴリズムのリアルタイム複雑性分析
  • より高速なデータ構造の AI 駆動提案
  • ボトルネック可視化のためのプロファイリングツール統合
  • ループ最適化と非同期パターンの自動リファクタリング
  • メモリリーク検出とヒープ分析ガイダンス

このガイドでは、JavaScript/TypeScript と基本的なアルゴリズムの概念に精通していることを前提としています。すべての例は TypeScript で記述され、Node.js 環境で実行されます。

パフォーマンスワークスペースのセットアップ​

最適化の前に、Cursor がコードを効果的に分析できる構造化された環境が必要です。プロジェクトを整理して、本番コード、ベンチマーク、およびプロファイリングスクリプトを分離します。

Cursor ワークスペースで以下の構造を作成します:

src/
algorithms/
search.ts
sort.ts
dataProcessing.ts
benchmarks/
search.bench.ts
sort.bench.ts
profiling/
cpu-profile.ts
memory-profile.ts

必要なベンチマークおよびプロファイリングライブラリをインストールします:

npm install -D benchmark autocannon clinic
npm install -D @types/benchmark

慣習的に構造化されると、Cursor の AI は各ディレクトリの目的を理解します。benchmarks フォルダー内のファイルを開くと、エディタは自動的にベンチマークテンプレートと比較パターンを提案します。

ヒント

Cursor の AI に「配列検索実装を比較するベンチマークセットアップを生成してください」と尋ねると、統計レポート付きの完全な Benchmark.js スイートが作成されます。

プロファイリングとボトルネック検出​

コードが実行時間の大部分を費やしている場所を特定することは、最適化への第一歩です。Cursor は、プロファイリングツールのセットアップと結果の解釈を助けます。

Node.js を使用した CPU プロファイリング​

Node.js は --cpu-prof フラグを通じて組み込みの CPU プロファイリング機能を備えています。Cursor のターミナル統合により、これらのプロファイルをシームレスに実行でき、AI は生成された .cpuprofile ファイルの解釈を助けます。

profiling/cpu-profile.ts にプロファイリングスクリプトを作成します:

function slowAlgorithm(n: number): number {
let sum = 0;
for (let i = 0; i < n; i++) {
for (let j = 0; j < n; j++) {
sum += i * j;
}
}
return sum;
}

function optimizedAlgorithm(n: number): number {
// 数学的最適化:0 から n-1 までの i の合計は n(n-1)/2
const sumI = (n * (n - 1)) / 2;
const sumJ = (n * (n - 1)) / 2;
return sumI * sumJ;
}

console.time('slow');
slowAlgorithm(10000);
console.timeEnd('slow');

console.time('optimized');
optimizedAlgorithm(10000);
console.timeEnd('optimized');

Cursor の統合ターミナルからプロファイラーを実行します:

node --cpu-prof profiling/cpu-profile.ts

実行後、生成された .cpuprofile ファイルを Chrome DevTools に読み込むか、Cursor の AI を使用して分析します。プロファイルファイルを選択して、「この CPU プロファイルのボトルネックを特定し、最適化を提案してください」と尋ねると、Cursor はホットパスをハイライトし、具体的な改善を推奨します。

Clinic.js を使用した視覚的プロファイリング​

Clinic.js は、Cursor のファイル分析と組み合わせると特に効果的な視覚的プロファイリングツールを提供します。Clinic.js をインストールして設定します:

npm install -D clinic

API サーバーをプロファイリングするスクリプトを作成します:

import { createServer } from 'http';

const server = createServer((req, res) => {
const data = new Array(100000).fill(0).map((_, i) => ({
id: i,
value: Math.random(),
}));

// 非効率なフィルタリング
const filtered = data.filter((item) => item.value > 0.5);

res.writeHead(200, { 'Content-Type': 'application/json' });
res.end(JSON.stringify({ count: filtered.length }));
});

server.listen(3000, () => {
console.log('Server running on port 3000');
});

Clinic.js の Doctor ツールを実行します:

npx clinic doctor -- node profiling/server.ts

出力には、イベントループのレイテンシ、CPU 使用率、およびメモリ消費のグラフが含まれます。生成された HTML レポートをブラウザで開き、Cursor の AI に「この Clinic.js レポートに基づいて、主なパフォーマンス問題は何ですか?どうやって修正しますか?」と尋ねて洞察を共有します。

警告

開発環境と本番環境の間で、プロファイリング結果は大きく異なる可能性があります。変更をデプロイする前に、常に Autocannon や k6 などのツールを使用して、本番のような負荷の下で最適化を検証してください。

速度のための AI リファクタリング​

Cursor の AI リファクタリング機能は、パフォーマンス最適化に特に強力です。エディタはアルゴリズムを書き換え、より良いデータ構造を提案し、コードの正確性を維持しながら操作を並列化できます。

アルゴリズムの複雑性削減​

最も影響力のある最適化の一つは、時間複雑性の削減です。Cursor の AI は一般的なパターンを認識し、数学的に等価ですが計算コストが低い代替案を提案します。

この非効率な配列処理関数を考えてみましょう:

function findDuplicates(items: string[]): string[] {
const duplicates: string[] = [];
for (let i = 0; i < items.length; i++) {
for (let j = i + 1; j < items.length; j++) {
if (items[i] === items[j] && !duplicates.includes(items[i])) {
duplicates.push(items[i]);
}
}
}
return duplicates;
}

この関数を Cursor で選択し、AI チャットで「より良い時間複雑性のためにこの関数をリファクタリングしてください」とプロンプトします。AI は最適化バージョンを生成します:

function findDuplicatesOptimized(items: string[]): string[] {
const seen = new Set<string>();
const duplicates = new Set<string>();

for (const item of items) {
if (seen.has(item)) {
duplicates.add(item);
} else {
seen.add(item);
}
}

return Array.from(duplicates);
}

複雑性は O(n³) から O(n) に低下し、大規模なデータセットにとって劇的な改善です。Cursor は変換を説明し、Set データ構造がネストされたループと配列包含チェックよりも適切である理由を強調します。

非同期操作の最適化​

モダンなアプリケーションは、非同期操作に大きく依存しています。Cursor の AI は、開発者が見落とす可能性のある並列化とバッチ処理の機会を特定します。

以下は、時間を浪費する順次非同期パターンです:

async function fetchUserData(userIds: string[]) {
const results = [];
for (const id of userIds) {
const user = await fetch(`/api/users/${id}`);
const posts = await fetch(`/api/users/${id}/posts`);
results.push({ user: await user.json(), posts: await posts.json() });
}
return results;
}

Cursor にこの関数を最適化するように依頼します。AI は以下を生成します:

async function fetchUserDataOptimized(userIds: string[]) {
return Promise.all(
userIds.map(async (id) => {
const [userResponse, postsResponse] = await Promise.all([
fetch(`/api/users/${id}`),
fetch(`/api/users/${id}/posts`),
]);

const [user, posts] = await Promise.all([
userResponse.json(),
postsResponse.json(),
]);

return { user, posts };
})
);
}

このバージョンは、すべての ID にわたってユーザーと投稿のリクエストを並列化し、総実行時間を O(n * sequential_delay) からおおよそ O(max_single_request_time) に削減します。

ヒント

Cursor のインラインディフビューを使用して、元のコードとリファクタリングされたコードを並べて比較します。これにより、変換を理解し、エラーハンドリング要件が保持されていることを確認できます。

メモリ最適化戦略​

メモリリークと過度の割り当ては、静かなパフォーマンスキラーです。Cursor は、問題のあるパターンを特定し、メモリ効率の良い代替案を実装するのを助けます。

メモリリークの検出​

メモリリークは、ガベージコレクションを妨げる意図しない参照から発生することがよくあります。Cursor の AI は、クリアされていないタイマー、イベントリスナー、およびクロージャキャプチャなどの一般的なリークパターンを認識します。

React のようなコンポーネントでのこのリークパターンを考えてみましょう:

class DataProvider {
private listeners: Set<(data: any) => void> = new Set();
private intervalId: NodeJS.Timeout | null = null;

startPolling() {
this.intervalId = setInterval(() => {
this.fetchData();
}, 5000);
}

addListener(callback: (data: any) => void) {
this.listeners.add(callback);
}

private fetchData() {
fetch('/api/data')
.then((res) => res.json())
.then((data) => {
this.listeners.forEach((listener) => listener(data));
});
}
}

このコードを選択し、Cursor に「このクラスのメモリリークを特定し、修正されたバージョンを提供してください」と尋ねます。AI は intervalId がクリアされず、リスナーが削除されないことを指摘し、以下を生成します:

class DataProvider {
private listeners: Set<(data: any) => void> = new Set();
private intervalId: NodeJS.Timeout | null = null;
private abortController: AbortController | null = null;

startPolling() {
this.stopPolling();
this.abortController = new AbortController();
this.intervalId = setInterval(() => {
this.fetchData();
}, 5000);
}

stopPolling() {
if (this.intervalId) {
clearInterval(this.intervalId);
this.intervalId = null;
}
if (this.abortController) {
this.abortController.abort();
this.abortController = null;
}
}

addListener(callback: (data: any) => void) {
this.listeners.add(callback);
return () => {
this.listeners.delete(callback);
};
}

private fetchData() {
if (!this.abortController) return;

fetch('/api/data', { signal: this.abortController.signal })
.then((res) => res.json())
.then((data) => {
this.listeners.forEach((listener) => listener(data));
})
.catch((err) => {
if (err.name !== 'AbortError') {
console.error('Fetch error:', err);
}
});
}

destroy() {
this.stopPolling();
this.listeners.clear();
}
}

改善されたバージョンには、適切なクリーンアップメソッド、購読解除関数の返却、および進行中のリクエストをキャンセルする AbortController の使用が含まれています。

効率的なデータ構造​

適切なデータ構造の選択は、メモリ使用量に深い影響を与えます。Cursor の AI は、非効率なパターンを検出すると代替案を提案します。

頻繁なメンバーシップテストには、Array の代わりに Set を使用します:

// 非効率:O(n) ルックアップ、大規模配列の高いメモリオーバーヘッド
const userIdsArray: string[] = ['user-1', 'user-2', 'user-3'];
function isAuthorizedArray(userId: string): boolean {
return userIdsArray.includes(userId);
}

// 効率的:O(1) ルックアップ、最適化されたメモリレイアウト
const userIdsSet: Set<string> = new Set(['user-1', 'user-2', 'user-3']);
function isAuthorizedSet(userId: string): boolean {
return userIdsSet.has(userId);
}

連続した範囲を持つ大規模な数値配列の場合、型付き配列を検討してください:

// 標準配列:柔軟だがメモリ集約型
const scores: number[] = new Array(1000000).fill(0);

// 型付き配列:固定型、コンパクトなメモリ、より高速なアクセス
const scoresTyped = new Int32Array(1000000);
警告

型付き配列には固定長と均質型があります。混合型のコレクションや、明示的なバッファ管理なしに動的なサイズ変更が必要な場合に使用しないでください。

最適化のベンチマーク​

リファクタリング後、厳密なベンチマークにより、変更が実際にパフォーマンスを改善することを検証します。Cursor は、統計的に有意義なベンチマークを作成するのを助けます。

信頼できるベンチマークの作成​

Benchmark.js ライブラリを使用して実装を比較します:

import Benchmark from 'benchmark';

const suite = new Benchmark.Suite();

const testData = new Array(10000).fill(0).map(() =>
Math.random().toString(36).substring(7)
);

suite
.add('findDuplicates#original', () => {
const duplicates: string[] = [];
for (let i = 0; i < testData.length; i++) {
for (let j = i + 1; j < testData.length; j++) {
if (testData[i] === testData[j] && !duplicates.includes(testData[i])) {
duplicates.push(testData[i]);
}
}
}
})
.add('findDuplicates#optimized', () => {
const seen = new Set<string>();
const duplicates = new Set<string>();
for (const item of testData) {
if (seen.has(item)) {
duplicates.add(item);
} else {
seen.add(item);
}
}
})
.on('cycle', (event: Benchmark.Event) => {
console.log(String(event.target));
})
.on('complete', function (this: Benchmark.Suite) {
console.log('Fastest is ' + this.filter('fastest').map('name'));
})
.run({ async: true });

このベンチマークを Cursor のターミナルで実行し、出力を AI と共有します。「これらのベンチマーク結果を解釈し、最適化が統計的に有意かどうかを判断してください」と尋ねると、Cursor は ops/second メトリクス、誤差の範囲、およびサンプルサイズの考慮事項を説明します。

API の負荷テスト​

サーバーサイドの最適化には、変更の前後で Autocannon を使用してリクエストスループットを測定します:

npx autocannon -c 100 -d 30 http://localhost:3000/api/data

ベースライン結果をリポジトリに保存し、各最適化パス後に比較します。Cursor の AI は Autocannon JSON 出力を解析し、レイテンシパーセンタイルとスループットの改善を要約できます。

データベースクエリの最適化​

データベースクエリは、パフォーマンスボトルネックの一般的な原因です。Cursor の AI は、クエリパターンを分析し、インデックス戦略、クエリの書き換え、およびキャッシュアプローチを提案します。

低速クエリの分析​

Prisma や生の SQL を使用する場合、Cursor は非効率なクエリの特定を助けることができます。この Prisma クエリを考えてみましょう:

const users = await prisma.user.findMany({
include: {
posts: {
include: {
comments: true,
tags: true,
},
},
},
});

Cursor の AI は、深くネストされた include を潜在的なパフォーマンス問題としてフラグを立てます。以下を提案します:

// 返されるフィールドを select で制限
const users = await prisma.user.findMany({
select: {
id: true,
name: true,
posts: {
select: {
id: true,
title: true,
published: true,
},
where: { published: true },
take: 10,
orderBy: { createdAt: 'desc' },
},
},
take: 50,
});

最適化されたバージョンは、データ転送を削減し、データベースレベルのフィルタリングを活用し、ページネーションを実装します。

ヒント

Cursor に「リゾルバ内のクエリパターンに基づいて、この Prisma スキーマのデータベースインデックスを提案してください」と尋ねると、AI はクエリを分析し、フィルタリングおよびソート条件に一致する複合インデックスを推奨します。

結論​

Cursor でのパフォーマンス最適化は、プロファイリングツール、AI 駆動のリファクタリング、および厳密なベンチマークを組み合わせた統合体験です。エディタの機能を活用することで、ボトルネックをより早く特定し、最適化をより速く実装し、改善を自信を持って検証できます。

このガイドの重要なポイント:

  • 最適化の前にプロファイリングを行い、実際のボトルネックを対象にしていることを確認する
  • Cursor の AI を使用してアルゴリズムをリファクタリングし、複雑性を削減する
  • 可能な場合は非同期操作を並列化し、リクエストをバッチ処理する
  • メモリリークを防ぐために適切なクリーンアップを実装する
  • すべての最適化をベンチマークして、その影響を検証する
  • 選択的なフィールドとページネーションでデータベースクエリを最適化する

これらのテクニックを使用すると、アプリケーションはユーザーが期待する速度と応答性を提供しながら、Cursor IDE 内でクリーンでメンテナンス可能なコードを維持します。