opentypejs / opentype.js

Read and write OpenType fonts using JavaScript.
https://opentype.js.org/
MIT License
4.37k stars 467 forks source link

Massive memory consuming when require('opentype.js') is run #333

Open minsikim opened 6 years ago

minsikim commented 6 years ago

Massive memory consuming when require('opentype.js') is run in html of electron app I'm trying to use this library, but when I add

const opentype = require('opentype.js');

to my code. and It runs. but when I try to open DevTools it consumes all of my memory 5.6GB and it crashes.

I'm on a Electron project. I tried the code in the Main process and the renderer process and within the html code. All the same problem happens.

Environment

Version used: 0.8.0 Font used: none Node version: v8.10.0 Operating System and version (desktop or mobile): Windows 8.1/10, and OSX

Jolg42 commented 6 years ago

Hi @minsikim

Interesting... Actually we just released 0.8.0 so maybe you could try to install the precedent version 0.7.3 and let us know if you have the same issue?

minsikim commented 6 years ago

@Jolg42 Thank you for the fast response

Unfortunately, I just tried out 0.7.3 and It's still not working. both Windows and Mac. I think something is looping through... and it's definitely an Electron + Opentype.js issue. I tried to import only opentype.Font as well. but it also seems to take all memory possible.

Jolg42 commented 6 years ago

I won't have the time to investigate this issue unfortunately but you should add a link to you repository if it's public as an example.

I guess the best way to know what's happening will be to record the memory consumption and see where it's being allocated.

You could try: https://electronjs.org/docs/tutorial/debugging-main-process https://github.com/sindresorhus/electron-debug

minsikim commented 6 years ago

Solved it by detuoring opentype variable through main process and passing it with remote module in electron

//in electron main process
global.opentype = require('opentype.js');
let mainWindow = new BrowserWindow();
mainWindow.webContents.send('init-opentype', opentype);
//in renderer process
var opentype = remote.getGlobal('opentype');
console.log(opentype);
>>Object {…}, BoundingBox:(...), Font:(...), Glyph:(...), Path:(...), load:(...).....

but still not sure why it doesn't work directly in the renderer process I'll notify when it all clears up.

@Jolg42 thanks again for advice

minsikim commented 6 years ago

I investigated this problem a little bit more. (I wanted to use const opentype = require('opentype.js'); for performance's sake)

I tried versions through 0.5.0 ~ 0.8.0(opentype.js) This problem happens from 0.7.2 ~0.8.0 I think it may be an issue from bundling configuration.(by rollup.js) (not sure specifically, never used rollup.js before)

electron has a different process layer compared to plain old web apps I suspect that something maybe causing infinite loops while loading the module.

++ electron + opentype.js examples

  1. desktop version of opentype.js glyphInspector(Forked from jcamins/woffviewer) https://github.com/minsikim/woffviewer

    • opentype.js@0.6.9
    • electron-prebuilt@0.36.0
  2. My project(devtools not working) https://github.com/minsikim/paper-app-test/commit/79952951c20ed7d39d8dada76a5b14bab9f69410

    • opentype.js@0.7.2
    • electron@2.0.0-beta.6
  3. My project(devtools working) https://github.com/minsikim/paper-app-test/commit/314414d168b02aec91eca66fb1277491b6c25a940

    • opentype.js@0.6.9
    • electron@2.0.0-beta.6
Jolg42 commented 6 years ago

@minsikim Indeed I found the circular dependency when I updated Rollup.

Could you try to use the version from that branch https://github.com/nodebox/opentype.js/tree/circular-dep-fix and let me if it works for you?

minsikim commented 6 years ago

@Jolg42 I tried https://github.com/nodebox/opentype.js/tree/circular-dep-fix, unfortunately it's not working yet.

Jolg42 commented 6 years ago

😞 Well I merged it in master. (Btw, I edited your previous comments because the url were broken.)

ardentia commented 7 months ago

This issue is old and I don't know if it has been already investigated but I can confirm that opentype consumes quite a lot of memory when loaded. For context, I am using pdfjs which depends on opentype. Currently installed opentype version is: 1.3.4

chrome_ZwLFOSCqDK

Connum commented 7 months ago

@ardentia Thanks for the update! Could you somehow test using the current master? 1.3.4 is quite old but there hasn't been a new release to npm yet.

ardentia commented 7 months ago

@Connum thanks for the quick reply. I uninstalled opentype.js@1.3.4 and instead installed the master branch, so now the entry in package.json looks like this:

"opentype.js": "github:opentypejs/opentype.js",

I assumed that the bin dir contains whatever is needed for the project to work out of the box, so I didn't run any build scripts. Let me know if I missed anything.

The allocation timeline snapshot with the latest master looks like this:

chrome_qYncazk9BS

To be fair, the shallow size this time is bit less but it still seems to be a lot.

I took a look at the pdfjs implementation and it also requires the opentype package the same way @minsikim did initially: https://github.com/rkusa/pdfjs/blob/b6cdd70c64611d0e1369ad928028b2cf51009379/lib/font/otf.js#L3

Connum commented 7 months ago

The bin files are only used for testing, in order to get the bundled files, run npm run build and npm run dist and you'll find them inside a dist folder. However, if pdfjs bundles opentype.js instead of having it as a peer dependency, that won't influence the instance that's used internally (and it should run without opentype.js being installed as a dependency of its own). You could also load your font in https://opentype.js.org and see what the memory footprint is there.

We definitely need to do performance optimizations. If you can find out which parts cause the highest memory usage, we could prioritise optimizations there.

Connum commented 7 months ago

I just hat a chance to look at your screenshots now on my computer instead of my phone. What you're seeing there is not the memory that opentype consumes, but diffferent bundles (including opentype.js) whose source code in string format seems to take up that much combined. Opentype.js is indeed the largest one, but that has nothing to say about how it performs during operation.