Skip to content

Commit 27a1f4d

Browse files
Kartik Rajwesm
Kartik Raj
authored andcommitted
Include windows registry perf improvement in pythonDiscoveryUsingWorkers experiment (microsoft/vscode-python#23075)
For microsoft/vscode-python#22146
1 parent 6d74b7a commit 27a1f4d

File tree

6 files changed

+21
-32
lines changed

6 files changed

+21
-32
lines changed

extensions/positron-python/src/client/pythonEnvironments/base/locators/composite/resolverUtils.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ async function updateEnvUsingRegistry(env: PythonEnvInfo): Promise<void> {
109109
let interpreters = getRegistryInterpretersSync();
110110
if (!interpreters) {
111111
traceError('Expected registry interpreter cache to be initialized already');
112-
interpreters = await getRegistryInterpreters(true);
112+
interpreters = await getRegistryInterpreters();
113113
}
114114
const data = interpreters.find((i) => arePathsSame(i.interpreterPath, env.executable.filename));
115115
if (data) {

extensions/positron-python/src/client/pythonEnvironments/base/locators/lowLevel/condaLocator.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,8 @@ export class CondaEnvironmentLocator extends FSWatchingLocator {
1919
}
2020

2121
// eslint-disable-next-line class-methods-use-this
22-
public async *doIterEnvs(_: unknown, useWorkerThreads = false): IPythonEnvsIterator<BasicEnvInfo> {
23-
const conda = await Conda.getConda(undefined, useWorkerThreads);
22+
public async *doIterEnvs(_: unknown): IPythonEnvsIterator<BasicEnvInfo> {
23+
const conda = await Conda.getConda();
2424
if (conda === undefined) {
2525
traceVerbose(`Couldn't locate the conda binary.`);
2626
return;

extensions/positron-python/src/client/pythonEnvironments/base/locators/lowLevel/windowsRegistryLocator.ts

+11-6
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,31 @@ import { getRegistryInterpreters } from '../../../common/windowsUtils';
99
import { traceError, traceVerbose } from '../../../../logging';
1010
import { isMicrosoftStoreDir } from '../../../common/environmentManagers/microsoftStoreEnv';
1111
import { PythonEnvsChangedEvent } from '../../watcher';
12+
import { DiscoveryUsingWorkers } from '../../../../common/experiments/groups';
13+
import { inExperiment } from '../../../common/externalDependencies';
1214

1315
export const WINDOWS_REG_PROVIDER_ID = 'windows-registry';
1416

1517
export class WindowsRegistryLocator extends Locator<BasicEnvInfo> {
1618
public readonly providerId: string = WINDOWS_REG_PROVIDER_ID;
1719

1820
// eslint-disable-next-line class-methods-use-this
19-
public iterEnvs(query?: PythonLocatorQuery, useWorkerThreads = false): IPythonEnvsIterator<BasicEnvInfo> {
21+
public iterEnvs(
22+
query?: PythonLocatorQuery,
23+
useWorkerThreads = inExperiment(DiscoveryUsingWorkers.experiment),
24+
): IPythonEnvsIterator<BasicEnvInfo> {
2025
if (useWorkerThreads) {
2126
/**
2227
* Windows registry is slow and often not necessary, so notify completion immediately, but use watcher
2328
* change events to signal for any new envs which are found.
2429
*/
2530
if (query?.providerId === this.providerId) {
2631
// Query via change event, so iterate all envs.
27-
return iterateEnvs(true);
32+
return iterateEnvs();
2833
}
2934
return iterateEnvsLazily(this.emitter);
3035
}
31-
return iterateEnvs(false);
36+
return iterateEnvs();
3237
}
3338
}
3439

@@ -38,13 +43,13 @@ async function* iterateEnvsLazily(changed: IEmitter<PythonEnvsChangedEvent>): IP
3843

3944
async function loadAllEnvs(changed: IEmitter<PythonEnvsChangedEvent>) {
4045
traceVerbose('Searching for windows registry interpreters');
41-
await getRegistryInterpreters(true);
46+
await getRegistryInterpreters();
4247
changed.fire({ providerId: WINDOWS_REG_PROVIDER_ID });
4348
traceVerbose('Finished searching for windows registry interpreters');
4449
}
4550

46-
async function* iterateEnvs(useWorkerThreads: boolean): IPythonEnvsIterator<BasicEnvInfo> {
47-
const interpreters = await getRegistryInterpreters(useWorkerThreads);
51+
async function* iterateEnvs(): IPythonEnvsIterator<BasicEnvInfo> {
52+
const interpreters = await getRegistryInterpreters(); // Value should already be loaded at this point, so this returns immediately.
4853
for (const interpreter of interpreters) {
4954
try {
5055
// Filter out Microsoft Store app directories. We have a store app locator that handles this.

extensions/positron-python/src/client/pythonEnvironments/common/environmentManagers/conda.ts

+4-8
Original file line numberDiff line numberDiff line change
@@ -280,9 +280,9 @@ export class Conda {
280280
});
281281
}
282282

283-
public static async getConda(shellPath?: string, useWorkerThreads?: boolean): Promise<Conda | undefined> {
283+
public static async getConda(shellPath?: string): Promise<Conda | undefined> {
284284
if (Conda.condaPromise.get(shellPath) === undefined || isTestExecution()) {
285-
Conda.condaPromise.set(shellPath, Conda.locate(shellPath, useWorkerThreads));
285+
Conda.condaPromise.set(shellPath, Conda.locate(shellPath));
286286
}
287287
return Conda.condaPromise.get(shellPath);
288288
}
@@ -293,11 +293,7 @@ export class Conda {
293293
*
294294
* @return A Conda instance corresponding to the binary, if successful; otherwise, undefined.
295295
*/
296-
private static async locate(shellPath?: string, useWorkerThread?: boolean): Promise<Conda | undefined> {
297-
let useWorkerThreads: boolean;
298-
if (useWorkerThread === undefined) {
299-
useWorkerThreads = false;
300-
}
296+
private static async locate(shellPath?: string): Promise<Conda | undefined> {
301297
traceVerbose(`Searching for conda.`);
302298
const home = getUserHomeDir();
303299
let customCondaPath: string | undefined = 'conda';
@@ -324,7 +320,7 @@ export class Conda {
324320
}
325321

326322
async function* getCandidatesFromRegistry() {
327-
const interps = await getRegistryInterpreters(useWorkerThreads);
323+
const interps = await getRegistryInterpreters();
328324
const candidates = interps
329325
.filter((interp) => interp.interpreterPath && interp.distroOrgName === 'ContinuumAnalytics')
330326
.map((interp) => path.join(path.win32.dirname(interp.interpreterPath), suffix));

extensions/positron-python/src/client/pythonEnvironments/common/windowsUtils.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -126,15 +126,15 @@ export function getRegistryInterpretersSync(): IRegistryInterpreterData[] | unde
126126

127127
let registryInterpretersPromise: Promise<IRegistryInterpreterData[]> | undefined;
128128

129-
export async function getRegistryInterpreters(useWorkerThreads: boolean): Promise<IRegistryInterpreterData[]> {
129+
export async function getRegistryInterpreters(): Promise<IRegistryInterpreterData[]> {
130130
if (!isTestExecution() && registryInterpretersPromise !== undefined) {
131131
return registryInterpretersPromise;
132132
}
133-
registryInterpretersPromise = getRegistryInterpretersImpl(useWorkerThreads);
133+
registryInterpretersPromise = getRegistryInterpretersImpl();
134134
return registryInterpretersPromise;
135135
}
136136

137-
async function getRegistryInterpretersImpl(useWorkerThreads: boolean): Promise<IRegistryInterpreterData[]> {
137+
async function getRegistryInterpretersImpl(useWorkerThreads = false): Promise<IRegistryInterpreterData[]> {
138138
let registryData: IRegistryInterpreterData[] = [];
139139

140140
for (const arch of ['x64', 'x86']) {

extensions/positron-python/src/test/pythonEnvironments/base/locators/lowLevel/condaLocator.testvirtualenvs.ts

-12
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,6 @@ import { PythonEnvsChangedEvent } from '../../../../../client/pythonEnvironments
1414
import { EXTENSION_ROOT_DIR_FOR_TESTS, TEST_TIMEOUT } from '../../../../constants';
1515
import { traceWarn } from '../../../../../client/logging';
1616
import { TEST_LAYOUT_ROOT } from '../../../common/commonTestConstants';
17-
import { getEnvs } from '../../common';
18-
import { assertBasicEnvsEqual } from '../envTestUtils';
1917
import { PYTHON_VIRTUAL_ENVS_LOCATION } from '../../../../ciConstants';
2018
import { isCI } from '../../../../../client/common/constants';
2119
import * as externalDependencies from '../../../../../client/pythonEnvironments/common/externalDependencies';
@@ -131,14 +129,4 @@ suite('Conda Env Locator', async () => {
131129

132130
assert.deepEqual(actualEvent!, expectedEvent, 'Unexpected event emitted');
133131
});
134-
135-
test('Worker thread to fetch conda environments is working', async () => {
136-
locator = new CondaEnvironmentLocator();
137-
const items = await getEnvs(locator.doIterEnvs(undefined, false));
138-
const workerItems = await getEnvs(locator.doIterEnvs(undefined, true));
139-
console.log('Number of items Conda locator returned:', items.length);
140-
// Make sure items returned when using worker threads v/s not are the same.
141-
assertBasicEnvsEqual(items, workerItems);
142-
assert(workerItems.length > 0, 'No environments found');
143-
}).timeout(TEST_TIMEOUT * 2);
144132
});

0 commit comments

Comments
 (0)