perf: reduce duplicate rendering in localSearch (#3170)

Co-authored-by: Divyansh Singh <40380293+brc-dd@users.noreply.github.com>
pull/3187/head
烽宁 1 year ago committed by GitHub
parent 37e4ab9ec2
commit 878f4378cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -31,6 +31,7 @@ import {
import type { ModalTranslations } from '../../../../types/local-search' import type { ModalTranslations } from '../../../../types/local-search'
import { pathToFile } from '../../app/utils' import { pathToFile } from '../../app/utils'
import { useData } from '../composables/data' import { useData } from '../composables/data'
import { LRUCache } from '../support/lru'
import { createTranslate } from '../support/translation' import { createTranslate } from '../support/translation'
const emit = defineEmits<{ const emit = defineEmits<{
@ -142,6 +143,8 @@ const mark = computedAsync(async () => {
return markRaw(new Mark(resultsEl.value)) return markRaw(new Mark(resultsEl.value))
}, null) }, null)
const cache = new LRUCache<string, Map<string, string>>(16) // 16 files
debouncedWatch( debouncedWatch(
() => [searchIndex.value, filterText.value, showDetailedList.value] as const, () => [searchIndex.value, filterText.value, showDetailedList.value] as const,
async ([index, filterTextValue, showDetailedListValue], old, onCleanup) => { async ([index, filterTextValue, showDetailedListValue], old, onCleanup) => {
@ -163,13 +166,12 @@ debouncedWatch(
? await Promise.all(results.value.map((r) => fetchExcerpt(r.id))) ? await Promise.all(results.value.map((r) => fetchExcerpt(r.id)))
: [] : []
if (canceled) return if (canceled) return
const c = new Map<string, Map<string, string>>()
for (const { id, mod } of mods) { for (const { id, mod } of mods) {
const mapId = id.slice(0, id.indexOf('#')) const mapId = id.slice(0, id.indexOf('#'))
let map = c.get(mapId) let map = cache.get(mapId)
if (map) continue if (map) continue
map = new Map() map = new Map()
c.set(mapId, map) cache.set(mapId, map)
const comp = mod.default ?? mod const comp = mod.default ?? mod
if (comp?.render || comp?.setup) { if (comp?.render || comp?.setup) {
const app = createApp(comp) const app = createApp(comp)
@ -209,7 +211,7 @@ debouncedWatch(
results.value = results.value.map((r) => { results.value = results.value.map((r) => {
const [id, anchor] = r.id.split('#') const [id, anchor] = r.id.split('#')
const map = c.get(id) const map = cache.get(id)
const text = map?.get(anchor) ?? '' const text = map?.get(anchor) ?? ''
for (const term in r.match) { for (const term in r.match) {
terms.add(term) terms.add(term)

@ -0,0 +1,33 @@
// adapted from https://stackoverflow.com/a/46432113/11613622
export class LRUCache<K, V> {
private max: number
private cache: Map<K, V>
constructor(max: number = 10) {
this.max = max
this.cache = new Map<K, V>()
}
get(key: K): V | undefined {
let item = this.cache.get(key)
if (item !== undefined) {
// refresh key
this.cache.delete(key)
this.cache.set(key, item)
}
return item
}
set(key: K, val: V): void {
// refresh key
if (this.cache.has(key)) this.cache.delete(key)
// evict oldest
else if (this.cache.size === this.max) this.cache.delete(this.first()!)
this.cache.set(key, val)
}
first(): K | undefined {
return this.cache.keys().next().value
}
}
Loading…
Cancel
Save