The memory is not released when using Sharp in Electron (Some Linux distributions)
Possible bug
Is this a possible bug in a feature of sharp, unrelated to installation?
- [x] Running
npm install sharpcompletes without error. - [x] Running
node -e "require('sharp')"completes without error.
Are you using the latest version of sharp?
- [x] I am using the latest version of
sharpas reported bynpm view sharp dist-tags.latest.
What is the output of running npx envinfo --binaries --system --npmPackages=sharp --npmGlobalPackages=sharp?
System:
OS: Linux 6.8 Ubuntu 24.04.3 LTS 24.04.3 LTS (Noble Numbat)
CPU: (16) x64 AMD Ryzen 7 5700G with Radeon Graphics
Memory: 24.10 GB / 31.19 GB
Container: Yes
Shell: 5.2.21 - /bin/bash
Binaries:
Node: 22.13.1 - ~/.nvm/versions/node/v22.13.1/bin/node
npm: 10.9.2 - ~/.nvm/versions/node/v22.13.1/bin/npm
pnpm: 8.5.1 - /usr/bin/pnpm
npmPackages:
sharp: ^0.34.4 => 0.34.4
Does this problem relate to file caching?
- [x] Adding
sharp.cache(false)does not fix this problem.
What are the steps to reproduce?
git clone https://github.com/ollm/electron-sharp-memory.git
cd electron-sharp-memory
npm install
npm start
Currently, when using Sharp on some Linux distributions through Electron, memory is not being released. To try to fix this, I've tested using global.gc() or moving Sharp into node:worker_threads, but neither worked.
When running the same Sharp script directly in Node, memory usage grows to about 200-500 MB and then stabilizes, but inside Electron it keeps increasing without stopping.
I've read issues #667 and #955.
It may also be related to #4351 and https://github.com/electron/electron/issues/46323
In Electron, Ubuntu 24.04.3 (Memory increases):
https://github.com/user-attachments/assets/18457f21-00d7-484a-8154-817514a34e1b
In Node, Ubuntu 24.04.3 (Memory remains stable):
node --expose-gc ./www/js/app.js
RSS: 0.06 GB, Heap Total: 0.01 GB, Heap Used: 0.01 GB, External: 0.00 GB
RSS: 0.12 GB, Heap Total: 0.01 GB, Heap Used: 0.01 GB, External: 0.00 GB
RSS: 0.17 GB, Heap Total: 0.01 GB, Heap Used: 0.01 GB, External: 0.00 GB
RSS: 0.19 GB, Heap Total: 0.01 GB, Heap Used: 0.01 GB, External: 0.00 GB
RSS: 0.19 GB, Heap Total: 0.01 GB, Heap Used: 0.01 GB, External: 0.00 GB
RSS: 0.19 GB, Heap Total: 0.01 GB, Heap Used: 0.01 GB, External: 0.00 GB
...
In Electron, Arch Linux (Memory remains stable, but not when running inside a Flatpak package):
https://github.com/user-attachments/assets/0bebd7fb-eed2-40f7-84c4-d7c68a30c05b
What is the expected behaviour?
That memory usage should be similar to running Sharp directly in Node.
Please provide a minimal, standalone code sample, without other dependencies, that demonstrates this problem
This is probably due to https://www.electronjs.org/blog/v8-memory-cage and the increased memory fragmentation it brings.
Please see https://github.com/electron/electron/issues/35241 for discussion from other frustrated Electron users and suggestions for using a build of Electron without the memory cage feature.
Hi Lovell, thanks for your response!
I'm not sure if this is related to Memory Cage, I have tested the sample app with Electron v20.3.12, and the problem persists.
I also tested old Sharp v33.5 with the latest version of Electron, and the issue does not occur in this case on Ubuntu 24.04.3.
This still sounds like memory fragmentation, possibly there have also been changes in the way V8 releases memory back to the OS in more recent versions.
Thanks for the insight! Is there anything I can do on my side to mitigate this in my Electron app?
Electron exposes control over the underlying V8 engine via --js-flags.
The semi-space is for short-lived data and the old-space is for long-lived data.
--max-semi-space-size (max size of a semi-space (in MBytes), the new space consists of two semi-spaces)
type: size_t default: --max-semi-space-size=0
--max-old-space-size (max size of the old space (in Mbytes))
type: size_t default: --max-old-space-size=0
Thanks, I've tried these flags, but they don't make any difference.
In the end, I found a temporary solution while this problem exists, I'm running Sharp inside a node:child_process.fork. Although the memory issue still occurs, I can kill the process, and doing so frees the memory (unlike node:worker_threads, which I initially tried, where killing it does not free the memory). So, after processing every X images, the process is killed and a new one is started (currently, I keep 2 open to switch between them with minimal downtime).
I've updated the example app with a simple implementation of this, so anyone encountering the same problem can use it as a reference.
https://github.com/ollm/electron-sharp-memory/commit/c1f53ad57d31a3583eaeaba706bfa4b29c9d9b55
sharp-fork.js
child-fork.js
Usage:
const childFork = require('./child-fork.js');
childFork.config({
jobsPerCycle: 10,
idleTimeout: 5000,
});
const options = {
input: './image.jpg',
pipeline: [
{fn: 'jpeg', args: [{quality: 95}]},
{fn: 'resize', args: [100, 100]},
{fn: 'toBuffer', args: []}
]
};
const buffer = await childFork.sharp(options);
Using node:child_process.fork in the sample app
https://github.com/user-attachments/assets/a09dac67-c7ab-4f37-94f8-738e6a86eff9