# Is .dispose() even needed?

**URL:** <https://discourse.threejs.org/t/is-dispose-even-needed/3482>\
**Category:** Questions\
**Tags:** dispose, scene\
**Created:** [July 19, 2018, 12:33pm UTC](https://discourse.threejs.org/t/is-dispose-even-needed/3482 "2018-07-19T12:33:05Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![ligazetom](https://avatars.discourse-cdn.com/v4/letter/l/b5ac83/32.png) [@ligazetom](https://discourse.threejs.org/u/ligazetom)\
**Post date:** [July 19, 2018, 12:33pm UTC](https://discourse.threejs.org/t/is-dispose-even-needed/3482/1 "2018-07-19T12:33:05Z")

</div>

Hey,

why is dispose() method needed? I see now I have memory leaks if I ramp up the number of objects, but if I keep no other references to the object, why won’t garbage collector get rid of it?

---

<div class="post-metadata">

**Author:** ![TheJim01](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/thejim01/32/2007_2.png) [@TheJim01](https://discourse.threejs.org/u/TheJim01)\
**Post date:** [July 19, 2018, 1:12pm UTC](https://discourse.threejs.org/t/is-dispose-even-needed/3482/2 "2018-07-19T13:12:38Z")

</div>

For `BufferGeometry`, the `dispose` method triggers an event, which calls [`onGeometryDispose`](https://github.com/mrdoob/three.js/blob/0949e59f3a4978efc39d7c1366d26274b7d9af82/src/renderers/webgl/WebGLGeometries.js#L14). This method ensures the `attribute` references are removed from the object (freed for garbage collection). It also does bookkeeping, tracking the number of geometries handled by three.js (line 57).

For `Material` objects, the `dispose` method triggers an event, which follows a chain of methods. It first calls [`onMaterialDispose`](https://github.com/mrdoob/three.js/blob/0949e59f3a4978efc39d7c1366d26274b7d9af82/src/renderers/WebGLRenderer.js#L536), which calls [`deallocateMaterial`](https://github.com/mrdoob/three.js/blob/0949e59f3a4978efc39d7c1366d26274b7d9af82/src/renderers/WebGLRenderer.js#L548), which finally calls [`releaseMaterialProgramReference`](https://github.com/mrdoob/three.js/blob/0949e59f3a4978efc39d7c1366d26274b7d9af82/src/renderers/WebGLRenderer.js#L557) (all in `three.js/src/renderers/WebGLRenderer.js`).

In `deallocateMaterial` it [removes the material reference from the `WebGLProperties`](https://github.com/mrdoob/three.js/blob/0949e59f3a4978efc39d7c1366d26274b7d9af82/src/renderers/webgl/WebGLProperties.js#L24).

In `releaseMaterialProgramReference`, it un-sets the material’s `program` (line 561), then [releases the program from the program cache](https://github.com/mrdoob/three.js/blob/0949e59f3a4978efc39d7c1366d26274b7d9af82/src/renderers/webgl/WebGLPrograms.js#L284) (line 565).

**TL;DR:** Even though your `Mesh` may get garbage collected, that does not mean that the low-level supporting objects were also released, because some of those low-level objects are referenced in other parts of three.js which aren’t obvious on the surface. Calling `dispose` ensures these low-level objects are properly freed from internal caches, allowing them to be fully garbage-collected.

(All code in reference to three.js r94.)

---

<div class="post-metadata">

**Author:** ![ligazetom](https://avatars.discourse-cdn.com/v4/letter/l/b5ac83/32.png) [@ligazetom](https://discourse.threejs.org/u/ligazetom)\
**Post date:** [July 19, 2018, 1:42pm UTC](https://discourse.threejs.org/t/is-dispose-even-needed/3482/3 "2018-07-19T13:42:40Z")

</div>

Ah ok, I came from C/C++ to Javascript and I was relieved no more deallocation for me, didn’t know functions could create variables that won’t get collected. Great, thanks!

---

<div class="post-metadata">

**Author:** ![TheJim01](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/thejim01/32/2007_2.png) [@TheJim01](https://discourse.threejs.org/u/TheJim01)\
**Post date:** [July 19, 2018, 4:28pm UTC](https://discourse.threejs.org/t/is-dispose-even-needed/3482/4 "2018-07-19T16:28:03Z")

</div>

> [@ligazetom](#):
>
> didn’t know functions could create variables that won’t get collected

I don’t know if that’s _conceptually_ correct. We may already be on the same page, but I’ll offer an example just in case there’s some misunderstanding.

```javascript
class Position {
  constructor( x, y, z ) {
    this.x = x
    this.y = y
    this.z = z
  }
}

class PointCache {
  constructor() {
    this.points = []
  }
  add( point ) {
    this.points.push( point )
  }
  remove( point ) {
    let idx = this.points.indexOf( point )
    if (idx > -1) {
      this.points.splice( idx, 1 )
    }
  }
}

class Example {
  constructor( point, cache ) {
    this.point = point
    this.cache = cache
    cache.add( point )
  }
  dispose() {
    this.point = undefined
  }
}

// Instantiate the objects
let pt = new Point( 1, 2, 3 )
let c = new PointCache()
let ex = new Example( pt, c )

// Setting these to undefined doesn't release the objects to garbage collection
// because other objects still hold references to them
pt = undefined
c = undefined

// Calling dispose on the Example to prepare it and its sub-objects for garbage collection
ex.dispose()
ex = undefined
// The Example is now ready to be collected, but...

```

…the above code is leaky. `PointCache` will retain a reference to `pt`, even though the other references to `pt` were set to `undefined`. Therefore, the `Point` represented by `pt` will never get garbage collected.

But if we change `Example.dispose` like this…

```javascript
  dispose() {
    this.cache.remove( this.point )
    this.point = undefined
  }

```

…then the `PointCache` will discard its reference to the `Point`. When `dispose` finishes, all references to the `Point` have been nullified, so the `Point` is freed for garbage collection.

---

<div class="post-metadata">

**Author:** ![pailhead](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pailhead/32/85_2.png) [@pailhead](https://discourse.threejs.org/u/pailhead)\
**Post date:** [July 19, 2018, 5:20pm UTC](https://discourse.threejs.org/t/is-dispose-even-needed/3482/5 "2018-07-19T17:20:07Z")

</div>

It also removes stuff from the GPU.

---

<div class="post-metadata">

**Author:** ![TheJim01](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/thejim01/32/2007_2.png) [@TheJim01](https://discourse.threejs.org/u/TheJim01)\
**Post date:** [July 19, 2018, 5:22pm UTC](https://discourse.threejs.org/t/is-dispose-even-needed/3482/6 "2018-07-19T17:22:22Z")

</div>

> [@pailhead](#):
>
> It also removes stuff from the GPU.

Maybe I didn’t look at the code closely enough, but I didn’t see where it was doing that. Could you link to where it tells the GPU to discard buffers?

Edit: Nevermind, I found it. The `attributes.remove` call ends up calling [`gl.deleteBuffer`](https://github.com/mrdoob/three.js/blob/0949e59f3a4978efc39d7c1366d26274b7d9af82/src/renderers/webgl/WebGLAttributes.js#L108), and [materials end up calling `gl.deleteProgram`](https://github.com/mrdoob/three.js/blob/0949e59f3a4978efc39d7c1366d26274b7d9af82/src/renderers/webgl/WebGLProgram.js#L638).

---

<div class="post-metadata">

**Author:** ![pailhead](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/pailhead/32/85_2.png) [@pailhead](https://discourse.threejs.org/u/pailhead)\
**Post date:** [July 19, 2018, 5:28pm UTC](https://discourse.threejs.org/t/is-dispose-even-needed/3482/7 "2018-07-19T17:28:42Z")

</div>

I actually thought that you **only** need it for that. Even when you call `foo.dispose()` you still have foo. You have to do `foo = undefined` to release it.

The webgl stuff though on the other hand has absolutely no idea what you’re doing with your garbage collection in javascript, probably doesn’t know it exists. So if you release something that holds pointers to your webgl objects… you cant release those objects, you dont know how to access them.

---

<div class="post-metadata">

**Author:** ![TheJim01](https://yyz1.discourse-cdn.com/flex035/user_avatar/discourse.threejs.org/thejim01/32/2007_2.png) [@TheJim01](https://discourse.threejs.org/u/TheJim01)\
**Post date:** [July 19, 2018, 5:55pm UTC](https://discourse.threejs.org/t/is-dispose-even-needed/3482/8 "2018-07-19T17:55:42Z")

</div>

At least until you close the tab, and the entire context gets discarded.

Yeah, managing JavaScript object references can be a pain, but I can definitely see why the primary purpose of `dispose` is to deallocate _ **GPU** _ resources.
