Skip to content

Commit

Permalink
perf: use work thread
Browse files Browse the repository at this point in the history
  • Loading branch information
Daydreamer-riri committed Dec 2, 2023
1 parent 09a2cd3 commit 5ee3f85
Show file tree
Hide file tree
Showing 10 changed files with 62 additions and 27 deletions.
2 changes: 2 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
{
}

Check failure on line 2 in .vscode/settings.json

View workflow job for this annotation

GitHub Actions / lint

Newline required at end of file but not found
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ This is packages, an extension for node dependencies. Aims helping developers to

## Roadmap

- [ ] Use `worker_threads` to avoid blocking the main thread.
- [x] Use `worker_threads` to avoid blocking the main thread.

## Thanks

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@
}
},
"scripts": {
"build": "tsup src/index.ts --external vscode",
"build": "tsup --external vscode",
"dev": "nr build --watch",
"lint": "eslint .",
"vscode:prepublish": "nr build",
Expand Down
14 changes: 6 additions & 8 deletions src/api/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
import { window } from 'vscode'
import type Item from '../core/Item'
import { now, ttl } from '../utils/ttl'
import { getWorkspaceFolderPath } from '../utils/resolve'
import { dumpCache, loadCache } from './cache'
import { version } from './version'
import { protocolDep } from './utils'
Expand All @@ -12,12 +10,12 @@ const cacheTTL = 30 * 60_000 // 30min

let cacheChanged = false

interface PackageData {
export interface PackageData {
version: string[]
info?: string
}

export async function getPackageData(item: Item): Promise<PackageData> {
export async function getPackageData(item: Item, root: string): Promise<PackageData> {
const preTest = protocolDep(item)
if (preTest)
return preTest
Expand All @@ -32,19 +30,19 @@ export async function getPackageData(item: Item): Promise<PackageData> {
}
else {
// cache.delete(name)
reGetVersion(name)
reGetVersion(name, root)
}
return { version: cacheData.data }
}

return {
version: await reGetVersion(name),
version: await reGetVersion(name, root),
}
}

async function reGetVersion(name: string) {
async function reGetVersion(name: string, root: string) {
try {
const root = getWorkspaceFolderPath(window.activeTextEditor)!
// const root = getWorkspaceFolderPath(window.activeTextEditor)!
const data = await version(name, root)

if (data) {
Expand Down
38 changes: 29 additions & 9 deletions src/core/fetcher.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,29 @@
import { Worker } from 'node:worker_threads'
import path from 'node:path'
import { CompletionItem, CompletionItemKind, CompletionList } from 'vscode'
import PQueue from 'p-queue'
import { getPackageData } from '../api'
import compareVersions from '../semver/compareVersion'
import { sortText } from '../providers/autoCompletion'
import { statusBarItem } from '../ui/indicators'
import type { PackageData } from '../api'
import { getRoot } from '../utils/resolve'
import type Item from './Item'
import type Dependency from './Dependency'

const queue = new PQueue({ concurrency: 10 })
// const queue = new PQueue({ concurrency: 10 })

export function fetchPackageVersions(
export async function fetchPackageVersions(
dependencies: Item[],
): [Promise<Dependency[]>, Map<string, Dependency[]>] {
): Promise<[Dependency[], Map<string, Dependency[]>]> {
statusBarItem.setText('👀 Fetching npm')

const responsesMap: Map<string, Dependency[]> = new Map()

const responses: Promise<Dependency>[] = dependencies.map(
async (item) => {
const packageData = await fetchPackageData(dependencies)

const responses = dependencies.map(
(item, index) => {
try {
const data = await queue.add(() => getPackageData(item))
const data = packageData[index]
if (!data)
throw new Error('Get Package information failure')

Expand Down Expand Up @@ -66,5 +70,21 @@ export function fetchPackageVersions(
},
)

return [Promise.all(responses), responsesMap]
return [responses, responsesMap]
}

function fetchPackageData(
dependencies: Item[],
): Promise<PackageData[]> {
return new Promise((resolve, reject) => {
const root = getRoot()

const worker = new Worker(path.resolve(__dirname, 'worker.js'), { workerData: { dependencies, root } })
worker.on('message', (data: PackageData[]) => {
resolve(data)
})
worker.on('error', (error) => {
reject(error)
})
})
}
4 changes: 2 additions & 2 deletions src/core/listener.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ export async function parseAndDecorate(
try {
dependencies = parseDeps(text)
if (fetchDeps || !fetchedDeps || !fetchedDepsMap) {
const data = fetchPackageVersions(dependencies)
fetchedDeps = await data[0]
const data = await fetchPackageVersions(dependencies)
fetchedDeps = data[0]
fetchedDepsMap = data[1]
}
decorate(editor, fetchedDeps)
Expand Down
11 changes: 11 additions & 0 deletions src/core/worker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { parentPort, workerData } from 'node:worker_threads'
import { getPackageData, saveCache } from '../api'
import type Item from './Item'

const { dependencies, root } = workerData as { dependencies: Item[]; root: string }
const datasP = dependencies.map(item => getPackageData(item, root))

Promise.all(datasP).then((datas) => {
parentPort?.postMessage(datas)
saveCache()
})
3 changes: 1 addition & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import type { ExtensionContext } from 'vscode'
import Commands from './commands/commands'
import { saveCache } from './api'
import { registerAutoCompletion } from './providers/autoCompletion'
import { registerListener } from './core/listener'

Expand All @@ -11,5 +10,5 @@ export function activate(context: ExtensionContext) {
}

export function deactivate() {
saveCache()
// saveCache()
}
6 changes: 5 additions & 1 deletion src/utils/resolve.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { TextDocument, TextEditor } from 'vscode'
import { workspace } from 'vscode'
import { window, workspace } from 'vscode'

export function getWorkspaceFolderPath(
documentOrEditor?: TextDocument | TextEditor,
Expand All @@ -17,3 +17,7 @@ function isEditor(
): documentOrEditor is TextEditor {
return (documentOrEditor as any).document != null
}

export function getRoot() {
return getWorkspaceFolderPath(window.activeTextEditor)!
}
7 changes: 4 additions & 3 deletions tsup.config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { defineConfig } from 'tsup'

export default defineConfig({
entry: [
'src/index.ts',
],
entry: {
index: 'src/index.ts',
worker: 'src/core/worker.ts',
},
format: ['cjs'],
shims: false,
dts: false,
Expand Down

0 comments on commit 5ee3f85

Please sign in to comment.