这是我的课程Sample
。
Sample
实例可以:
Tag1
,Tag2
等isTagged
来查询它是否已被标记(即!Tag1
)
function Sample(){
// [..]
this.tags = [];
// [..]
}
Sample.prototype.tag = function(tags){
// [..]
this.tags[tags] = true;
// [..]
};
// if an array is passed, isTagged will return true at the first match ie. not all need to match, just one
Sample.prototype.isTagged = function(tag){
if(tag){
if(Array.isArray(tag)){
let tLength = tag.length;
while(tLength--){
if(isTaggedSingleNoChecks(this, tag[tLength])){
return true;
}
}
return false;
}
else{
return isTaggedSingleNoChecks(this, tag);
}
}
return false;
};
function isTaggedSingleNoChecks(sample, tag){
const isNegated = tag.charAt(0) == "!";
if(isNegated){
tag = tag.replace(/^[!]/, "");
return sample.tags[tag]!==true;
}
else{
return sample.tags[tag]===true;
}
}
// showing usage
var sample = new Sample();
sample.tag('Tag1');
sample.tag('Tag2');
console.log(sample.isTagged('Tag1'));
console.log(sample.isTagged('Tag3'));
console.log(sample.isTagged('!Tag2'));
这一切都很好,但是我的应用程序在数千个isTagged
实例上递归查询Sample
数百万次,而我的分析显示这是性能瓶颈。
关于如何提高性能的任何建议?
答案 0 :(得分:1)
在开始对此进行优化之前,如何首先简化代码并摆脱最明显的奇怪之处(对象而不是Set,无用的正则表达式等)
class Sample {
constructor() {
this.tags = new Set();
}
tag(...tags) {
for (let t of tags)
this.tags.add(t);
}
isTagged(...tags) {
return tags.some(t =>
(t[0] === '!')
? !this.tags.has(t.slice(1))
: this.tags.has(t)
)
}
}
如果这仍然太慢,那么您必须求助于全局对象标签反向索引,例如:
class SetMap extends Map {
get(key) {
if (!this.has(key))
this.set(key, new Set)
return super.get(key)
}
}
let tagIndex = new SetMap()
class Sample {
tag(...tags) {
for (let t of tags) {
tagIndex.get(t).add(this)
}
}
isTagged(...tags) {
return tags.some(t => tagIndex.get(t).has(this))
}
}
当然,要取消标记(删除标签),尤其是适当的序列化,还需要做更多的工作。
索引本身不会立即加快isTagged
的速度,但是会极大地优化查询“查找由X和/或Y标记的对象”。