混合类型还是保留类型性能更好?

Is it more performant to mix types or to keep types?

我想知道,对于 v8,在存储 class 属性时,使用一个混合类型的变量还是每个类型一个变量的性能更高? 考虑以下片段(用 TypeScript 编写,以便更清楚地区分):

type Type = "number" | "string";
type FooChild = number | string;

class Foo {
    val?: FooChild;
    _type: Type = "number";
    constructor(initialValue: FooChild, initialType: Type) {
        this.val = initialValue;
        this._type = initialType;
    }
    getValue() {
        return this.val;
    }
}

class Bar {
    str?: string;
    val?: number;
    _type: Type = "number";
    constructor(initialValue: FooChild, initialType: Type) {
        if (initialType === "string") this.str = initialValue as string;
        else this.val = initialValue as number;
        this._type = initialType;
    }
    getValue() {
        return this._type === "string" ? this.str : this.val;
    }
}

Afaik 两者都应该有优势或默认值。使用一个变量会有这样的问题,即 JS 引擎可能会对类型做出假设,针对该类型对其进行优化,并且必须取消优化它,事实证明它实际上也接受数字。但是使用多个变量会使每个实例中都存在很多垃圾变量,而占用大量 space 的内存却一无所获。

我做了 this little benchmark 看看一个是否优于另一个,似乎只使用一个变量的性能更高。但我也知道这样的基准通常不能很好地复制现实世界的情况,所以我正在寻求更多知识渊博的程序员的确认。

KISS -- 做对你来说容易的事情,程序员。 JS/Perl/PHP/etc 等解释性语言的开销很大。

我喜欢统计源中的令牌数量来判断性能。更短的代码也减少了我搞砸的地方。

当然,明智地使用函数(方法)、类等是有充分理由的

(这里是 V8 开发人员。)定义“更高性能”:更快地创建此类对象,更快地读取它们的属性,更快地修改它们?您通常可以以另一个为代价来改进其中一个操作:-)

在实践中的大多数情况下,我希望这两种方法的行为足够相似以至于无关紧要,因此您可以使用更简单的方法。

的确,在某些情况下,当给定对象 属性 始终具有数字作为其值时,引擎可以应用某些技巧和快捷方式,并且可能(我没有尝试过)制定一个微基准,使其看起来具有重大影响。但是,如果您的用例中的对象自然必须存储各种类型的属性,那么手动对区别进行建模(如您的示例所做的那样)会带来其自身的性能成本,因此很可能无法获得回报。

TL;DR:别担心,让引擎做它的事。当你有一个完整的应用程序并且对其性能不满意时,分析它(运行 在现实条件下)并找到最容易实现的成果,即通过投入一些努力(可能还有代码复杂性)来改进事物而获得最大影响的瓶颈。我怀疑将一个 属性 分成两个将是您可以做的更有效的优化之一,它甚至可能会损害整体性能(尽管我可以想象在某些非常特定的情况下它可能会有所帮助)。

[旁注:请忽略您链接的微基准测试,无论其结果如何。首先,它的两个版本分配 instance.str = randint(...(或 .val,或 .bar)的方式显然违反了 class 的合同,分配是非法的strval 而不更新 _type。其次,在对此类微基准测试的结果进行 任何事情 之前,您需要确保它实际衡量的是您认为它衡量的内容。 randint 花费的时间百分比是多少?对象是否实际分配,或者优化编译器是否意识到它们从未被使用并完全消除了分配?第三,“一次分配,一千次分配,更改类型的概率为 50%,零读取”真的代表您感兴趣的实际工作量吗?除非您深入研究了引擎实际最终做了什么,否则永远不要相信微基准测试!]