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

Add support for LZ4 compressor #4289

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

Add support for LZ4 compressor #4289

wants to merge 2 commits into from

Conversation

arco
Copy link
Contributor

@arco arco commented Aug 22, 2015

No description provided.

PKG_LICENSE="BSD"
PKG_SITE="http://www.lz4.org/"
PKG_URL="https://github.com/Cyan4973/lz4/archive/$PKG_VERSION.tar.gz"
PKG_DEPENDS_TARGET="toolchain"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PKG_DEPENDS_HOST="" and remove PKG_DEPENDS_TARGET

@arco
Copy link
Contributor Author

arco commented Aug 22, 2015

For older kernels without LZ4 support, you need to add backported patches. See the LZ4 and squashfs related patches here: https://github.com/arco/linux-amlogic

The squashfs options I use for my Amlogic S805 based stick is:
CONFIG_SQUASHFS_FILE_DIRECT=y
CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y

Which gets OpenELEC booted in around 17 seconds.

@MilhouseVH
Copy link
Contributor

Which gets OpenELEC booted in around 17 seconds.

Compared with how long without? What's the benefit of adding this package? Nothing so far in this PR says why this is needed or why it's a good idea.

Edit: I see you mention some benefit for LZ4 in #4288 - some hard timing numbers on any actual benefit would seem like a minimum before making this kind of change. Just my humble opinion though.

@arco
Copy link
Contributor Author

arco commented Aug 22, 2015

For my device, Amlogic S805 based, with using gzip the boot is around 25 seconds, so there's a clear improvement by using LZ4. The benefits are improved compression/decompression speed, with the latter as being most important in OpenELEC's case.

There's some comparison numbers here: https://github.com/Cyan4973/lz4

@MilhouseVH
Copy link
Contributor

OK thanks, that's the kind of information that would have been useful in the first post. :)

And you're proposing "LZ4 HC" as the compressor, if I'm reading the second commit correctly (-Xhc). I might try doing some tests on RPi1/RPi2 tomorrow.

@arco
Copy link
Contributor Author

arco commented Aug 22, 2015

I'll update it with some more info. :)

Yeah, -Xhc gives the best compression ratio, while keeping the good decompression speed.

@MilhouseVH
Copy link
Contributor

using gzip the boot is around 25 seconds

How are you determining the boot duration - is this the time to start kodi? eg. time of first log entry, or "potato time" when the GUI appears?

It would be useful to know what your reference is when trying to compare against other systems - for instance, with existing squashfs defaults, an RPi2 will start kodi.bin in under 8.5 seconds (first kodi.log entry):

00:04:08   8.493264 T:1967050752  NOTICE: special://profile/ is mapped to: special://masterprofile/

(You can add monotonic time logging to kodi with this patch)

@MilhouseVH
Copy link
Contributor

Trying to build with this PR and getting an almost immediate build failure (build log) while building lz4 for host - it's including /usr/includes/features.h which then tries to include a non-existant sys/cdefs.h header.

In /usr/includes/features.h at line 364 - on Ubuntu 15.04 - there is the following:

361: /* This is here only because every header file already includes this one.  */
362: #ifndef __ASSEMBLER__
363: # ifndef _SYS_CDEFS_H
364: #  include <sys/cdefs.h>
365: # endif

@arco
Copy link
Contributor Author

arco commented Aug 23, 2015

http://askubuntu.com/questions/470796/fatal-error-sys-cdefs-h-no-such-file-or-directory

Btw, I time it from the u-boot logo appears on the TV, until Kodi GUI appears. With a stop-watch, so yeah, it's kinda "potato-time" and not very scientifically. :)

8.5 seconds for kodi.bin to start? That can't be correct. For me the log says:

02:53:06 10.872539 T:3040669696 NOTICE: special://profile/ is mapped to: special://masterprofile/

But when I use stop-watch to clock it from Kodi logo appears until GUI appears, it takes about 3 seconds. If I study the log, and extract the difference between the following two lines, that seems more right. Not sure why it starts with the number 10 though.

02:53:06 10.872773 T:3040669696 NOTICE: Starting Kodi (15.1 Git:f4dda26). Platform: Linux ARM 32-bit
02:53:08 13.825722 T:3040669696 NOTICE: initialize done

@chewitt
Copy link
Contributor

chewitt commented Aug 23, 2015

On "limited" hardware it may be beneficial to run squashfs with no compression. It results in double the file-size on disk but you keep the one-file packaging benefits and if you gzip the installer img there's only a ~10% increase in the file users are downloading. The additional overhead from the compression is (was) enough to cause all manner of problems with the old AppleTV build. The benefit is probably less on multi-core systems with more RAM available but other low power hardware may benefit. In all cases it would serve as a reference for how much penalty compression adds.

LZ4 is a lossless compression algorithm, providing compression
speed at 400 MB/s per core, scalable with multi-cores CPU.
It also features an extremely fast decoder, with speed in
multiple GB/s per core, typically reaching RAM speed limits
on multi-core systems.

Benchmark comparison and more info at: https://github.com/Cyan4973/lz4
@MilhouseVH
Copy link
Contributor

http://askubuntu.com/questions/470796/fatal-error-sys-cdefs-h-no-such-file-or-directory

Strange that this is the only package with this issue. Or maybe other packages solve this same issue without needing additional packages installed on the build system. It would be great if this package could build on existing build systems.

8.5 seconds for kodi.bin to start? That can't be correct.

Yep, it's correct - just timed it with a stopwatch, and cross referenced against entries in journalctl to ensure it is correct.

The monotonic time recorded in kodi.log represents the time elapsed since the system started, and therefore is indicative of how long it takes the system to boot the kernel, start systemd and all services, and get the system to a point where it can start kodi.bin.

For me the log says:

02:53:06 10.872539 T:3040669696 NOTICE: special://profile/ is mapped to: special://masterprofile/

... Not sure why it starts with the number 10 though.

Because on your system it takes 10.872539 seconds to get the system to a point where it can start kodi.bin.

Remember the system has to boot the kernel and start all the systemd services before it can start Kodi - the monotonic time in kodi.log isn't the elapsed time since Kodi started, it's the elapsed time since the system started.

@arco
Copy link
Contributor Author

arco commented Aug 23, 2015

That's odd about the build failure. No issues here on Linux Mint 17.2, based on Ubuntu 14.04.

arco@tuxbox /home $ dpkg -S /usr/include/sys/cdefs.h 
libc6-dev-i386: /usr/include/sys/cdefs.

And in OpenELEC build folder, which I guess is what it's actually using:

$ find -name cdefs.h
./toolchain/armv7a-openelec-linux-gnueabi/sysroot/usr/include/sys/cdefs.h
./gcc-4.9.3/fixincludes/tests/base/sys/cdefs.h
./glibc-2.21/include/sys/cdefs.h
./glibc-2.21/misc/sys/cdefs.h

And yep, you're right about the timing.

OpenELEC:~ # systemd-analyze 
Startup finished in 5.527s (kernel) + 4.642s (userspace) = 10.170s
OpenELEC:~ # systemd-analyze blame
          3.757s systemd-modules-load.service
           600ms hwdb.service
           457ms connman.service
           447ms systemd-logind.service
           264ms swap.service
           248ms systemd-user-sessions.service
           247ms unbind-console.service
           247ms amlogic-remotecfg.service
           246ms cron.service
           245ms sshd.service
           238ms kodi-cleanlogs.service
           218ms systemd-udev-trigger.service
           155ms wpa_supplicant.service
           152ms systemd-journald.service
           112ms show-version.service
            55ms systemd-tmpfiles-setup-dev.service
            51ms kmod-static-nodes.service
            42ms machine-id.service
            42ms tmp.mount
            39ms sys-kernel-debug.mount
            37ms var.mount
            34ms kodi.service
            33ms rpcbind.service
            33ms systemd-udevd.service
            33ms systemd-tmpfiles-clean.service
            33ms systemd-tmpfiles-setup.service
            31ms systemd-journal-flush.service
            29ms dev-mqueue.mount
            29ms systemd-remount-fs.service
            27ms systemd-sysctl.service
            19ms tz-data.service
            11ms userconfig.service
             9ms systemd-random-seed.service

@MilhouseVH
Copy link
Contributor

$ dpkg -S /usr/include/sys/cdefs.h
dpkg-query: no path found matching pattern /usr/include/sys/cdefs.h

In build.OpenELEC-RPi2.arm-6.0-devel build directory:

$ find -name cdefs.h
./toolchain/armv7ve-openelec-linux-gnueabi/sysroot/usr/include/sys/cdefs.h
./glibc-2.21/include/sys/cdefs.h
./glibc-2.21/misc/sys/cdefs.h
./gcc-4.9.3/fixincludes/tests/base/sys/cdefs.h

@MilhouseVH
Copy link
Contributor

OpenELEC:~ # systemd-analyze
Startup finished in 5.527s (kernel) + 4.642s (userspace) = 10.170s

What on Earth is your kernel doing for 5.5 seconds? :)

Is this with or without lz4? Have you tried lzo as used by the Pi, which boots the kernel in under 2 secondsIgnore that, the kernel is already zImage compressed so lzo/lz4 makes no difference:

rpi22:~ # systemd-analyze time
Startup finished in 1.985s (kernel) + 5.686s (userspace) = 7.671s

I've uploaded a dmesg from the RPi2: http://sprunge.us/ASVS - maybe you can spot where the delays are occurring in your kernel startup. Maybe this kind of discussion should move to the forum.

@arco
Copy link
Contributor Author

arco commented Aug 23, 2015

Could be because I run kernel 3.10, and that yours 4.1.6 has some major improvements. Or it could be the systemd-modules-load.service which takes almost 4 seconds. If it's counted with the kernel timing that is. I'm not sure.

@MilhouseVH
Copy link
Contributor

systemd doesn't start until after the kernel is loaded, you can see systemd starting in my dmesg after 2.01 seconds. Anyway the kernel issues are OT for this PR and should be discussed in the forum, apologies for derailing the lz4 discussion.

Priority now would be to resolve the build issue...

@MilhouseVH
Copy link
Contributor

By the way, the options you say you're using are already the defaults on all projects so any difference is presumably just down to lz4 instead of gzip (Wetek and RPi/RPi2 all use lzo for some reason):

CONFIG_SQUASHFS_FILE_DIRECT=y
CONFIG_SQUASHFS_DECOMP_MULTI_PERCPU=y

@arco
Copy link
Contributor Author

arco commented Aug 23, 2015

Yeah, too easy to get carried away. :) Just finish that off with saying it looks by the kernel log that there's a lot of nand discard/recovering going on, that seems to take time. Maybe the nand chip is in not so good shape.

About the build issue, I'll try to see if I can find something. Clearly there must be more package sources that includes the features.h file...

@lrusak
Copy link
Contributor

lrusak commented Aug 23, 2015

Honestly I see no harm in having this added, however, I did test all this before and realized it was useless because it doesn't save space or time compared to other methods.

@arco
Copy link
Contributor Author

arco commented Aug 23, 2015

@MilhouseVH Yeah, those options doesn't exist in legacy kernels, like 3.10 which I'm stuck with, so some stuff had to be backported. I guess those are also responsible for some of the improved speed i'm seeing.

Regarding the build error, I'm pretty sure you need to install the package providing /usr/include/sys/cdefs.h, which in Ubuntu is libc6-dev-i386. This again should be a dependency of gcc-multilib. For example, in the case of Android, it's a build requirement to have it installed.

@MilhouseVH
Copy link
Contributor

$ sudo apt-get install libc6-dev-i386
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  gcc-4.9-multilib gcc-multilib lib32asan1 lib32atomic1 lib32cilkrts5 lib32gcc-4.9-dev lib32gcc1 lib32gomp1 lib32itm1 lib32quadmath0 lib32stdc++6 lib32ubsan0 libc6-dev-x32 libc6-i386
  libc6-x32 libx32asan1 libx32atomic1 libx32cilkrts5 libx32gcc-4.9-dev libx32gcc1 libx32gomp1 libx32itm1 libx32quadmath0 libx32ubsan0
The following NEW packages will be installed
  gcc-4.9-multilib gcc-multilib lib32asan1 lib32atomic1 lib32cilkrts5 lib32gcc-4.9-dev lib32gcc1 lib32gomp1 lib32itm1 lib32quadmath0 lib32stdc++6 lib32ubsan0 libc6-dev-i386 libc6-dev-x32
  libc6-i386 libc6-x32 libx32asan1 libx32atomic1 libx32cilkrts5 libx32gcc-4.9-dev libx32gcc1 libx32gomp1 libx32itm1 libx32quadmath0 libx32ubsan0
0 to upgrade, 25 to newly install, 0 to remove and 37 not to upgrade.
Need to get 12.6 MB of archives.
After this operation, 52.6 MB of additional disk space will be used.

Hmmm... I dunno, this just feels wrong... installing 32-bit libraries to solve a build problem on a 64-bit system doesn't seem like the right solution. I'm just really quite loathe to use this sledgehammer solution right now, which may be masking the correct solution, besides I'm out of time for testing - maybe later in the week (and hopefully someone can suggest a less dramatic build solution).

@arco
Copy link
Contributor Author

arco commented Aug 24, 2015

/usr/include/sys/cdefs.h is actually just a symlink to ../x86_64-linux-gnu/sys/cdefs.h (does this exist on your system?), which is part of the libc6-dev:amd64 package. If i delete cdefs.h from /usr/include/sys/, it still builds fine here, as long as the file in /usr/include/x86_64-linux-gnu/sys/ exists.

@MilhouseVH
Copy link
Contributor

$ dpkg -l libc6-dev:amd64
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                       Version                    Architecture               Description
+++-==========================================-==========================-==========================-=========================================================================================
ii  libc6-dev:amd64                            2.21-0ubuntu4              amd64                      GNU C Library: Development Libraries and Header Files
$ find /usr/include -name cdefs.h -ls
283675   16 -rw-r--r--   1 root     root        15052 Mar 26 06:59 /usr/include/x86_64-linux-gnu/sys/cdefs.h

@arco
Copy link
Contributor Author

arco commented Aug 25, 2015

Well, I'm baffled. It's amazing that anything at all compiles for you, when taking into the fact that cdefs.h is included from features.h, which in turn is included from stdlib.h, which in turn is included in many many sources.

I removed libc6-dev-i386 completely, with all its dependencies, and lz4 sources still compiled fine here.

probox / # sudo apt-get remove libc6-dev-i386
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following packages will be REMOVED:
  g++-4.9-multilib g++-multilib gcc-4.9-multilib gcc-multilib libc6-dev-i386
  libc6-dev-x32
0 upgraded, 0 newly installed, 6 to remove and 0 not upgraded.
After this operation, 14.0 MB disk space will be freed.
Do you want to continue? [Y/n]
(Reading database ... 169106 files and directories currently installed.)
Removing g++-multilib (4:4.9.2-2) ...
Removing g++-4.9-multilib (4.9.2-10) ...
Removing gcc-multilib (4:4.9.2-2) ...
Removing gcc-4.9-multilib (4.9.2-10) ...
Removing libc6-dev-x32 (2.19-18) ...
Removing libc6-dev-i386 (2.19-18) ...

My gcc configuration, which you can see contains the path to the x86_64 include files.

arco@probox ~ $ gcc -v -E -
Using built-in specs.
COLLECT_GCC=gcc
Target: x86_64-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian 4.9.2-10' --with-bugurl=file:///usr/share/doc/gcc-4.9/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.9 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.9 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-vtable-verify --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.9-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.9-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --with-arch-32=i586 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu
Thread model: posix
gcc version 4.9.2 (Debian 4.9.2-10)
COLLECT_GCC_OPTIONS='-v' '-E' '-mtune=generic' '-march=x86-64'
 /usr/lib/gcc/x86_64-linux-gnu/4.9/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu - -mtune=generic -march=x86-64
ignoring nonexistent directory "/usr/local/include/x86_64-linux-gnu"
ignoring nonexistent directory "/usr/lib/gcc/x86_64-linux-gnu/4.9/../../../../x86_64-linux-gnu/include"
#include "..." search starts here:
#include <...> search starts here:
 /usr/lib/gcc/x86_64-linux-gnu/4.9/include
 /usr/local/include
 /usr/lib/gcc/x86_64-linux-gnu/4.9/include-fixed
 /usr/include/x86_64-linux-gnu
 /usr/include
End of search list.

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

Successfully merging this pull request may close these issues.

5 participants