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

How to tell if vips is using libjpeg or libjepg-turbo? #229

Closed
keeganwitt opened this issue Jan 20, 2021 · 18 comments
Closed

How to tell if vips is using libjpeg or libjepg-turbo? #229

keeganwitt opened this issue Jan 20, 2021 · 18 comments

Comments

@keeganwitt
Copy link

Similar to the question asked about Pillow (where they added a way in Python to check), I'm wondering how I can know whether libjpeg or libjepg-turbo is being used by pyvips/libvips.

@keeganwitt keeganwitt changed the title How to tell if vips is using libjpeg or libjepg-turbo How to tell if vips is using libjpeg or libjepg-turbo? Jan 20, 2021
@keeganwitt
Copy link
Author

keeganwitt commented Jan 20, 2021

I saw libvips/libvips#1098, but in my case, it doesn't look like the binary got installed as part of the vips package.

$ dpkg-query -L libvips42
/.
/usr
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libvips-cpp.so.42.12.2
/usr/lib/x86_64-linux-gnu/libvips.so.42.12.2
/usr/share
/usr/share/doc
/usr/share/doc/libvips42
/usr/share/doc/libvips42/AUTHORS
/usr/share/doc/libvips42/NEWS.gz
/usr/share/doc/libvips42/README.Debian
/usr/share/doc/libvips42/THANKS
/usr/share/doc/libvips42/changelog.Debian.gz
/usr/share/doc/libvips42/changelog.gz
/usr/share/doc/libvips42/copyright
/usr/share/lintian
/usr/share/lintian/overrides
/usr/share/lintian/overrides/libvips42
/usr/share/locale
/usr/share/locale/de
/usr/share/locale/de/LC_MESSAGES
/usr/share/locale/de/LC_MESSAGES/vips8.9.mo
/usr/share/locale/en_GB
/usr/share/locale/en_GB/LC_MESSAGES
/usr/share/locale/en_GB/LC_MESSAGES/vips8.9.mo
/usr/lib/x86_64-linux-gnu/libvips-cpp.so.42
/usr/lib/x86_64-linux-gnu/libvips.so.42
$ dpkg-query -L libvips-dev
/.
/usr
/usr/include
/usr/include/vips
/usr/include/vips/VConnection8.h
/usr/include/vips/VError8.h
/usr/include/vips/VImage8.h
/usr/include/vips/VInterpolate8.h
/usr/include/vips/almostdeprecated.h
/usr/include/vips/arithmetic.h
/usr/include/vips/basic.h
/usr/include/vips/buf.h
/usr/include/vips/cimg_funcs.h
/usr/include/vips/colour.h
/usr/include/vips/connection.h
/usr/include/vips/conversion.h
/usr/include/vips/convolution.h
/usr/include/vips/create.h
/usr/include/vips/dbuf.h
/usr/include/vips/debug.h
/usr/include/vips/deprecated.h
/usr/include/vips/dispatch.h
/usr/include/vips/draw.h
/usr/include/vips/enumtypes.h
/usr/include/vips/error.h
/usr/include/vips/foreign.h
/usr/include/vips/format.h
/usr/include/vips/freqfilt.h
/usr/include/vips/gate.h
/usr/include/vips/generate.h
/usr/include/vips/header.h
/usr/include/vips/histogram.h
/usr/include/vips/image.h
/usr/include/vips/interpolate.h
/usr/include/vips/intl.h
/usr/include/vips/mask.h
/usr/include/vips/memory.h
/usr/include/vips/morphology.h
/usr/include/vips/mosaicing.h
/usr/include/vips/object.h
/usr/include/vips/operation.h
/usr/include/vips/private.h
/usr/include/vips/rect.h
/usr/include/vips/region.h
/usr/include/vips/resample.h
/usr/include/vips/sbuf.h
/usr/include/vips/semaphore.h
/usr/include/vips/soname.h
/usr/include/vips/thread.h
/usr/include/vips/threadpool.h
/usr/include/vips/transform.h
/usr/include/vips/type.h
/usr/include/vips/util.h
/usr/include/vips/vector.h
/usr/include/vips/version.h
/usr/include/vips/video.h
/usr/include/vips/vips-operators.h
/usr/include/vips/vips.h
/usr/include/vips/vips7compat.h
/usr/include/vips/vips8
/usr/lib
/usr/lib/x86_64-linux-gnu
/usr/lib/x86_64-linux-gnu/libvips-cpp.a
/usr/lib/x86_64-linux-gnu/libvips.a
/usr/lib/x86_64-linux-gnu/pkgconfig
/usr/lib/x86_64-linux-gnu/pkgconfig/vips-cpp.pc
/usr/lib/x86_64-linux-gnu/pkgconfig/vips.pc
/usr/share
/usr/share/doc
/usr/share/doc/libvips-dev
/usr/share/doc/libvips-dev/AUTHORS
/usr/share/doc/libvips-dev/NEWS.gz
/usr/share/doc/libvips-dev/THANKS
/usr/share/doc/libvips-dev/changelog.Debian.gz
/usr/share/doc/libvips-dev/changelog.gz
/usr/share/doc/libvips-dev/copyright
/usr/share/gir-1.0
/usr/share/gir-1.0/Vips-8.0.gir
/usr/lib/x86_64-linux-gnu/libvips-cpp.so
/usr/lib/x86_64-linux-gnu/libvips.so

@jcupitt
Copy link
Member

jcupitt commented Jan 20, 2021

On debian, just do apt install libjpeg-turbo8 and it'll swap out the regular one for the turbo one.

@keeganwitt
Copy link
Author

keeganwitt commented Jan 20, 2021

On debian, just do apt install libjpeg-turbo8 and it'll swap out the regular one for the turbo one.

I've done that, but libjpeg8 is also an installed package. I was concerned it might not be using what I thought it was using.

I have no particular reason to suspect so, other than vimage.tiffsave is taking a very long time and was hoping this might be the cause for an easy speedup.

@jcupitt
Copy link
Member

jcupitt commented Jan 20, 2021

You could try:

$ ldd $(which vips) | grep jpeg
	libjpeg.so.8 => /usr/lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007f97f40e6000)
$ dpkg -S /usr/lib/x86_64-linux-gnu/libjpeg.so.8
libjpeg-turbo8:amd64: /usr/lib/x86_64-linux-gnu/libjpeg.so.8

Your slow tiffsave is probably caused by something else in your pipeline :( I could check your code if you upload a benchmark.

@keeganwitt
Copy link
Author

keeganwitt commented Jan 20, 2021

Thanks for your kind offer. Do you have a doc describing how to capture a benchmark for analysis (sorry for my ignorance)?

I installed the tools package so I have access to the vips command, and it looks like it is indeed linking to the wrong library

$ ldd $(which vips) | grep jpeg
	libjpeg.so.8 => /usr/lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007ff8bbf96000)

This is running a bit of a tweaked vips Debian package, so I can run a reasonably recent vips on an older Ubuntu, which I describe here. I'm compiling it in whatever way Ubuntu was, unless I'm missing something. Support for turbo isn't directly compiled in, right (so it's OK I'm not directly invoking ldconfig)?

@jcupitt
Copy link
Member

jcupitt commented Jan 20, 2021

That could be the right binary --- try the dpkg -S to see which package installed it.

I usually benchmark stuff by writing a few lines of python that does what I need to do. pyvips is high-level and very quick to develop.

@keeganwitt
Copy link
Author

Ah, you're right. I thought the object files would have a different name.

$ dpkg -S libjpeg.so.8
libjpeg-turbo8:amd64: /usr/lib/x86_64-linux-gnu/libjpeg.so.8.1.2
libjpeg-turbo8:amd64: /usr/lib/x86_64-linux-gnu/libjpeg.so.8

@jcupitt
Copy link
Member

jcupitt commented Jan 20, 2021

For API mode you can also use:

$ python3 -c "import pyvips; print(pyvips.API_mode)"
True

@jcupitt
Copy link
Member

jcupitt commented Jan 20, 2021

It's because libjpeg-turbo is completely binary-compatible. You can swap the .so file and everything will keep working, with no need to relink.

@keeganwitt
Copy link
Author

keeganwitt commented Jan 25, 2021

I shared a file with you on Google Drive.
To reduce the number of moving pieces, I've reproduced this using the vips tool without pyvips, and to have a consistent environment, I did the test in Docker. Just run the commands in the comments of Dockerfile.

# docker build -t vips-test .
# docker run --rm -v $PWD/images:/images vips-test time vips tiffsave 13.tiff 13-pyramid.tiff --compression=jpeg --tile --tile-width=256 --tile-height=256 --pyramid --bigtiff

FROM ubuntu:20.10

VOLUME /images
WORKDIR /images

RUN set -o errexit -o nounset \
    && apt-get -y update \
    && apt-get install --no-install-recommends --no-install-suggests -y \
        libjpeg-turbo8-dev \
        libpng-dev \
        libtiff5-dev \
        libvips-dev \
        libvips-tools \
        time \
    && rm -rf /var/lib/apt/lists/*

It could be we just have to live with this due to file size (there are some files we deal with that are even bigger), but let me know if you have any suggestions.

@jcupitt
Copy link
Member

jcupitt commented Jan 27, 2021

Hi again, I tried this dockerfile:

FROM ubuntu:20.10

RUN apt-get update \ 
        && apt-get install -y

RUN apt-get install -y \
        libvips \
        libvips-tools

RUN echo -n "vips binary: "; which vips \
        && echo -n "linked to libjpeg: "; ldd $(which vips) | grep jpeg \
        && echo -n "supplied by package: "; dpkg -S libjpeg.so.8

I see:

 ---> Running in 12b3e8a1018a
vips binary: /usr/bin/vips
linked to libjpeg: 	libjpeg.so.8 => /lib/x86_64-linux-gnu/libjpeg.so.8 (0x00007f9f0bb39000)
supplied by package: libjpeg-turbo8:amd64: /usr/lib/x86_64-linux-gnu/libjpeg.so.8.2.2
libjpeg-turbo8:amd64: /usr/lib/x86_64-linux-gnu/libjpeg.so.8

So I think you're probably using libjpeg-turbo.

@jcupitt
Copy link
Member

jcupitt commented Jan 27, 2021

I tried on my PC fwiw and I see:

$ time vips tiffsave 13.tiff x.tif --pyramid --tile-width 256 --tile-height 256 --tile --compression jpeg
real	2m0.528s
user	3m16.473s
sys	0m2.659s

I think that's probably as fast as libvips can easily go at this task. There are some things that could be improved internally (moving jpg-encode outside the lock, buffering other pyr layers in ram), but they would be a fair amount of work.

@keeganwitt
Copy link
Author

It looked like when this was running in Kubernetes only 1 vcpu was being used. Is there some arg needed to make better use of the cores?

@jcupitt
Copy link
Member

jcupitt commented Jan 27, 2021

libvips checks the number of CPUs available on startup and will use all of them by default. Perhaps your k8 setup needs something to allocate another CPU to this task?

@keeganwitt
Copy link
Author

I know this is a potentially complicated question, but what's the mechanism Vips uses for core detection? I'm wondering if there's a mismatch between how K8s configures this and how Vips detects it.

@jcupitt
Copy link
Member

jcupitt commented Feb 18, 2021

It's this horrible thing:

https://github.com/libvips/libvips/blob/master/libvips/iofuncs/threadpool.c#L315-L392

Which on linux boils down to just:

int n_proc = sysconf( _SC_NPROCESSORS_ONLN );

See https://man7.org/linux/man-pages/man3/sysconf.3.html

@keeganwitt
Copy link
Author

keeganwitt commented Feb 18, 2021

I've seen the vcpu usage go up to like 1500 or 1700 at one point, but then dropped down to like 1010, so still not using much more than 1 core. Maybe the "reduceh: 13 point mask" (the last thing I saw logged) just isn't something very parallelizable...

@keeganwitt
Copy link
Author

I think we've answered the original question associated with this issue though, so closing. Thanks for your help!

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

No branches or pull requests

2 participants