Sharp: SVGs at higher densities can result in librsvg/libvips overcomputation

Created on 10 Sep 2019  路  11Comments  路  Source: lovell/sharp

What is the output of running npx envinfo --binaries --languages --system --utilities?

System:
    OS: Linux 4.15 Ubuntu 16.04.6 LTS (Xenial Xerus)
    CPU: (4) x64 Intel(R) Core(TM) i5-3210M CPU @ 2.50GHz
    Memory: 584.79 MB / 7.67 GB
    Container: Yes
    Shell: 5.1.1 - /usr/bin/zsh
  Binaries:
    Node: 12.10.0 - /usr/bin/node
    npm: 6.11.2 - ~/.npm-global/bin/npm
  Utilities:
    Make: 4.1 - /usr/bin/make
    GCC: 5.4.0 - /usr/bin/gcc
    Git: 2.7.4 - /usr/bin/git
  Languages:
    Bash: 4.3.48 - /bin/bash
    Perl: 5.22.1 - /usr/bin/perl
    Python: 2.7.12 - /usr/bin/python

What are the steps to reproduce?

take SVG

and this code snippet

sharp('svgs/1.svg', { density: 2400 })
  .resize({ width: 180, height: 180 })
  .toFile('output.png', (err, info) => {
    if (err) console.log('err', err);
    console.log('done');
  });

What is the expected behaviour?

Successfull convertion and resizing.

Are you able to provide a standalone code sample, without other dependencies, that demonstrates this problem?

Yes, above

Are you able to provide a sample image that helps explain the problem?

<svg xmlns="http://www.w3.org/2000/svg" height="203.06" viewBox="0 0 250 203.0594" width="250"><g transform="matrix(1.25 0 0 -1.25 -125.48 427.68)"><g transform="matrix(2.2671 0 0 2.2671 -252.3 -328.71)"><path d="m199.44 224.64-5.8 7.532c-7.379 2.435-12.515 9.104-12.99 16.862l-4.021 3.896c-3.421-1.474-6.425-3.035-6.425-3.035l-10.79 10.83 4.548 9.97-8.133 10.562h12.939l2.505 5.455 6.406 2.585 0.711 1.933 5.192-2.372 1.235 4.315 0.847 0.282c4.107 1.368 8.84 2.105 13.685 2.132 0.139 0.009 1.679-0.018 1.715-0.018 0.181 0 0.937-0.041 0.937-0.041 4.099-0.198 7.949-0.88 11.445-2.028l0.859-0.283 1.137-4.115 1.869 1.412 10.495-3.731 2.532-5.528h13.004l-8.22-10.605 4.479-9.827-10.959-11.284s-3.977 2.492-6.731 3.585l-3.345-3.821c-0.377-7.943-5.782-14.91-13.378-17.249l-5.748-7.414z" fill="#fff"/><path d="m55.564 3.0859-0.05078 4.4883 0.8125 0.83008 0.26953 0.019531 0.01367 1.9336 1.3438 0.03906-0.03711-1.9297 0.25195-0.013672 0.75976-0.75781-0.16211-4.5137c-0.37125-0.03125-1.1992-0.058594-1.1992-0.058594l0.04687 4-0.78711 0.00586-0.01172-4.0234s-0.815-0.019531-1.25-0.019531zm-2.3945 0.10547c-0.45375 0.0275-0.72414 0.019922-1.2441 0.076172l-0.44336 5.5938-0.86914 0.078125 0.50781-5.6172-1.2188 0.11914-0.69141 5.6582-0.88477 0.097656 0.66602-5.6465-1.2363 0.16992-0.94141 6.3945 0.7168 0.68359 1.6348-0.15234 0.70508-0.59961 0.55664 0.48438 1.502-0.08984 0.875-0.87109 0.36523-6.3789zm7.3359 0.10938c-0.2425 0.2625-0.55266 0.47133-0.75391 0.73633 0.115 1.8788 0.21031 3.7634 0.35156 5.6309l0.79492 0.86523 2.2031 0.14844 0.68164-1.041c-0.185-1.7088-0.48758-3.4637-0.64258-5.2949l-0.799-0.8653-1.836-0.1797zm3.666 0.41406 0.97266 7.1758 1.4648 0.18164-0.3125-2.1074 0.88086 0.097656 0.40039 2.1621 1.4688 0.25391l-0.444-2.5942-0.514-0.6133 0.291-0.4043-0.504-2.6113-0.906-1.0469-2.799-0.4942zm-17.315 0.1367-2.882 0.5859c-0.2875 1.655-1.4453 7.0176-1.4453 7.0176 1.0338-0.18 2.1171-0.3343 3.1934-0.4668 0.0775-0.445 0.23047-1.4414 0.23047-1.4414l-1.5391 0.22461 0.2832-1.4785 1.5-0.21484c0.1-0.545 0.1275-0.74141 0.21875-1.3164-0.652 0.0862-0.987 0.1394-1.536 0.2382l0.27148-1.5449 1.4941-0.28125 0.21094-1.3223zm22.018 0.789s0.96359 4.6963 1.4961 7.0801l1.5273 0.29883-0.51172-2.2129 0.93945 0.21094 0.58789 2.2227 1.5078 0.33789-0.91602-3.1699-0.60352-0.66406 0.32617-0.46875-0.69531-2.6035c-0.69-0.20875-1.3379-0.39062-1.3379-0.39062l0.65234 2.6875-0.25195 0.34766-0.52344-0.10547c0-0.0003-0.537-2.1612-0.81-3.2112-0.613-0.1975-1.387-0.3594-1.387-0.3594zm-7.7871 0.013672 0.75195 0.083984 0.41211 4.3438-0.77344-0.060547-0.39062-4.3672zm-18.25 0.025391c-0.485 0.10875-1.4492 0.36523-1.4492 0.36523l-0.36914 1.4277s-0.41008-0.77516-0.58008-1.1602c-0.4625 0.13875-0.8525 0.25734-1.375 0.43359-0.635 2.2788-1.2842 4.5584-1.918 6.8359l1.523-0.348 1.225-4.2067 0.484 1.0489-0.715 2.9238 1.559-0.307 1.615-7.0133zm22.922 0.666 0.74 0.1367 0.348 1.7793-0.828-0.0957-0.26-1.8203zm-60.342 15.679 50.258 65.235 50.594-65.233-100.85-0.002z" transform="matrix(.8 0 0 -.8 154.9 296.4)" fill="#006bb6"/><path d="m236.83 278.07-37.385-48.203-37.138 48.204 74.523-0.001z" fill="#bec0c2"/><path d="m231.44 274.71-0.013 0.032-0.028 0.018-2.393 1.608 0.891 1.702 0.027 0.052-0.024 0.054-3.293 7.216-0.022 0.044-0.046 0.017-8.875 3.161-0.061 0.022-0.053-0.04-2.354-1.796-0.024-0.019-0.012-0.03-0.404-0.988s-3.679 0.924-9.083 1.464c-0.551 0.055-2.021 0.176-4.369 0.361l-0.228 0.018-0.237 0.018-0.055 0.004-0.039-0.039-1.754-1.747 0.002 1.794s-4.975-0.281-8.233-0.724c-3.257-0.444-6.462-1.25-6.462-1.25l-0.589 1.262-0.019 0.04-0.039 0.018-4.188 1.917-0.118 0.053-0.044-0.121-0.488-1.326-0.11 0.266-0.046 0.109-0.11-0.045-5.993-2.402-0.044-0.019-0.021-0.044-11.055-24.288 9.077-9.09 0.423 0.24c0.273 0.156 0.66 0.386 1.098 0.642 1.098 0.648 2.602 1.533 3.32 1.88l0.147 0.07c0.929 0.449 1.396 0.676 5.808 2.564l0.369 0.138c0.004 0.001 0.495 0.192 1.404 0.493 2.423 0.806 8.717 2.679 14.817 2.679h0.069c0.244 0 0.486-0.004 0.73-0.011 4.143-0.114 8.986-0.995 12.318-1.712 3.207-0.692 5.62-1.356 6.306-1.549l0.461-0.142c3.034-1.172 6.745-3.109 10.181-5.31l0.437-0.281 9.188 9.462-6.147 13.555z" fill="#006bb6"/><path d="m55.418 32.451 0.0332 4.4668 1.8379 0.06641 0.04102-2.5469-1.9121-1.9863zm2.6992 2.3066c-0.0375 0.7475-0.03789 1.7991-0.08789 2.3516 1.2888 0.15125 2.6684 0.57406 3.8809 0.91406 1.0975 0.265 2.2779 0.73602 3.2441 1.166l0.53125-3.8457c-2.548-0.314-4.96-0.505-7.568-0.586zm-5.5117 0.0059c-1.7388 0.05875-3.4659 0.16758-5.1797 0.33008 0.14875 0.975 0.37164 2.4323 0.52539 3.4473 0 0 1.5846-0.92805 4.7559-1.2793l-0.10156-2.498zm-8.3184 0.68164c-1.6912 0.22375-3.3673 0.50172-5.0273 0.82422 0.63625 2.0688 1.447 4.8455 2.082 6.9355 1.4762-1.0988 2.3642-2.2276 3.918-3.1738-0.295-1.3975-0.68641-3.2059-0.97266-4.5859zm23.057 0.09961-0.9043 4.418c1.44 0.83375 2.5621 1.7761 3.8496 3.0273l0.25195 0.19336 2.0293-6.7109c-1.7475-0.36125-3.4441-0.67648-5.2266-0.92773zm-31.871 1.5469c-1.8988 0.45875-3.5504 0.94164-5.4004 1.5254 1.17 2.7812 2.4791 5.647 3.8691 8.3145 1.2625-0.465 3.0237-1.1003 4.6699-1.5391l-3.1387-8.3008zm40.662 0.19922-3.2949 8.5039 4.834 1.1367 4.0684-8.043c-1.875-0.61125-3.6849-1.1164-5.6074-1.5977zm-49.16 2.3457c-2.0475 0.73125-3.9106 1.4879-5.8906 2.3691l5.5645 7.9141c0.27875-0.24 3.0236-1.425 4.9023-2.2188-1.4275-2.585-3.1449-5.4345-4.5762-8.0645zm57.717 0.27734-4.457 8.0137c3.8512 1.495 9.2364 4.5124 11.379 5.9512 0.9875-0.945 6.3458-6.5693 7.082-7.3418-4.455-2.6138-9.1352-4.8355-14.004-6.623zm-68.486 4.418c-1.22 0.6325-2.4238 1.2963-3.6113 1.9863l7.209 7.2324c0.87375-0.525 1.7996-1.0604 2.8184-1.6504l-6.416-7.5684z" transform="matrix(.8 0 0 -.8 154.9 296.4)" fill="#bec0c2"/><path d="m199.6 267.52c-9.562-0.001-17.312-7.752-17.312-17.314 0-9.56 7.75-17.31 17.312-17.31 9.561 0 17.312 7.75 17.312 17.31 0 9.562-7.751 17.313-17.312 17.314" fill="#006bb6"/><path d="m31.41 11.426-3.0352 8.6328-4.8652 4.1895 4.4336-11.193-4.7656 1.9023-13.137 28.822 2.0547 2.0605c1.2188-0.71125 2.4552-1.3937 3.709-2.0449l4.1875-10.639 3.6758-3.2852 0.87891 1.0234-3.6309 10.443c1.985-0.875 4.0061-1.6761 6.0586-2.4023l2.6328-8.6113-2.2715-3.75 4.7031-4.4707 2.75-9.1602-3.3789-1.5176zm47.221 0.04687-1.8008 1.3906 3.2617 10.596 10.496 7.416 2.6895 6.7051-4.3652-1.9688-1.498-4.1738-5.3535-1.5762 2.8633 9.4297c0.8825 0.325 1.7582 0.66117 2.627 1.0137 2.3825 0.96375 4.7168 2.0317 6.998 3.1992 1.5812 0.80875 3.1346 1.6659 4.6621 2.5684l2.2813-2.3398-7.0625-15.57-11.035-7.3672-1.9199-5.3906 3.416 1.2148 1.3828 3.3691 5.1953 1.666-3.0312-6.6992-9.8066-3.4824zm-20.652 1.1211-2.3848 2.3809-0.0078 16.557 2.5039 2.5625c2.5825 0.08 5.1391 0.27312 7.6641 0.57812l-0.51758-4.7246-4.6777-0.27734-0.75195-13.242 3.9648 0.19336-0.46484-3.6465-5.3281-0.38086zm-4.6953 0.0098-4.0293 0.21094-1.8926 21.621c1.7112-0.1625 3.4363-0.27328 5.1738-0.33203l0.74805-21.5zm-6.3965 0.49609-3.7422 0.54492-1.2266 7.0996-1.3906-6.6816-4.3984 1.1016-6.1211 22.762c1.765-0.55125 3.5499-1.0469 5.3574-1.4844l3.3633-15.305 1.6895 8.2188-1.0918 6.2285c1.6338-0.31375 3.2823-0.58273 4.9473-0.80273l0.0098-0.002 2.6035-21.68zm17.742 0.0332s1.9105 14.577 2.8105 21.758c1.7238 0.24375 3.4305 0.54242 5.123 0.88867l-1.3203-7.0273 1.3164-1.7773 1.9238 1.582 1.7695 8.0625c1.8575 0.46625 3.6927 0.99383 5.5039 1.5801l-3.302-11.825-3.4043-2.7832 1.9375-2.5859-1.6113-6.002-4.1074-0.91211 1.6152 6.041-2.5586 3.4199-1.8926-9.9375-3.8047-0.48242zm-9.3203 24.574c-1.872 0.04131-3.6785 0.26711-5.3848 0.88867 0.73125 0.47125 1.3504 0.6357 2.4316 1.2832 1.585-0.73625 3.1845-1.5814 4.8457-2.1602-0.63781-0.01937-1.2686-0.02549-1.8926-0.01172zm3.9473 0.29492c-1.97 0.50375-5.7891 2.3223-5.7891 2.3223 6.4888 1.8162 14.136 1.4458 19.236 6.582-3.0125-4.8275-8.1435-8.0005-13.447-8.9043zm-10.59 1.0117c-1.8925 0.7725-3.9166 1.7797-5.3066 3.0547 2.1488 0.25 3.0692 0.38383 4.8242 0.86133 1.0488-0.9325 2.0637-1.7496 3.3262-2.5059l-2.8438-1.4102zm3.7832 1.7383c-1.21 0.74125-2.3897 1.6152-3.3984 2.5215 11.085 3.475 21.145 14.315 23.541 25.518 1.74-2.5112 2.7891-5.4251 3.2129-8.5176 0.27-4.7513 0.22375-9.0749-4.2812-13.201-5.3538-4.7238-12.815-4.1191-19.074-6.3203zm-10.174 2.1953c-1.97 1.7375-3.8293 4.396-4.7168 6.6348 1.8588-1.89 4.1731-3.4082 7.1094-2.752l0.02344 0.0078c0.83625-1.18 1.6351-2.192 2.7051-3.2207-1.9875-0.62-3.3061-0.59117-5.1211-0.66992zm6.0352 1.0176c-1.005 0.9825-1.8989 2.04-2.6914 3.1562l0.0039 0.0293c3.7175 1.6138 4.6932 5.5915 6.0957 10.865 1.8288 6.8725 3.5334 13.846 8.7109 19.215 2.9125-0.69375 5.9481-1.9776 8.7031-4.4551 0.85-0.85 2.119-2.0369 2.6465-2.8906-1.8088-11.296-12.381-22.792-23.469-25.92zm-4.8633 3.6738c-2.9114-0.05541-5.1137 2.1055-6.8516 4.5312-2.2612 7.9625 0.7432 16.164 5.7832 20.396-3.9-8.1125-3.2386-17.37 1.6602-24.887-0.20047-0.02398-0.3977-0.03732-0.5918-0.04102zm1.5684 0.3125c-5.215 7.3775-5.7072 18.731-0.49219 26.342 4.2112 2.665 9.4923 4.2629 14.822 3.1816-6.8375-7.905-7.4225-16.595-10.062-24.443-0.345-1.025-1.7276-4.3501-4.2676-5.0801z" transform="matrix(.8 0 0 -.8 154.9 296.4)" fill="#f58426"/></g></g></svg>
enhancement ready-to-ship

Most helpful comment

OK, merged to libvips master. Thank you for pointing out this issue, @bdrtsky !

All 11 comments

With width: 1000, height: 1000, or width: 16, height: 16, everythings ok. Or if I remove density

I think a combination of this image, density and dimensions is causing libvips to over-compute the underlying librsvg renderer, as seen and partially-fixed previously with https://github.com/libvips/libvips/pull/969

The effect can be seen on the boundary between resizing to 173 and 174 pixels wide:

sharp('1.svg', { density: 2400 })
  .resize(173)
  .toFile('output.png')

takes:

real    0m0.683s
user    0m0.779s
sys 0m0.072s

but one pixel wider

sharp('1.svg', { density: 2400 })
  .resize(174)
  .toFile('output.png')

takes about 20x longer:

real    0m14.558s
user    0m14.666s
sys 0m0.076s

As a workaround for this particular image and output dimensions, the density doesn't need to be so high.

I notice you've already seen #1421, which contains some suggestions for calculating the necessary density for given input and output dimensions when rasterising from vector to bitmap.

You can see this strange effect at the CLI as well. Here is your test SVG:

$ vipsheader test.svg[dpi=2400]
test.svg: 8333x6766 uchar, 4 bands, srgb, svgload

Then resizing to the two sizes Lovell found:

$ time vips resize test.svg[dpi=2400] x.png $(bc <<< "scale=10; 174 / 8333")
real    0m34.656s
user    0m34.502s
sys 0m0.152s
$ time vips resize test.svg[dpi=2400] x.png $(bc <<< "scale=10; 173 / 8333")
real    0m1.901s
user    0m2.273s
sys 0m0.109s

@jcupitt Thanks for confirming John, it's somewhat inconsistent, but on most runs of this task, the vips_foreign_load_svg_generate function (which pretty much renders the whole image via librsvg each time) is called 9 times for 173px wide output and a whopping 486 times for 174px wide output.

If I increase max_tiles from a minimum of 2 to 3, it then only calls vips_foreign_load_svg_generate a maximum of 5 times regardless of output dimensions.

Yes, I've been having a look. There's a lot of overcomputation on SVG, and it depends on exactly how the ratios of the various cache sizes work out.

I tried 3, but it then starts to get stuck at 261 pixels across :-(

How about giving up on the dream of random access for SVG load, and instead treating it like all the other loaders, so a strict top-to-bottom sequential process?

I'll open an issue on the libvips repo to track this so as to avoid cluttering up sharp.

Sorry, I changed my mind, it's actually quite simple. I'll paste it here.

Here's a patch that turns svgload into a sequential loader, like most of the others:

https://github.com/libvips/libvips/commit/e505d560791276c688ede4bc862a94ec3c04ef3c

It fixes all of the overcomputation. If I run this:

$ for i in {150..300}; do echo width $i; time vips resize test.svg[dpi=2400] x.png $(bc <<< "scale=10; $i / 8333"); done

I see under 2s times for every size between 150 and 300 pixels across.

Any thoughts? It's in a branch for now, perhaps it should be merged.

@jcupitt Thanks John, a move to sequential loading of SVG sounds like the right approach.

OK, merged to libvips master. Thank you for pointing out this issue, @bdrtsky !

@lovell yes, I am using that density formula right now, and if you ask me it's too much boilerplate code, and it should be somewhere in density: 'auto' default option. But yeah, it works, thanks!

@bdrtsky Pull Requests to improve the experience of using sharp are always welcome, if you're able.

What you describe would require quite a few unit tests to cover the various resize, extract and trim operations that impact output dimensions and therefore the calculation of any "automatic" density value.

v0.24.0 is now available with a prebuilt libvips v8.9.0. Thanks for reporting this!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

AVVS picture AVVS  路  3Comments

vermin1337 picture vermin1337  路  3Comments

zilions picture zilions  路  3Comments

henbenla picture henbenla  路  3Comments

iq-dot picture iq-dot  路  3Comments