• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

excaliburjs / Excalibur / 14804036802

02 May 2025 09:58PM UTC coverage: 5.927% (-83.4%) from 89.28%
14804036802

Pull #3404

github

web-flow
Merge 5c103d7f8 into 0f2ccaeb2
Pull Request #3404: feat: added Graph module to Math

234 of 8383 branches covered (2.79%)

229 of 246 new or added lines in 1 file covered. (93.09%)

13145 existing lines in 208 files now uncovered.

934 of 15759 relevant lines covered (5.93%)

4.72 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

3.13
/src/engine/GarbageCollector.ts
1
export interface GarbageCollectionOptions {
2
  /**
3
   * Textures that aren't drawn after a certain number of milliseconds are unloaded from the GPU
4
   * Default 60_000 ms
5
   */
6
  textureCollectInterval?: number; // default 60_000 ms
7
  // TODO future work to integrate the font and text configuration, refactor existing collection mechanism
8
  // /**
9
  //  * Font pre-renders that aren't drawn after a certain number of milliseconds are unloaded from the GPU
10
  //  * Default 60_000 ms
11
  //  */
12
  // fontCollectInterval: number; // default 60_000 ms
13
  // /**
14
  //  * Text measurements that aren't used after a certain number of milliseconds are unloaded from the GPU
15
  //  * Default 60_000 ms
16
  //  */
17
  // textMeasurementCollectInterval: number; // default 60_000 ms
18
}
19

20
export const DefaultGarbageCollectionOptions: GarbageCollectionOptions = {
1✔
21
  textureCollectInterval: 60_000
22
  // TODO future work to integrate the font and text configuration, refactor existing collection mechanism
23
  // fontCollectInterval: 60_000,
24
  // textMeasurementCollectInterval: 60_000,
25
};
26

27
export interface GarbageCollectorOptions {
28
  /**
29
   * Returns a timestamp in milliseconds representing now
30
   */
31
  getTimestamp: () => number;
32
}
33

34
export class GarbageCollector {
35
  private _collectHandle: number;
UNCOV
36
  private _running = false;
×
UNCOV
37
  private _collectionMap = new Map<any, [type: string, time: number]>();
×
UNCOV
38
  private _collectors = new Map<string, [(resource: any) => boolean, interval: number]>();
×
39

UNCOV
40
  constructor(public options: GarbageCollectorOptions) {}
×
41

42
  /**
43
   *
44
   * @param type Resource type
45
   * @param timeoutInterval If resource type exceeds interval in milliseconds collect() is called
46
   * @param collect Collection implementation, returns true if collected
47
   */
48
  registerCollector(type: string, timeoutInterval: number, collect: (resource: any) => boolean) {
UNCOV
49
    this._collectors.set(type, [collect, timeoutInterval]);
×
50
  }
51

52
  /**
53
   * Add a resource to be tracked for collection
54
   * @param type
55
   * @param resource
56
   */
57
  addCollectableResource(type: string, resource: any) {
UNCOV
58
    this._collectionMap.set(resource, [type, this.options.getTimestamp()]);
×
59
  }
60

61
  /**
62
   * Update the resource last used timestamp preventing collection
63
   * @param resource
64
   */
65
  touch(resource: any) {
UNCOV
66
    const collectionData = this._collectionMap.get(resource);
×
UNCOV
67
    if (collectionData) {
×
UNCOV
68
      this._collectionMap.set(resource, [collectionData[0], this.options.getTimestamp()]);
×
69
    }
70
  }
71

72
  /**
73
   * Runs the collection loop to cleanup any stale resources given the registered collect handlers
74
   */
UNCOV
75
  public collectStaleResources = (deadline?: IdleDeadline) => {
×
UNCOV
76
    if (!this._running) {
×
UNCOV
77
      return;
×
78
    }
UNCOV
79
    for (const [type, [collector, timeoutInterval]] of this._collectors.entries()) {
×
UNCOV
80
      const now = this.options.getTimestamp();
×
UNCOV
81
      for (const [resource, [resourceType, time]] of this._collectionMap.entries()) {
×
UNCOV
82
        if (type !== resourceType || time + timeoutInterval >= now) {
×
UNCOV
83
          continue;
×
84
        }
85

UNCOV
86
        const collected = collector(resource);
×
UNCOV
87
        if (collected) {
×
UNCOV
88
          this._collectionMap.delete(resource);
×
89
        }
90
      }
91
    }
92

UNCOV
93
    this._collectHandle = requestIdleCallback(this.collectStaleResources);
×
94
  };
95

96
  /**
97
   * Force collect all resources, useful for shutting down a game
98
   * or if you know that you will not use anything you've allocated before now
99
   */
100
  public forceCollectAll() {
UNCOV
101
    for (const [_, [collector]] of this._collectors.entries()) {
×
UNCOV
102
      for (const [resource] of this._collectionMap.entries()) {
×
UNCOV
103
        const collected = collector(resource);
×
UNCOV
104
        if (collected) {
×
UNCOV
105
          this._collectionMap.delete(resource);
×
106
        }
107
      }
108
    }
109
  }
110

111
  running(): boolean {
112
    return this._running;
×
113
  }
114

115
  /**
116
   * Starts the garbage collection loop
117
   */
118
  start() {
UNCOV
119
    this._running = true;
×
UNCOV
120
    this.collectStaleResources();
×
121
  }
122

123
  /**
124
   * Stops the garbage collection loop
125
   */
126
  stop() {
UNCOV
127
    this._running = false;
×
UNCOV
128
    cancelIdleCallback(this._collectHandle);
×
129
  }
130
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc