将文字/对象/类传递给具有数千次调用的函数的内存含义

Memory implications of passing literals/objects/classes to functions with thousands of calls

本文关键字:调用 千次 函数 内存 对象 文字      更新时间:2023-09-26

Background

我正在编写的框架涉及一个Figure类调用Renderer类上的函数SetTranslate( x, y )。反过来,Renderer类必须存储(x, y)传递给SetTranslate的参数。

可能有数千个

数字,因此单个用户操作可能会触发数千个此类调用。

与此类调用的文字相比,我有点担心使用对象或类的内存影响(和垃圾回收(。

具体如下。

所有选项相同

请原谅我在下面的代码中使用类似类的语法,但这对实际问题没有区别。可以轻松地用标准的JS函数和原型语法替换Class语法。

在下面的所有选项中,figure类是使用属性rect构造的,该属性是类Rect的新实例:

Figure = new Class({
    // Constructor 
    initialize: function() {
        this.rect = new Rect( 0, 0, 10, 10 );
    }    
});

选项 1 - 使用基元值参数

Figure 类:

Figure = new Class({
    render: function( aRenderer ) {
        aRenderer.setTranslate( this.rect.x, this.rect.y );
    }       
});

渲染器类:

Renderer = new Class({
    // Constructor 
    initialize: function() {
        this.translation = {
            x: 0,
            y: 0
        };
    },
    setTranslate: function( x, y ) {
        this.translation.x = x;
        this.translation.y = y;
    }       
});

关注

如果我没记错的话,这里不涉及内存分配,所以没有真正的问题 - 这很简单。

选项 2 - 使用对象文本

Figure 类:

Figure = new Class({    
    render: function( aRenderer ) {
        aRenderer.setTranslate( { x: this.rect.x, y: this.rect.y } );
    }       
});

渲染器类:

Renderer = new Class({
    // Constructor 
    initialize: function() {
        this.translation = {
            x: 0,
            y: 0
        };
    },
    setTranslate: function( aTranslation ) {
        this.translation = aTranslation;
    }       
});

关注

我的问题是,如果使用

        aRenderer.setTranslate( { x: this.rect.x, y: this.rect.y } );

将创建一个新对象。此外,通过执行

        this.translation = aTranslation;

以前的对象现在不会进入垃圾回收吗?

选项 3 - 使用类实例

Figure 类:

Figure = new Class({    
    render: function( aRenderer ) {
        // rect.getTopLeft() returns new Point( x, y );
        aRenderer.setTranslate( this.rect.getTopLeft() );
    }       
});

渲染器类:

Renderer = new Class({
    // Constructor 
    initialize: function() {
        this.translation = new Point( 0, 0 );
    },
    setTranslate: function( aTranslation ) {
        this.translation = aTranslation;
    }       
});

关注

getTopLeft() 返回new Point( x, y )这一事实明确表明内存分配将是其中的一部分:

        // rect.getTopLeft() returns new Point( x, y );
        aRenderer.setTranslate( this.rect.getTopLeft() );

很明显,有了这一行:

        this.translation = aTranslation;

上一个translation对象(类(将进入垃圾回收。

这与选项 2 有什么不同吗?

而且由于这对我来说是理想的解决方案(Point 类具有可能对setTranslate中的其他事情有用的方法(,考虑到每个用户操作可能有数千个此类调用(与选项 1 和 2 相比,也就是说(会是一个问题吗?

我想你会发现对象池是控制这样的东西的内存行为的一种非常有效的方法。预先分配并发所需的对象数,然后重用它们以避免垃圾回收问题。

为了回答你的问题,

aRenderer.setTranslate( { x: this.rect.x, y: this.rect.y } );

创建一个新对象,是的,在您的示例中,以前的翻译对象将有资格使用 GC(假设没有其他引用(。