我目前为在node.js中运行的C API编写了JS包装器。原始的API具有数百种不同的结构。
原始的API样式如下:
MYAPI a = {};
a.prop = 2;
...
JS版本如下:
let a = new MYAPI();
a.prop = 2;
当上面的JS示例放入循环中时,它变得很昂贵-每个结构的C ++包装器代码都非常昂贵,某些结构具有约50个成员。但是,如果可以重用一个类或进行堆栈分配怎么办?
我想到了这样的东西:
let a = MYAPI();
a.prop = 2;
在C ++包装器代码中,然后我可以检测到何时在没有'new'关键字的情况下调用了一个类。如果没有构造函数调用,请使用缓存的版本(此特定代码位置始终相同)。
这里的问题是,要进行“堆栈分配”,用户必须将唯一的id传递给类调用,例如:
let a = MYAPI(3);
让用户每次都确定唯一的ID是不可接受的
我认为最好的方法是:
let a = MYAPI(_STACK_OFFSET_);
// _STACK_OFFSET_ returns a unique number for this specific source code location, never changes
或者只是:
let a = MYAPI(); // always the same object at this source code location
另一种解决方案是在全局级别创建和缓存所有必需的类,然后在实际代码中使用它们-但是以我的经验,这很快就变得一团糟。
let $0 = new MYAPI();
(function updateLoop() {
setTimeout(updateLoop, 0);
let a = $0;
a.prop = 2;
})();
我想要实现的目标:
function test() {
let a = MYAPI();
console.log(a.id); // id is always 0
for (let i = 0; i < 10; ++i) {
let b = MYAPI();
console.log(b.id); // is always 1
};
};
test(); // logs: 0, 1, 1, 1, 1...
test(); // logs: 0, 1, 1, 1, 1...
我花了很多时间寻找解决方案,除了抛出一个错误然后从堆栈跟踪行/列号中获取唯一ID之外,我找不到别的东西-从性能上讲这是不可接受的。
我检查过但无法使用/的其他内容太乱了:
_STACK_OFFSET_
我知道JS不应该像C一样使用,但是我认为这可能是降低GC压力并缩短某些代码路径的便捷解决方案-至少这是一个有趣的实验。
答案 0 :(得分:0)
我得到的是,每次调用javascript函数时,您都希望变量具有唯一值。
说实话,我完全不了解您使用c-wrapper所做的事情,或者在这种情况下您对“堆栈分配”的含义,或者这是否真的是解决性能的最佳方法问题,但我认为这没有关系。
您可以使用以下js:
function MyApiWrapper() {
if (MyApiWrapper.counter === undefined) {
MyApiWrapper.counter = 0;
}
MyApiWrapper.counter++;
return MYAPI(MyApiWrapper.counter);
}
用途如下:
let a = MyApiWrapper();
每次调用MyApiWrapper()函数时,MyApiWrapper.counter var都会单调增加。该函数将返回MYAPI(number)调用的结果,每次调用时该数字都会不同(增加1)。
答案 1 :(得分:0)
我认为让任何缓存依赖于调用它的确切代码行不是一个好主意。相反,此解决方案对您有帮助吗?
function generateCacheId() {
if (generateCacheId.nextCacheId === undefined) {
generateCacheId.nextCacheId = -1;
}
generateCacheId.nextCacheId++;
return MYAPI(generateCacheId.nextCacheId);
}
用途如下:
function test() {
let cacheIdA = generateCacheId();
let a = MYAPI(cacheIdA);
console.log(a.id); // id is always 0
let cacheIdB = generateCacheId();
for (let i = 0; i < 10; ++i) {
let b = MYAPI(cacheIdB);
console.log(b.id); // is always 1
};
};
test(); // logs: 0, 1, 1, 1, 1...
test(); // logs: 0, 1, 1, 1, 1...
通过这种方式,您可以在代码中非常清楚地知道何时要使用缓存的对象,而在不希望使用的地方。可以通过这样一种方式来实现:调用MYAPI的每个代码行都可以拥有自己的缓存,而不必依赖行号。