Change:
Reconnecting/restoring terminals becomes quite slow when you have many terminals. We should measure what's happening with the pty host trace logs and try optimize.
A lot of time is spent validating profiles in the first getProfiles call: <img width="685" alt="Screenshot 2023-06-23 at 2 26 59 pm" src=""This happens per profile candidate and actually happens on the main process in the PtyHostService atm. Each call communicates back with the renderer:
Lots of metrics and debug tools are now available and some optimization happened. Making a feature request to remind me to add release notes.

Discussion:
logService?: ILogService, variableResolver?: (text: string[]) => Promise<string[]>, ): Promise<ITerminalProfile[]> { <del> const resultProfiles: ITerminalProfile[] = []; </del> <ins> const promises: Promise<ITerminalProfile | undefined>[] = []; </ins> for (const [profileName, profile] of entries) { <del> if (profile === null) { continue; } let originalPaths: (string | ITerminalUnsafePath)[]; let args: string[] | string | undefined; let icon: ThemeIcon | URI | { light: URI; dark: URI } | undefined = undefined; // use calculated values if path is not specified if ('source' in profile && !('path' in profile)) { const source = profileSources?.get(profile.source); if (!source) { continue; } originalPaths = source.paths; // if there are configured args, override the default ones args = profile.args || source.args; if (profile.icon) { icon = validateIcon(profile.icon); } else if (source.icon) { icon = source.icon; } } else { originalPaths = Array.isArray(profile.path) ? profile.path : [profile.path]; args = isWindows ? profile.args : Array.isArray(profile.args) ? profile.args : undefined; icon = validateIcon(profile.icon); </del> <ins> promises.push(getValidatedProfile(profileName, profile, defaultProfileName, fsProvider, shellEnv, logService, variableResolver)); } return (await Promise.all(promises)).filter(e => !!e) as ITerminalProfile[]; } async function getValidatedProfile( profileName: string, profile: IUnresolvedTerminalProfile, defaultProfileName: string | undefined, fsProvider: IFsProvider, shellEnv: typeof process.env = process.env, logService?: ILogService, variableResolver?: (text: string[]) => Promise<string[]> ): Promise<ITerminalProfile | undefined> { if (profile === null) { return undefined; } let originalPaths: (string | ITerminalUnsafePath)[]; let args: string[] | string | undefined; let icon: ThemeIcon | URI | { light: URI; dark: URI } | undefined = undefined; // use calculated values if path is not specified if ('source' in profile && !('path' in profile)) { const source = profileSources?.get(profile.source); if (!source) { return undefined; </ins> } <ins> originalPaths = source.paths; </ins> <del> let paths: (string | ITerminalUnsafePath)[]; if (variableResolver) { // Convert to string[] for resolve const mapped = originalPaths.map(e => typeof e === 'string' ? e : e.path); const resolved = await variableResolver(mapped); // Convert resolved back to (T | string)[] paths = new Array(originalPaths.length); for (let i = 0; i < originalPaths.length; i++) { if (typeof originalPaths[i] === 'string') { paths[i] = resolved[i]; } else { paths[i] = { path: resolved[i], isUnsafe: true }; } } } else { paths = originalPaths.slice(); </del> <ins> // if there are configured args, override the default ones args = profile.args || source.args; if (profile.icon) { icon = validateIcon(profile.icon); } else if (source.icon) { icon = source.icon; </ins> } <ins> } else { originalPaths = Array.isArray(profile.path) ? profile.path : [profile.path]; args = isWindows ? profile.args : Array.isArray(profile.args) ? profile.args : undefined; icon = validateIcon(profile.icon); } </ins> <del> let requiresUnsafePath: string | undefined; if (profile.requiresPath) { // Validate requiresPath exists let actualRequiredPath: string; if (isString(profile.requiresPath)) { actualRequiredPath = profile.requiresPath; </del> <ins> let paths: (string | ITerminalUnsafePath)[]; if (variableResolver) { // Convert to string[] for resolve const mapped = originalPaths.map(e => typeof e === 'string' ? e : e.path); const resolved = await variableResolver(mapped); // Convert resolved back to (T | string)[] paths = new Array(originalPaths.length); for (let i = 0; i < originalPaths.length; i++) { if (typeof originalPaths[i] === 'string') { paths[i] = resolved[i]; </ins> } else { <del> actualRequiredPath = profile.requiresPath.path; if (profile.requiresPath.isUnsafe) { requiresUnsafePath = actualRequiredPath; } } const result = await fsProvider.existsFile(actualRequiredPath); if (!result) { continue; </del> <ins> paths[i] = { path: resolved[i], isUnsafe: true }; </ins> } } <ins> } else { paths = originalPaths.slice(); } </ins> <del> const validatedProfile = await validateProfilePaths(profileName, defaultProfileName, paths, fsProvider, shellEnv, args, profile.env, profile.overrideName, profile.isAutoDetected, requiresUnsafePath); if (validatedProfile) { validatedProfile.isAutoDetected = profile.isAutoDetected; validatedProfile.icon = icon; validatedProfile.color = profile.color; resultProfiles.push(validatedProfile); </del> <ins> let requiresUnsafePath: string | undefined; if (profile.requiresPath) { // Validate requiresPath exists let actualRequiredPath: string; if (isString(profile.requiresPath)) { actualRequiredPath = profile.requiresPath; </ins> } else { <del> logService?.debug('Terminal profile not validated', profileName, originalPaths); </del> <ins> actualRequiredPath = profile.requiresPath.path; if (profile.requiresPath.isUnsafe) { requiresUnsafePath = actualRequiredPath; } } const result = await fsProvider.existsFile(actualRequiredPath); if (!result) { return; </ins> } } <del> logService?.debug('Validated terminal profiles', resultProfiles); return resultProfiles; </del> <ins> const validatedProfile = await validateProfilePaths(profileName, defaultProfileName, paths, fsProvider, shellEnv, args, profile.env, profile.overrideName, profile.isAutoDetected, requiresUnsafePath); if (!validatedProfile) { logService?.debug('Terminal profile not validated', profileName, originalPaths); return undefined; } validatedProfile.isAutoDetected = profile.isAutoDetected; validatedProfile.icon = icon; validatedProfile.color = profile.color; return validatedProfile; </ins> } function validateIcon(icon: string | TerminalIcon | undefined): TerminalIcon | undefined {