Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Crash on svg optimization #2075

Open
YuanLinMtp opened this issue Sep 21, 2024 · 7 comments
Open

Crash on svg optimization #2075

YuanLinMtp opened this issue Sep 21, 2024 · 7 comments
Labels

Comments

@YuanLinMtp
Copy link

YuanLinMtp commented Sep 21, 2024

node: 20.10.0
svgo: 3.3.2

Hi
We've encountered an issue while using SVGO to optimize SVG inputs. In the following case, the optimization function hangs, causing really high CPU usage and eventually leading the server to crash after some time.

Through step-by-step debugging, we identified a set of plugins that take an unusually long time to run, effectively blocking the entire process (marked as '// too long' in the code snippet below).

Could someone offer any advice on this please?

A more general question related to this issue: is there a way to implement a timeout mechanism to abort the process if it takes too long, and eventually release the occupied resources?

Thanks a lot!

VISUELDOS-24-42437

		const optimizedSvg = optimize(svg, {
			multipass: true,
			plugins: [
				{ name: 'removeDoctype' },
				{ name: 'removeXMLProcInst' },
				{ name: 'removeComments' },
				{ name: 'removeMetadata' },
				{ name: 'removeEditorsNSData' },
				{ name: 'cleanupAttrs' },
				{ name: 'mergeStyles' },
				{ name: 'inlineStyles', params: { onlyMatchedOnce: false } },  // too long 
				{ name: 'minifyStyles' },
				{ name: 'cleanupIds' },
				{ name: 'removeUselessDefs' },
				{ name: 'cleanupNumericValues' },
				{
					name: 'convertColors',
					params: {
						shorthex: false,
					},
				},
				{
					name: 'removeUnknownsAndDefaults',
					params: { defaultAttrs: false },
				},  // too long 
				{ name: 'removeNonInheritableGroupAttrs' },  // too long 
				{ name: 'removeUselessStrokeAndFill' },
				{ name: 'cleanupEnableBackground' },
				{ name: 'removeHiddenElems' },  // too long 
				{ name: 'removeEmptyText' },
				{ name: 'convertShapeToPath' },
				{ name: 'convertEllipseToCircle' },
				{ name: 'moveElemsAttrsToGroup' },
				{ name: 'moveGroupAttrsToElems' },
				{ name: 'collapseGroups' },
				{ name: 'convertPathData' },  // too long 
				{ name: 'convertTransform' },
				{ name: 'removeEmptyAttrs' },
				{ name: 'removeEmptyContainers' },
				{ name: 'removeUnusedNS' },
				{ name: 'mergePaths' },
				{ name: 'sortAttrs' },
				{ name: 'sortDefsChildren' },
				{ name: 'removeTitle' },
				{ name: 'removeDesc' },
			],
		});
@YuanLinMtp YuanLinMtp added the bug label Sep 21, 2024
@KTibow
Copy link
Contributor

KTibow commented Sep 21, 2024

That is the largest SVG I've ever seen
It embeds hundreds of clip paths and images
It's not just SVGO that it troubles, when I tried to open it with Inkscape it took a few minutes and almost crashed twice

I find it unlikely that SVGO would be able to efficiently handle this SVG at any point, so if I were you I would:

  • first, try to get a more simplified, less bloated version of it
  • alternatively, just use a raster version (it's actually smaller this way, at 10-20% of the size depending on resolution)
  • if for some reason you need to keep using the SVG, exclude it from your SVGO inputs

@YuanLinMtp
Copy link
Author

hi @KTibow ,

Thanks for your reply!

I really appreciate everything the SVGO library provides.
I agree with you that it's relatively uncommon to encounter an SVG file over 3MB in size with such intricate details. Typically, we're more likely dealing with simpler SVGs like logos. However, since our application involves public user input, where designers can upload files, we don't have full control over the complexity or size of the SVGs being submitted.

This is why I asked about the possibility of adding a timeout configuration. Do you have any additional suggestions for avoiding situations like this?

Thanks in advance!

@KTibow
Copy link
Contributor

KTibow commented Sep 21, 2024

Why not only run optimization on small files or implement the timeout inside whatever program is falling SVGO

@YuanLinMtp
Copy link
Author

I’d like to try a timeout solution, but it seems that once optimization starts on such a large input, SVGO quickly consumes CPU resources, leading to server crashes.

Perhaps the simplest solution would be to just limit the size of uploaded SVGs.

@GreLI
Copy link
Member

GreLI commented Sep 22, 2024

Try disabling mergePaths–it has some some complicated logic to check for intersections which may be too much for your case.

@johnkenny54
Copy link
Contributor

This doesn't have much to do with the file size. SVGO doesn't handle styles efficiently, and this file has about 8500 style rules.

I've been looking into some of the scalability problems with SVGO, and working on a version that handles this better - https://www.npmjs.com/package/svgo-ll. It still takes almost a minute on a not particularly fast laptop. Almost all of the time is spent inlining the styles, other than that it's pretty fast.

The inlining could be sped up significantly for this file, but it may be enough of a special case that it's not worth it.

Compression on the current version is 22.7%.

@YuanLinMtp
Copy link
Author

@johnkenny54 Thanks for your feedback! This particular SVG comes from one of our clients and is one of the most complex we've dealt with so far. Since then, we've implemented a file size limit for SVGs (up to 1.5MB) to keep things running smoothly. If SVGO2 has stable releases, we'll definitely run some benchmarks later!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants