(
kernelName: string, numDataIdsBefore: number,
outInfos: TensorInfo[])
| 559 | } |
| 560 | |
| 561 | private checkKernelForMemLeak( |
| 562 | kernelName: string, numDataIdsBefore: number, |
| 563 | outInfos: TensorInfo[]): void { |
| 564 | const numDataIdsAfter = this.backend.numDataIds(); |
| 565 | |
| 566 | // Count the number of data ids associated with the result of the kernel. |
| 567 | let numOutputDataIds = 0; |
| 568 | outInfos.forEach(info => { |
| 569 | // Complex numbers allocate 3 data ids, one for 'real', one for |
| 570 | // 'imaginary', and one for the container that holds the former two. |
| 571 | numOutputDataIds += (info.dtype === 'complex64' ? 3 : 1); |
| 572 | }); |
| 573 | |
| 574 | // Account for the number of moves during kernel execution. A "data move" |
| 575 | // can happen in the middle of a kernel execution, placing a new (key,value) |
| 576 | // pair in the data storage. Since data moves have net zero effect (we |
| 577 | // always remove the data from the old backend), we have to cancel them out |
| 578 | // when detecting memory leaks. |
| 579 | const numMoves = |
| 580 | this.state.numDataMovesStack[this.state.numDataMovesStack.length - 1]; |
| 581 | const dataIdsLeaked = |
| 582 | numDataIdsAfter - numDataIdsBefore - numOutputDataIds - numMoves; |
| 583 | if (dataIdsLeaked > 0) { |
| 584 | throw new Error( |
| 585 | `Backend '${this.backendName}' has an internal memory leak ` + |
| 586 | `(${dataIdsLeaked} data ids) after running '${kernelName}'`); |
| 587 | } |
| 588 | } |
| 589 | |
| 590 | /** |
| 591 | * Internal helper method to execute a kernel Func |
no test coverage detected