[bootlin/training-materials updates] master: Boot time lab: filesystem optimizations (1ddf301a)
Michael Opdenacker
michael.opdenacker at bootlin.com
Wed May 22 22:07:47 CEST 2019
Repository : https://github.com/bootlin/training-materials
On branch : master
Link : https://github.com/bootlin/training-materials/commit/1ddf301ae274beb280db5ec47dc80b447004dbe3
>---------------------------------------------------------------
commit 1ddf301ae274beb280db5ec47dc80b447004dbe3
Author: Michael Opdenacker <michael.opdenacker at bootlin.com>
Date: Wed May 22 22:07:47 2019 +0200
Boot time lab: filesystem optimizations
Signed-off-by: Michael Opdenacker <michael.opdenacker at bootlin.com>
>---------------------------------------------------------------
1ddf301ae274beb280db5ec47dc80b447004dbe3
lab-data/boot-time/solutions/busybox.config | 16 ++-
.../boot-time-filesystem-optimizations.tex | 155 +++++++++++++++++++++
.../boot-time-init-scripts.tex | 8 +-
mk/boot-time.mk | 1 +
.../boot-time-init-scripts3.tex | 18 ++-
5 files changed, 178 insertions(+), 20 deletions(-)
diff --git a/lab-data/boot-time/solutions/busybox.config b/lab-data/boot-time/solutions/busybox.config
index bf2165c1..1bf9d2e3 100644
--- a/lab-data/boot-time/solutions/busybox.config
+++ b/lab-data/boot-time/solutions/busybox.config
@@ -1,7 +1,7 @@
#
# Automatically generated make config: don't edit
# Busybox version: 1.29.3
-# Wed May 22 11:38:17 2019
+# Wed May 22 18:00:52 2019
#
CONFIG_HAVE_DOT_CONFIG=y
@@ -222,7 +222,7 @@ CONFIG_GZIP_FAST=0
# CONFIG_UNIX2DOS is not set
# CONFIG_DU is not set
# CONFIG_FEATURE_DU_DEFAULT_BLOCKSIZE_1K is not set
-# CONFIG_ECHO is not set
+CONFIG_ECHO=y
# CONFIG_FEATURE_FANCY_ECHO is not set
# CONFIG_ENV is not set
# CONFIG_EXPAND is not set
@@ -630,7 +630,7 @@ CONFIG_DEFAULT_DEPMOD_FILE=""
# CONFIG_MKSWAP is not set
# CONFIG_FEATURE_MKSWAP_UUID is not set
# CONFIG_MORE is not set
-# CONFIG_MOUNT is not set
+CONFIG_MOUNT=y
# CONFIG_FEATURE_MOUNT_FAKE is not set
# CONFIG_FEATURE_MOUNT_VERBOSE is not set
# CONFIG_FEATURE_MOUNT_HELPERS is not set
@@ -672,8 +672,12 @@ CONFIG_DEFAULT_DEPMOD_FILE=""
# CONFIG_FEATURE_UMOUNT_ALL is not set
# CONFIG_UNSHARE is not set
# CONFIG_WALL is not set
-# CONFIG_FEATURE_MOUNT_LOOP is not set
-# CONFIG_FEATURE_MOUNT_LOOP_CREATE is not set
+
+#
+# Common options for mount/umount
+#
+CONFIG_FEATURE_MOUNT_LOOP=y
+CONFIG_FEATURE_MOUNT_LOOP_CREATE=y
# CONFIG_FEATURE_MTAB_SUPPORT is not set
# CONFIG_VOLUMEID is not set
# CONFIG_FEATURE_VOLUMEID_BCACHE is not set
@@ -1088,7 +1092,7 @@ CONFIG_HUSH_LOOPS=y
# CONFIG_HUSH_LOCAL is not set
# CONFIG_HUSH_RANDOM_SUPPORT is not set
# CONFIG_HUSH_MODE_X is not set
-CONFIG_HUSH_ECHO=y
+# CONFIG_HUSH_ECHO is not set
# CONFIG_HUSH_PRINTF is not set
# CONFIG_HUSH_TEST is not set
# CONFIG_HUSH_HELP is not set
diff --git a/labs/boot-time-filesystem-optimizations/boot-time-filesystem-optimizations.tex b/labs/boot-time-filesystem-optimizations/boot-time-filesystem-optimizations.tex
new file mode 100644
index 00000000..d770199f
--- /dev/null
+++ b/labs/boot-time-filesystem-optimizations/boot-time-filesystem-optimizations.tex
@@ -0,0 +1,155 @@
+\subchapter{Filesystem optimizations}{See what best filesystem options
+are in terms of boot time}
+
+During this lab, we will compare 3 ways of accessing the root filesystem
+
+\begin{itemize}
+\item Booting from an {\em ext4} filesystem
+\item Booting from a {\em SquashFS} filesystem
+\item Booting from an {\em initramfs}
+\end{itemize}
+
+\section{Tests with ext4 and Squashfs}
+
+First, recompile your kernel with {\em SquashFS} support, and update it
+on the SD card.
+
+Write the size of the \code{zImage} file in the first row of the below table:
+
+\begin{tabular}{| l | l |}
+ \hline
+ Type & zImage size (bytes) \\
+ \hline
+ \hline
+ zImage without initramfs & \\
+ \hline
+ zImage with initramfs & \\
+ \hline
+\end{tabular}
+
+Go to \code{~/boot-time-labs/rootfs}. You should have a \code{rootfs}
+subdirectory where your root filesystem archive has been extracted.
+
+Boot your system with \code{grabserial} and start filling the
+table below:
+
+\begin{tabular}{| l | l | l | r |}
+ \hline
+ Filesystem & Time for \code{Run /playvideo} & Time for \code{First frame decoded} & Time difference\\
+ \hline
+ \hline
+ ext4 & & & \\
+ \hline
+ SquashFS & & & \\
+ \hline
+ Initramfs & & & \\
+ \hline
+\end{tabular}
+
+For {\em SquashFS}, you will have to create an image and copy it to the
+raw partition:
+
+\begin{verbatim}
+sudo apt install squashfs-tools
+cd ~/boot-time-labs/rootfs
+mksquashfs rootfs/ rootfs.sqfs -noappend
+sudo dd if=rootfs.sqfs of=/dev/mmcblk0p2
+\end{verbatim}
+
+Then remove the SD card and boot the board with it as usual, and record
+measurements.
+
+Note that we also made tests with {\em ext2}, but they were very close
+to {\em ext4} ones, at least for very small filesystems like this one.
+So we decided to skip this filesystem here, to save time.
+
+\section{Initramfs tests}
+
+Booting from an {\em initramfs} is completely different. The strong
+advantage here is that the root filesystem will be extracted from an
+archive inside the kernel binary. So instead of several reads from the
+MMC, we will just have one reading (though bigger) the kernel binary.
+This can work well with small root filesystems as ours.
+
+Booting the kernel should be faster too, as we won't need the MMC and
+filesystem drivers at all. So, let's configure the kernel accordingly.
+
+To switch to an initramfs, there are a few things to do though:
+\begin{itemize}
+\item In an initramfs, you cannot have the kernel mount the {\em
+devtmpfs} filesystem mounted automatically on \code{/dev}. We'll mount
+it from our \code{playvideo} script.
+So:
+ \begin{itemize}
+ \item Modify the Busybox configuration to add support for the
+ \code{mount} command (found in \code{Linux System Utilities}), without
+ any additional option.
+ \item Add the following line to the \code{/playvideo} file:\\
+ \code{mount -t devtmpfs nodev /dev}
+ \item Run \code{make} to update your root filesystem and then
+ extract it again in your \code{rootfs} directory.
+ \end{itemize}
+\item Go to the U-Boot command line on your board, and modify the
+kernel parameters:\\
+ \code{setenv bootargs console=ttyO0,115200n8 rdinit=/playvideo}\\
+ \code{root=} and \code{rootwait} are ignored when there is an
+ Initramfs and \code{init} is replaced by \code{rdinit=}.
+ Don't forget to run \code{saveenv}.
+\end{itemize}
+
+Go to \code{~/boot-time-labs/kernel/linux} and run the Linux
+configuration interface:
+
+\begin{itemize}
+ \item In \code{General setup}
+ \begin{itemize}
+ \item Fill \code{Initramfs source file(s)} with
+\code{../../rootfs/rootfs} (or the correct path to the directory
+containing your root filesystem)
+ \item Make sure you set \code{CONFIG_INITRAMFS_COMPRESSION_NONE=y}
+ to avoid wasting space compressing the initramfs twice.
+ \end{itemize}
+ \item Disable \code{Enable the block layer}
+ \item Disable \code{MMC/SD/SDIO card support}
+ \item We won't have to disable block filesystems as they are no longer
+compiled when block support is disabled.
+\end{itemize}
+
+Rebuild your kernel binary:
+\begin{verbatim}
+make -j8 zImage
+\end{verbatim}
+
+Copy the new kernel image to your SD card and then boot the board. You
+will see that there is a new issue though: the messages from \code{echo}
+and \code{ffmpeg} don't go through. That's probably because
+\code{/dev/console} doesn't exit yet when the script is started.
+
+So, let's fix it in our script. We are redirecting the important
+messages to \code{/dev/console}:
+
+\begin{verbatim}
+#!/bin/sh
+mount -t devtmpfs nodev /dev
+if ! [ -e /dev/video0 ]
+then
+ echo "Waiting for /dev/video0 to be ready..." > /dev/console
+ while ! [ -e /dev/video0 ]
+ do
+ sleep 0.001
+ done
+fi
+echo "Starting ffmpeg" > /dev/console
+ffmpeg -t 10 -f video4linux2 -video_size 544x288 -input_format mjpeg -i /dev/video0 -pix_fmt rgb565le -f fbdev /dev/fb0 2> /dev/console
+/bin/sh
+\end{verbatim}
+
+Now, you should be able to extrat the measures and write them down in
+the table above. If your tests run the same way ours did, the
+initramfs approach should win by a few tens of milliseconds.
+
+Also measure the size of your \code{zImage} file at write it in the
+table at the top of this chapter, to compare with your initial kernel.
+
+Let's choose this solution with an initramfs. There are still many things we can
+accelerate during the execution of the bootloader and execution.
diff --git a/labs/boot-time-init-scripts/boot-time-init-scripts.tex b/labs/boot-time-init-scripts/boot-time-init-scripts.tex
index 9cfc04a1..a3f8b857 100644
--- a/labs/boot-time-init-scripts/boot-time-init-scripts.tex
+++ b/labs/boot-time-init-scripts/boot-time-init-scripts.tex
@@ -323,16 +323,16 @@ Just select the below options, based on what we have in our
if you don't select \code{ash}. Otherwise, compiling
\code{hush} will fail.
\item Select the \code{hush} shell
- \item Keep only \code{Support if/then/elif/else/fi},
+ \item Keep only \code{Support if/then/elif/else/fi} and
\code{Support for, while and until loops},
- \code{echo builtin} and \code{test builtin}.
\end{itemize}
\item In \code{Coreutils}:
\begin{itemize}
\item Support for the \code{sleep} command, with support for fractional arguments.
+ \item Support for the \code{echo} command, without additional options.
\item Support for the \code{sync} command, without further options.
We need this utility if we make changes to the root filesystem.
- \item Enable \code{test as [}
+ \item Enable \code{test} and \code{test as [}
\item Disable \code{Extend test to 64 bit}
\end{itemize}
\end{itemize}
@@ -362,7 +362,7 @@ If everything works, it's time to boot the system again through
Step & Duration & Description \\
\hline
\hline
- Init scripts & & Between \code{Run /sbin/init} and \code{Starting ffmpeg} \\
+ Init scripts & & Between \code{Run /playvideo as init process} and \code{Starting ffmpeg} \\
\hline
Application & & Between \code{Starting ffmpeg} and \code{First frame decoded} \\
\hline
diff --git a/mk/boot-time.mk b/mk/boot-time.mk
index c6f06ade..ad3681cf 100644
--- a/mk/boot-time.mk
+++ b/mk/boot-time.mk
@@ -37,6 +37,7 @@ BOOT_TIME_LABS = boot-time-goals \
boot-time-toolchain \
boot-time-application \
boot-time-init-scripts \
+ boot-time-filesystem-optimizations \
boot-time-kernel \
boot-time-bootloader \
boot-time-results
diff --git a/slides/boot-time-init-scripts3/boot-time-init-scripts3.tex b/slides/boot-time-init-scripts3/boot-time-init-scripts3.tex
index ada91766..e8d96ab6 100644
--- a/slides/boot-time-init-scripts3/boot-time-init-scripts3.tex
+++ b/slides/boot-time-init-scripts3/boot-time-init-scripts3.tex
@@ -41,21 +41,19 @@ application and then switch to the final root filesystem with
\end{frame}
\begin{frame}
-\frametitle{Do not compress your initramfs (1)}
+\frametitle{Do not compress your initramfs}
\begin{itemize}
\item If you ship your initramfs inside a compressed kernel image, don't compress
it \\
(enable \code{CONFIG_INITRAMFS_COMPRESSION_NONE}).
\item Otherwise, your initramfs data will be compressed twice, and
- the kernel will be slightly bigger and will take a little more time to uncompress.
+ the kernel will be bigger and will take a little more time to load
+ and uncompress.
+\item Example on Linux 5.1 with a 2 MB initramfs uncompressed archive
+ on Beagle Bone Black: this allowed to reduce the kernel from 4.8 MB to 4.6 MB
+ and save about 120 ms of boot time.
+\item Older examples:
\end{itemize}
-\end{frame}
-
-\begin{frame}
-\frametitle{Do not compress your initramfs (2)}
-Tests on Linux 3.13-rc4, measuring the penalty of having a
-\code{gzip} compressed initramfs in a \code{gzip} compressed kernel. \\
-\vfill{}
\scriptsize
Beagle Bone Black (ARM, TI AM3359, 1 GHz)
\begin{tabular}{| l || c | c | c | c | c | }
@@ -129,6 +127,6 @@ and even create an animation!
geometric shapes on the framebuffer!
\item Example: {\small \url{https://bootlin.com/pub/code/fb/anim.c}}.
On a 400 MHz ARM9 system: starts drawing in 10 ms \\
- size: 24 KB, compiled statically).
+ Size: 24 KB, compiled statically.
\end{itemize}
\end{frame}
More information about the training-materials-updates
mailing list