Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion perf-tests/baselines.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": 1,
"updatedAt": "2026-04-09T02:30:22.000Z",
"updatedAt": "2026-04-13T19:49:01.577Z",
"scenarios": {
"cold-startup-time": {
"wallClockMs": 927.553249999999,
Expand All @@ -21,6 +21,41 @@
"wallClockMs": 1119.9,
"cpuTotalUs": 2100,
"timestamp": "2026-04-09T02:30:22.000Z"
},
"long-conversation": {
"wallClockMs": 4199.5024319999975,
Comment thread
cynthialong0-0 marked this conversation as resolved.
Outdated
"cpuTotalUs": 292959,
"timestamp": "2026-04-11T01:52:23.183Z"
},
"long-conversation-resume": {
"wallClockMs": 2807.285507000008,
"cpuTotalUs": 21912,
"timestamp": "2026-04-13T19:48:10.905Z"
},
"long-conversation-typing": {
"wallClockMs": 339.29195900000923,
"cpuTotalUs": 10295,
"timestamp": "2026-04-13T19:48:24.011Z"
},
"long-conversation-execution": {
"wallClockMs": 247.3171299999958,
"cpuTotalUs": 3583,
"timestamp": "2026-04-13T19:48:36.640Z"
},
"long-conversation-scrolling": {
"wallClockMs": 210.18672699999297,
"cpuTotalUs": 7911,
"timestamp": "2026-04-13T18:32:14.226Z"
},
"long-conversation-terminal-scrolling": {
"wallClockMs": 207.54268199999933,
"cpuTotalUs": 6390,
"timestamp": "2026-04-13T19:48:49.110Z"
},
"long-conversation-alternate-scrolling": {
"wallClockMs": 207.34147999998822,
"cpuTotalUs": 6135,
"timestamp": "2026-04-13T19:49:01.577Z"
}
}
}
228 changes: 225 additions & 3 deletions perf-tests/perf-usage.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,13 @@ import { describe, it, beforeAll, afterAll } from 'vitest';
import { TestRig, PerfTestHarness } from '@google/gemini-cli-test-utils';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import { existsSync, readFileSync } from 'node:fs';
import {
existsSync,
readFileSync,
mkdirSync,
copyFileSync,
writeFileSync,
} from 'node:fs';

const __dirname = dirname(fileURLToPath(import.meta.url));
const BASELINES_PATH = join(__dirname, 'baselines.json');
Expand Down Expand Up @@ -165,7 +171,7 @@ describe('CPU Performance Tests', () => {
const snapshot = await harness.measureWithEventLoop(
'high-volume-output',
async () => {
const runResult = await rig.run({
await rig.run({
args: ['Generate 1M lines of output'],
timeout: 120000,
env: {
Expand All @@ -176,7 +182,6 @@ describe('CPU Performance Tests', () => {
DEBUG: 'true',
},
});
console.log(` Child Process Output:`, runResult);
},
);

Expand Down Expand Up @@ -266,4 +271,221 @@ describe('CPU Performance Tests', () => {
harness.assertWithinBaseline(result);
}
});

describe('long-conversation', () => {
let rig: TestRig;
const identifier = 'perf-long-conversation';
const SESSION_ID =
'anonymous_unique_id_577296e0eee5afecdcec05d11838e0cd1a851cd97a28119a4a876b11';
const LARGE_CHAT_SOURCE = join(
__dirname,
'..',
'memory-tests',
'large-chat-session.json',
);

beforeAll(async () => {
if (!existsSync(LARGE_CHAT_SOURCE)) {
throw new Error(
`Performance test fixture missing: ${LARGE_CHAT_SOURCE}.`,
);
}

rig = new TestRig();
rig.setup(identifier, {
fakeResponsesPath: join(__dirname, 'perf.long-chat.responses'),
});

const geminiDir = join(rig.homeDir!, '.gemini');
const projectTempDir = join(geminiDir, 'tmp', identifier);
const targetChatsDir = join(projectTempDir, 'chats');

mkdirSync(targetChatsDir, { recursive: true });
writeFileSync(
join(geminiDir, 'projects.json'),
JSON.stringify({
projects: { [rig.testDir!]: identifier },
}),
);
writeFileSync(join(projectTempDir, '.project_root'), rig.testDir!);
copyFileSync(
LARGE_CHAT_SOURCE,
join(targetChatsDir, `session-${SESSION_ID}.json`),
);
});

afterAll(async () => {
await rig.cleanup();
});

it('session-load: resume a 60MB chat history', async () => {
const result = await harness.runScenario(
'long-conversation-resume',
async () => {
const snapshot = await harness.measureWithEventLoop(
'resume',
async () => {
const run = await rig.runInteractive({
args: ['--resume', 'latest'],
env: { GEMINI_API_KEY: 'fake-perf-test-key' },
});
await run.kill();
},
);
return snapshot;
},
);

if (UPDATE_BASELINES) {
harness.updateScenarioBaseline(result);
} else {
harness.assertWithinBaseline(result);
}
});

it('typing: latency when typing into a large session', async () => {
const result = await harness.runScenario(
'long-conversation-typing',
async () => {
const run = await rig.runInteractive({
args: ['--resume', 'latest'],
env: { GEMINI_API_KEY: 'fake-perf-test-key' },
});

const snapshot = await harness.measureWithEventLoop(
'typing',
async () => {
await run.type('Hello');
},
Comment thread
cynthialong0-0 marked this conversation as resolved.
);

await run.kill();
return snapshot;
},
);

if (UPDATE_BASELINES) {
harness.updateScenarioBaseline(result);
} else {
harness.assertWithinBaseline(result);
}
});

it('execution: response latency for a simple shell command', async () => {
const result = await harness.runScenario(
'long-conversation-execution',
async () => {
const run = await rig.runInteractive({
args: ['--resume', 'latest'],
env: { GEMINI_API_KEY: 'fake-perf-test-key' },
});

await run.expectText('type your message');

const snapshot = await harness.measureWithEventLoop(
'execution',
async () => {
await run.sendKeys('!echo hi\r');
await run.expectText('hi');
},
);

await run.kill();
return snapshot;
},
);

if (UPDATE_BASELINES) {
harness.updateScenarioBaseline(result);
} else {
harness.assertWithinBaseline(result);
}
});

it('terminal-scrolling: latency when scrolling a large terminal buffer', async () => {
const result = await harness.runScenario(
'long-conversation-terminal-scrolling',
async () => {
// Enable terminalBuffer to intentionally test CLI scrolling logic
const settingsPath = join(rig.homeDir!, '.gemini', 'settings.json');
writeFileSync(
settingsPath,
JSON.stringify({
security: { folderTrust: { enabled: false } },
ui: { terminalBuffer: true },
}),
);

const run = await rig.runInteractive({
args: ['--resume', 'latest'],
env: { GEMINI_API_KEY: 'fake-perf-test-key' },
});

await run.expectText('type your message');

const snapshot = await harness.measureWithEventLoop(
'terminal-scrolling',
async () => {
for (let i = 0; i < 5; i++) {
await run.sendKeys('\u001b[5~'); // PageUp
await run.sendKeys('\u001b[6~'); // PageDown
}
},
);
Comment thread
cynthialong0-0 marked this conversation as resolved.
Outdated

await run.kill();
return snapshot;
},
);

if (UPDATE_BASELINES) {
harness.updateScenarioBaseline(result);
} else {
harness.assertWithinBaseline(result);
}
});

it('alternate-scrolling: latency when scrolling a large alternate buffer', async () => {
const result = await harness.runScenario(
'long-conversation-alternate-scrolling',
async () => {
// Enable useAlternateBuffer to intentionally test CLI scrolling logic
const settingsPath = join(rig.homeDir!, '.gemini', 'settings.json');
writeFileSync(
settingsPath,
JSON.stringify({
security: { folderTrust: { enabled: false } },
ui: { useAlternateBuffer: true },
}),
);

const run = await rig.runInteractive({
args: ['--resume', 'latest'],
env: { GEMINI_API_KEY: 'fake-perf-test-key' },
});

await run.expectText('type your message');

const snapshot = await harness.measureWithEventLoop(
'alternate-scrolling',
async () => {
for (let i = 0; i < 5; i++) {
await run.sendKeys('\u001b[5~'); // PageUp
await run.sendKeys('\u001b[6~'); // PageDown
}
},
);

await run.kill();
return snapshot;
},
);

if (UPDATE_BASELINES) {
harness.updateScenarioBaseline(result);
} else {
harness.assertWithinBaseline(result);
}
});
});
});
4 changes: 4 additions & 0 deletions perf-tests/perf.long-chat.responses
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"{\"complexity_reasoning\":\"simple\",\"complexity_score\":1}"}],"role":"model"},"finishReason":"STOP","index":0}]}}
{"method":"generateContentStream","response":[{"candidates":[{"content":{"parts":[{"text":"I am a large conversation model response."}],"role":"model"},"finishReason":"STOP","index":0}],"usageMetadata":{"candidatesTokenCount":10,"promptTokenCount":20,"totalTokenCount":30}}]}
{"method":"generateContent","response":{"candidates":[{"content":{"parts":[{"text":"{\"originalSummary\":\"large chat summary\",\"events\":[]}"}],"role":"model"},"finishReason":"STOP","index":0}]}}
{"method":"countTokens","response":{"totalTokens":100}}
Loading