Skip to content

Commit 13f4446

Browse files
luoxuanzaoQoder-AI
andcommitted
perf: drop the console-based timing diagnostics
The stricter review forbids disabling no-console, and the [qoderian perf] console lines were a developer-only nicety. Remove the diagnostics module, its tests, and unwrap every measureAsync/measure/ logElapsed call site back to the direct calls; the performance work itself (parallel metadata reads, probes) stays. Co-authored-by: QoderAI (Qwen 3.8 Max) <qoder_ai@qoder.com>
1 parent dbee659 commit 13f4446

9 files changed

Lines changed: 18 additions & 328 deletions

File tree

‎src/core/diagnostics/performance.ts‎

Lines changed: 0 additions & 37 deletions
This file was deleted.

‎src/features/chat/controllers/input-controller.ts‎

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,6 @@ import { Notice } from 'obsidian';
33
import { hasErrorContentBlock } from '../../../core/chat/error-blocks';
44
import { detectBuiltInCommand } from '../../../core/commands/built-in-commands';
55
import type { BrowserSelectionContext, CanvasSelectionContext } from '../../../core/context/types';
6-
import {
7-
logElapsed,
8-
measure,
9-
measureAsync,
10-
} from '../../../core/diagnostics/performance';
116
import type { EditorSelectionContext } from '../../../core/editor/editor-context';
127
import type { ChatRuntime } from '../../../core/runtime/chat-runtime';
138
import type { ApprovalCallbackOptions, ChatTurnRequest } from '../../../core/runtime/types';
@@ -282,13 +277,13 @@ export class InputController {
282277
displayContent: content,
283278
turnRequest: cloneChatTurnRequest(options.turnRequestOverride),
284279
}
285-
: await measureAsync('turn.buildSubmission', () => this.buildTurnSubmission({
280+
: await this.buildTurnSubmission({
286281
content,
287282
images: imagesForMessage,
288283
editorContextOverride: options?.editorContextOverride,
289284
browserContextOverride: options?.browserContextOverride,
290285
canvasContextOverride: options?.canvasContextOverride,
291-
}));
286+
});
292287
const { displayContent, turnRequest } = turnSubmission;
293288

294289
fileContextManager?.markCurrentNoteSent();
@@ -305,7 +300,7 @@ export class InputController {
305300
state.hasPendingConversationSave = true;
306301
renderer.addMessage(userMsg);
307302

308-
await measureAsync('turn.titleGeneration', () => this.triggerTitleGeneration());
303+
await this.triggerTitleGeneration();
309304

310305
const assistantMsg: ChatMessage = {
311306
id: this.deps.generateId(),
@@ -330,9 +325,6 @@ export class InputController {
330325
isCompact ? 'qoderian-thinking--compact' : undefined,
331326
);
332327
state.responseStartTime = performance.now();
333-
// Turn-level timing origin for the [qoderian perf] turn.* diagnostics.
334-
const turnStartedAt = state.responseStartTime;
335-
let sawFirstRuntimeChunk = false;
336328

337329
let wasInterrupted = false;
338330
let wasInvalidated = false;
@@ -341,7 +333,7 @@ export class InputController {
341333

342334
// Lazy initialization: ensure service is ready before first query
343335
if (this.deps.ensureServiceInitialized) {
344-
const ready = await measureAsync('turn.serviceInit', () => this.deps.ensureServiceInitialized!());
336+
const ready = await this.deps.ensureServiceInitialized();
345337
if (!ready) {
346338
new Notice('Failed to initialize agent service. Please try again.');
347339
streamController.hideThinkingIndicator();
@@ -384,7 +376,7 @@ export class InputController {
384376
}
385377

386378
try {
387-
const preparedTurn = measure('turn.prepareTurn', () => agentService.prepareTurn(turnRequest));
379+
const preparedTurn = agentService.prepareTurn(turnRequest);
388380
userMsg.content = preparedTurn.persistedContent;
389381
userMsg.currentNote = preparedTurn.isCompact
390382
? undefined
@@ -394,10 +386,6 @@ export class InputController {
394386
// This prevents duplication when rebuilding context for new sessions
395387
const previousMessages = state.messages.slice(0, -2);
396388
for await (const chunk of agentService.query(preparedTurn, previousMessages)) {
397-
if (!sawFirstRuntimeChunk) {
398-
sawFirstRuntimeChunk = true;
399-
logElapsed('turn.firstChunk', turnStartedAt);
400-
}
401389
if (state.streamGeneration !== streamGeneration) {
402390
wasInvalidated = true;
403391
break;
@@ -428,7 +416,6 @@ export class InputController {
428416
this.activeStreamingAssistantMessage ?? assistantMsg,
429417
);
430418
} finally {
431-
logElapsed('turn.total', turnStartedAt);
432419
const finalAssistantMsg = this.activeStreamingAssistantMessage ?? assistantMsg;
433420
const turnMetadata = agentService.consumeTurnMetadata();
434421
userMsg.userMessageId = turnMetadata.userMessageId ?? userMsg.userMessageId;

‎src/features/chat/tabs/tab-manager.ts‎

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { Notice } from 'obsidian';
22

3-
import { measureAsync } from '../../../core/diagnostics/performance';
43
import { reportRestoreIssue } from '../../../core/diagnostics/restore-report';
54
import type { ChatRuntime } from '../../../core/runtime/chat-runtime';
65
import { t } from '../../../i18n/i18n';
@@ -95,10 +94,7 @@ export class TabManager implements TabManagerInterface {
9594
tabId?: TabId,
9695
options: CreateTabOptions = {},
9796
): Promise<TabData | null> {
98-
return measureAsync(
99-
this.isRestoringState ? 'tab.restore' : 'tab.create',
100-
() => this.createTabInner(conversationId, tabId, options),
101-
);
97+
return this.createTabInner(conversationId, tabId, options);
10298
}
10399

104100
private async createTabInner(
@@ -171,7 +167,7 @@ export class TabManager implements TabManagerInterface {
171167
* @param tabId The tab to switch to.
172168
*/
173169
async switchToTab(tabId: TabId): Promise<void> {
174-
return measureAsync('tab.switchTo', () => this.switchToTabInner(tabId));
170+
return this.switchToTabInner(tabId);
175171
}
176172

177173
private async switchToTabInner(tabId: TabId): Promise<void> {
@@ -545,7 +541,7 @@ export class TabManager implements TabManagerInterface {
545541

546542
/** Restores state from persisted data. */
547543
async restoreState(state: PersistedTabManagerState): Promise<void> {
548-
await measureAsync('startup.restoreTabs', () => this.restoreStateInner(state));
544+
await this.restoreStateInner(state);
549545
}
550546

551547
private async restoreStateInner(state: PersistedTabManagerState): Promise<void> {

‎src/main.ts‎

Lines changed: 7 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import type { Editor, WorkspaceLeaf } from 'obsidian';
66
import { addIcon, MarkdownView, Notice, Plugin } from 'obsidian';
77

88
import { QoderianStorage } from './app/storage/app-storage';
9-
import { measureAsync } from './core/diagnostics/performance';
109
import { beginRestoreReport, reportRestoreIssue } from './core/diagnostics/restore-report';
1110
import { buildCursorContext } from './core/editor/editor-context';
1211
import { getVaultPath } from './core/fs/path';
@@ -418,22 +417,10 @@ export default class QoderianPlugin extends Plugin {
418417
}
419418
const didNormalizeModelVariants = this.normalizeModelVariantSettings();
420419

421-
const allMetadata = await measureAsync(
422-
'startup.listMetadata',
423-
() => this.storage.sessions.listMetadata(),
424-
);
425-
const legacyLocations = await measureAsync(
426-
'startup.probeLegacyEditions',
427-
() => this.probeLegacyEditionLocations(allMetadata),
428-
);
429-
await measureAsync(
430-
'startup.migrateLegacyEditions',
431-
() => this.migrateLegacySessionEditions(allMetadata, legacyLocations),
432-
);
433-
this.conversations = await measureAsync(
434-
'startup.buildConversationIndex',
435-
() => this.buildConversationIndex(allMetadata, legacyLocations),
436-
);
420+
const allMetadata = await this.storage.sessions.listMetadata();
421+
const legacyLocations = await this.probeLegacyEditionLocations(allMetadata);
422+
await this.migrateLegacySessionEditions(allMetadata, legacyLocations);
423+
this.conversations = await this.buildConversationIndex(allMetadata, legacyLocations);
437424
setLocale(this.settings.locale as Locale);
438425

439426
if (didNormalizeModelVariants) {
@@ -590,12 +577,9 @@ export default class QoderianPlugin extends Plugin {
590577
return;
591578
}
592579

593-
await measureAsync(
594-
'history.hydrateConversation',
595-
() => historyService.hydrateConversationHistory(
596-
conversation,
597-
getVaultPath(this.app),
598-
),
580+
await historyService.hydrateConversationHistory(
581+
conversation,
582+
getVaultPath(this.app),
599583
);
600584
}
601585

‎src/qoder/runtime/persistent-turn-stream.ts‎

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import type { SDKUserMessage } from '@qoder-ai/qoder-agent-sdk';
22

3-
import { logElapsed } from '../../core/diagnostics/performance';
43
import type { StreamChunk } from '../../core/types';
54
import type { QoderMessageChannel } from './qoder-message-channel';
65
import { isSessionExpiredError } from './session-context';
@@ -27,16 +26,9 @@ export async function* streamPersistentTurn(
2726
error: null as Error | null,
2827
};
2928
const handlerId = `handler-${Date.now()}-${Math.random().toString(36).slice(2)}`;
30-
const enqueuedAt = performance.now();
31-
let sawFirstChunk = false;
3229
const handler = createResponseHandler({
3330
id: handlerId,
3431
onChunk: chunk => {
35-
if (!sawFirstChunk) {
36-
sawFirstChunk = true;
37-
// Covers CLI cold-start when the persistent Query was just spawned.
38-
logElapsed('turn.enqueueToFirstChunk', enqueuedAt);
39-
}
4032
handler.markChunkSeen();
4133
if (state.resolveChunk) {
4234
state.resolveChunk(chunk);

‎src/qoder/runtime/qoder-chat-runtime.ts‎

Lines changed: 1 addition & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,6 @@ import type {
2323
import { query as agentQuery } from '@qoder-ai/qoder-agent-sdk';
2424
import { Notice } from 'obsidian';
2525

26-
import {
27-
logElapsed,
28-
measureAsync,
29-
} from '../../core/diagnostics/performance';
3026
import { getEnhancedPath, getMissingNodeError } from '../../core/env/environment';
3127
import { getVaultPath } from '../../core/fs/path';
3228
import type { ChatRuntime } from '../../core/runtime/chat-runtime';
@@ -149,8 +145,6 @@ export class QoderChatRuntime implements ChatRuntime {
149145
private persistentQuery: Query | null = null;
150146
private messageChannel: QoderMessageChannel | null = null;
151147
private queryAbortController: AbortController | null = null;
152-
/** Set when the persistent Query is created; used to time CLI cold-start. */
153-
private persistentQueryCreatedAt: number | null = null;
154148
private readonly responseRouter: QoderResponseRouter;
155149
private responseConsumerRunning = false;
156150
private responseConsumerPromise: Promise<void> | null = null;
@@ -425,13 +419,10 @@ export class QoderChatRuntime implements ChatRuntime {
425419
externalContextPaths
426420
);
427421

428-
const spawnStartedAt = performance.now();
429422
this.persistentQuery = agentQuery({
430423
prompt: this.messageChannel,
431424
options,
432425
});
433-
logElapsed('runtime.spawnPersistentQuery', spawnStartedAt);
434-
this.persistentQueryCreatedAt = performance.now();
435426

436427
if (this.pendingResumeAt === resumeAtMessageId) {
437428
this.pendingResumeAt = undefined;
@@ -490,7 +481,6 @@ export class QoderChatRuntime implements ChatRuntime {
490481
this.persistentQuery = null;
491482
this.messageChannel = null;
492483
this.queryAbortController = null;
493-
this.persistentQueryCreatedAt = null;
494484
this.responseConsumerRunning = false;
495485
this.responseConsumerPromise = null;
496486
this.currentConfig = null;
@@ -638,15 +628,7 @@ export class QoderChatRuntime implements ChatRuntime {
638628
if (!this.persistentQuery) return;
639629

640630
try {
641-
let sawFirstMessage = false;
642631
for await (const message of this.persistentQuery) {
643-
if (!sawFirstMessage) {
644-
sawFirstMessage = true;
645-
if (this.persistentQueryCreatedAt !== null) {
646-
// CLI cold-start: from Query creation to the first runtime message.
647-
logElapsed('runtime.cliFirstMessage', this.persistentQueryCreatedAt);
648-
}
649-
}
650632
if (this.shuttingDown) break;
651633

652634
await this.responseRouter.route(message);
@@ -964,7 +946,7 @@ export class QoderChatRuntime implements ChatRuntime {
964946
const savedPreapprovedTools = this.currentPreapprovedTools;
965947

966948
// Apply dynamic updates before sending (Phase 1.6)
967-
await measureAsync('runtime.applyDynamicUpdates', () => this.applyDynamicUpdates(queryOptions));
949+
await this.applyDynamicUpdates(queryOptions);
968950

969951
// Restore turn pre-approvals in case a dynamic update restarted the Query.
970952
this.currentPreapprovedTools = savedPreapprovedTools;

‎src/qoder/services/qoder-title-generation-service.ts‎

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { measureAsync } from '../../core/diagnostics/performance';
21
import type {
32
TitleGenerationCallback,
43
TitleGenerationResult,
@@ -37,15 +36,15 @@ export class QoderTitleGenerationService {
3736
const prompt = `User's request:\n"""\n${truncatedUser}\n"""\n\nGenerate a title for this conversation:`;
3837

3938
try {
40-
const result = await measureAsync('title.coldStartQuery', () => runColdStartQuery({
39+
const result = await runColdStartQuery({
4140
plugin: this.plugin,
4241
systemPrompt: TITLE_GENERATION_SYSTEM_PROMPT,
4342
tools: [],
4443
model: this.resolveTitleModel(),
4544
thinking: { disabled: true },
4645
persistSession: false,
4746
abortController,
48-
}, prompt));
47+
}, prompt);
4948

5049
const title = this.parseTitle(result.text);
5150
if (title) {

0 commit comments

Comments
 (0)