Posts Tagged ‘linux’

Doppelt so schnell booten durch 93 mal schnelleren Festplattenzugriff?

Da ich mein Linux daheim ja nur alle paar Tage/Wochen neu boote, und der Rechner sonst rund um die Uhr läuft (ich darf das, ich hab 100% Ökostrom!), könnte mit die Zeit zum Booten ja eigentlich egal sein. Aber ich bin nun mal optimierungswütig, vor allem, wenn zwischen dem Ist-Zustand und dem, was ich für möglich halte, ein sehr hoher Faktor liegt. In diesem Fall denke ich, ich könnte die Geschwindigkeit der Festplattenzugriffe um einen zweistelligen Faktor erhöhen und damit den Gesamtbootvorang immerhin um 77% beschleunigen. Das motiviert, also habe ich gestern und heute ein paar Nachforschungen und Versuche angestellt. Ich möchte hier schonmal von den Ergebnissen berichten, aber auch von dem Weg dorthin, denn die offensichtlichsten Verfahren zur Messung stellten sich oft als falsch heraus.

Ausgangszustand: Normaler Bootvorgang mit ureadahead in 114 Sekunden

Mein Ubuntu bootet in 114 Sekunden. Gemessen habe ich von der Auswahl im GRUB Menü bis sich auf dem Desktop das Fenster zur Schlüsselbundentsperrung öffnet. Dies ist das letzte sichtbare Ereignis nach beim Hochfahren, so dass es sich zur Zeitnahme eignet.

Beim gesamten Bootvorgang höre ich permanent die Festplatte “knattern”, es finden scheinbar viele Lesezugriffe an verschiedenen Stellen statt. Das wollte ich genauer wissen. Mittels ureadahead konnte ich das genauer untersuchen. Dieses Programm nutzt eine Kernelerweiterung, um beim Booten alle Lesezugriffe zu protokollieren. Ich vertraue darauf, dass dies prinzipiell korrekt abläuft und habe als Ergebnis erhalten: Ubuntu liest beim Starten 226MB aus 3140 Dateien. Angeblich liegen diese an nur 3113 verschiedenen Stellen der HDD. Komisch, aber eine Abweichung, die ich akzeptieren kann.

Wie viel dieser Zeit wird zum Lesen benötigt?

Meine Platte braucht im Schnitt 20ms für eine Neupositionierung des Kopfes, für 3113 davon also rechnerisch etwa 65 Sekunden. Die Zeit, die das eigentliche Lesen braucht, ist im Vergleich dazu zu vernachlässigen: rechnerisch 2,8 Sekunden auf dieser Partition, oder sogar nur 1,4 Sekunden wenn ich die erste Partition verwenden würde, da diese doppelt so schnell liest. (Liegt daran, dass sich die Platte am äußeren Rand schneller unter dem Lesekopf bewegt als innen.)

Aber wie viel ist dran an dieser Rechnung? Kann ich die Lesezeiten nicht auch direkt messen? Ja, ich kann. Mittels “ureadahead –dump” kann ich mir eine Liste der Dateien ausgeben. Zugegebermaßen, diese Dateien sind in der Summe 300 MB groß, beim booten werden aber nur 226 MB gelesen, da nicht alle Dateien komplett gebraucht werden. Bei den weiteren Messungen verwende ich stets diese 300MB Dateien komplett.

Mit ein bisschen Textersetzung erhalte ich aus der Dateiliste ein Skript, das nacheinander jede dieser Dateien nach /dev/null kopiert. Ich messe also mittels “time” die Ausführungszeit. 13,5 Sekunden? Da stimmt was nicht, das geht zu schnell. Ich messe nochmal: Diesmal nur noch 4,5 Sekunden!

Aber klar doch, die Dateien sind noch im Lesecache. Also diesen mal schnell mit

sync && echo 3 > /proc/sys/vm/drop_caches

leeren und nochmal messen. Ergebnis: 63,44 Sekunden. Das stimmt doch erstaunlich gut mit den berechneten 65 Sekunden überein.

Kann ich das auf 2,6 Sekunden reduzieren?

Die Frage ist jetzt: Wie kann ich das Lesen dieser Dateien auf die 2,6 Sekunden beschleunigen, die es dauern würde, wenn diese am Stück hintereinander stehen würden? Die Lösung: ich schreibe sie am Stück hintereinander :) Also kopiere ich all diese Dateien in ein neu angelegtes Verzeichnis. Anschließend leere ich wieder den Cache und lese all diese Dateien nacheinander ein. Statt 63,44 Sekunden braucht dies nur noch 31,49 Sekunden. Aber immer noch deutlich länger als erwartet. Dummerweise habe ich die Dateien in einer anderen Reihenfolge geschrieben, als ich sie nun gelesen habe. Also ein neuer Versuch, diesmal in gleicher Reihung geschrieben und dann gelesen, dazwischen natürlich wieder den Cache geleert. Und siehe da: 16,8 Sekunden. Eine Beschleunigung von 74% allein dadurch, dass die Dateien in der richtigen Reihenfolge hintereinander auf der Platte stehen.

Was aber, wenn ich sie mittels tar komplett zu einer Datei vereinige? Dann kann ich sie in 7,69 Sekunden einlesen. Und gepackt als .tar.gz dauert es sogar nur noch 1,8 Sekunden. Aber auch diese Datei liegt nun am langsamen Ende meiner Festplatte, am schnellen Ende wäre ich somit bei 0,9 Sekunden.Mir ist dabei übrigens total unklar, warum die .tar.gz 4,2 mal so schnell gelesen wird obwohl sie nur um den Faktor 2,7 kleiner ist. Wiederholte Messungen haben das aber bestätigt.

Was nützt schnelles Lesen, wenn die Daten dann gepackt sind?

Aber die Daten müssen ja nach bzw. während des Lesens noch entpackt werden, und zwar in den Arbeitsspeicher. Das dauert auf die naive Art und Weise 3,1 Sekunden, also deutlich länger, als die Daten ungezippt zu lesen. Dabei wird aber nur ein Kern benutzt. Es wäre aber einfach möglich, alle Kerne damit auszulasten. In meinem Fall mit zwei Kernen würde der Lesevorgang auf 1,55 Sekunden verkürzt, mit vier Kernen wäre das Entpacken schneller als das Lesen, so dass das theoretische Optimum von 0,9 Sekunden erreicht wird. Bekanntlich lese ich dabei ja komprimierte Dateien ein, die entpackt 300 MB ergeben, von denen ich aber nur 226 MB wirklich verwende. Ich war zu faul, für die Messung die richtigen 226MB zu extrahieren, aber wenn man hochrechnet, kommt man auf 0,678 Sekunden für das Lesen der benötigten Daten, immerhin ein Faktor von 93.

Fazit

Ich weiß, wie ich das Lesen der zum Booten benötigten Dateien von 63,44 Sekunden auf 0,678 Sekunden beschleunigen könnte, was den Bootvorgang vermutlich von auf die Hälfte verkürzen würde. Die nötigen Operationen habe ich im laufenden System getestet. Jetzt müsste ich “nur noch” herausfinden, wie ich das praktisch in den Bootvorgang einbinden kann… Das wird sehr wahrscheinlich meine Fähigkeiten und Kenntnisse übersteigen – aber vielleicht können meine Messungen ja jemand schlaueres dazu motivieren, sich des Themas anzunehmen. Offenbar ist ja noch einiges herauszuholen.

Higher display resolution – free and in less than 1 minute

Are you using Linux and would like some more screen resolution than your current display offers?

The short version

On a terminal, type

xrandr

In the output look for the first word in the second line (just under “Screen 0″). In my case, that’s “VGA1″. Other common values to look for are “lvds” and “default”. Then type something like

xrandr --output VGA1 --scale 1.5x1.5

Voila, that’s it!

Some technical details

This is a feature of X.org and is performed on your graphics board. It will create a larger desktop frame buffer, scale that down, and send the scaled output to your monitor. No matter what desktop resolution you were using before, your display will get the same type signal afterwards and won’t even notice that there is something special going on. So there’s practically no risk of damaging your display.

Most graphics boards will get pretty slow when your horizontal resolution is above 2048 pixels. Just calculate 2048 / (current horizontal resolution) to see what’s the maximum factor you should use instead of “1.5×1.5″. Also note that any scaling beyond 1.5 will likely result in unreadable small text.

In case you didn’t already figure it out, I should tell you how to get back to your original settings:

xrandr --output VGA1 --scale 1x1

Pictures

To show you what to expect from this little hack, I made some photos (screen shots wouldn’t give the same impression). What you see is a TFT display from 2005 featuring a physical resolution of 1280×1024.

Factor 1

Factor 1

Factor 1.333

Factor 1.333

Factor 2

Factor 2

 

Right now I’m working with the configuration shown on the second picture: a scaling factor of 1.333 and a desktop resolution of 1707 x 1365. Thats 77% more pixels for 0% more money!

Personal Background

I always wished for that feature, even more so since I had an OQO 1+ ultra portable PC with a tiny 800×480 screen. Most applications just don’t fit. The successor model OQO 2 had the same physical resolution but a built-in scaling mode to use a virtual resolution up to 1200×720 – as well as hardware keys to zoom in and out and resistive touch scroll bars along the display edges -wow.

Now I have a Dell Precision M70 with a physical resolution of 1920×1200. You wouldn’t believe it, but sometimes I’d wish for even more. Did you ever sit in front of an 30″ Apple Cinema Display? You’ll miss the 2560×1600 pixels once you get back. Sadly,  xrandr –scale does not work on my Dell system, neither with the default VESA driver nor with several versions of the Nvidia Quadro driver.

Surprisingly, it works well on one of the cheapest of possible graphics chips: The Intel GMA 950, and for the last 6 months I just did not try it.

Why is it so hard to have some libraries installed?

Edit: I asked a related question on stackoverflow.com, but since it was “not programming related” (!!!) is was moved over to superuser.com, where I got a nice answer and an even nicer comment to the answer. Now I know that “apt-file” can figure out which library to install, and 90% of my usual lib-install-sorrow is cured by this nice tool. Anyway, some cases remain where I just have to give up. You can read more about it here.

I feel completely lost each time I have to fulfill the dependencies of some C or C++ code.

I really do understand C, C++, static and dynamic libraries, header files and linking, as well as the packet manager “aptitude” but when it comes to the practical part, I have absolutely no idea what to do.

I mean, I know what to do on a theoretical level, and most of the time, I can even archive it. But over the year’s, I got so much better in all aspects of programming, but concerning library dependency resolution, I still feel like the 6 year old boy writing his very first for-next-loop. After going though this trouble so many times, there still is no pattern, no deterministic approach to follow, just desperate  fiddling around and running in circles.

First of all, I think it must be possible to get this libraries as a recompiled binary. If I had to compile them myself, I would be stuck in a recursive problem because I had to fulfill their dependencies, which involves compiling them as well, but first… I feel there must be something in between getting only the end-user executable and getting the full source of without binaries.

Sometimes, I manage to find a download, but it doesn’t say where to put it. So I prefer a packet manager, but that does not make it easier at all.

You might be tempted to say: It’s not that hard. Well, it is. If you don’t believe, read on.

Just an example

I will introduce an example to explain my problem, but really, I don’t ask for a specific solution for those three libs, I want some deeper understanding of how to approach that problem in general. I experienced the same with many more libs, and I remember having the same general problems when I was still using windows.

Three little libraries

I want to use code which states that “It utilizes glib2, curl and openssl” – it does not say anything else about it. All of that libs are absolutely standard, so it shouldn’t be hard at all to get them. I think this means I need static libraries from those projects, as well as header files. In the source I want to use, there is

#include <curl/curl.h>
#include <openssl/md5.h>
#include <glib.h>

And none of them is found at compilation time. I never know if this is really a missing file, or just misconfiguration of my build process, so each time I end up doing a fully recursive file search on my whole hard drive to see if those files are present anywhere. This time, they aren’t. Of course, I knew that I need to somehow get glib2, curl and openssl onto my computer. I think I can install them via apt-get.

So I tried sudo apt-get install curl openssl (let’s forget about glib for a moment). Still there is no curl.h on my system and all md5.h instances on my system have nothing to do with openssl. I know that some packages have variants with suffixes like -dev, -devel, -src, -source or a lib- or lib prefix, but I never know which to choose, and sometimes there are none of those at all.

Installing curl (and, by pure chance, also openssl)

For curl, there is the choice between curl, curlftpfs, flickcurl-doc, flickcurl-utils, gambas-gb-net-curl, gambas2-gb-net-curl, gimp-libcurl, gnupg-curl, libcurl-ocaml, libcurl-ocaml-dev, libcurl3, libcurl3-dbg, libcurl3-gnutls, libcurl3-gnutls-dev, libcurl3-openssl-dev, libcurl4-gnutls-dev, libcurl4-openssl-dev, libflickcurl-dev, libflickcurl0, libghc6-curl-dev, libghc6-curl-doc, libghc6-curl-prof, liblua5.1-curl-dev, liblua5.1-curl0, libwww-curl-perl, php4-curl, php5-curl, python-pycurl, python2.4-pycurl, slang-curl, spl-curl, tclcurl, xmms2-plugin-curl and somehow I figured out that libcurl3-dev sounds nice, but how do I really know? In the end, this also installed libcurl4-openssl-dev and got me a matching version of openssl’s md5.h.

Lucky me, bacause I wouldn’t have known which one to chose from openssl, aolserver4-nsopenssl, globus-openssl-progs, libcrypt-openssl-bignum-perl, libcrypt-openssl-dsa-perl, libcrypt-openssl-random-perl, libcrypt-openssl-rsa-perl, libcrypt-openssl-x509-perl, libcurl3-openssl-dev, libcurl4-openssl-dev, libengine-pkcs11-openssl, libengine-tpm-openssl, libglobus-gsi-openssl-error-dev, libglobus-gsi-openssl-error-doc, libglobus-gsi-openssl-error0, libglobus-openssl, libglobus-openssl-dev, libglobus-openssl-module-dev, libglobus-openssl-module-doc, libglobus-openssl-module0, libopenssl-ruby, libopenssl-ruby1.6, libopenssl-ruby1.8, libopenssl-ruby1.9, libopenssl-ruby1.9.1, libpathfinder-openssl-1, libxmlsec1-openssl, openssl-blacklist, openssl-blacklist-extra, openssl-doc, pyopenssl-doc, python-openssl, python-openssl-dbg, python-openssl-doc, python-pyopenssl, python2.4-pyopenssl, since there is no -dev package with a generic name for openssl.

glib

But still, this leaves me without glib, which is not to be confused with glibc. There are no matching packets, only glibc-doc and glibc-source. Starting from the reference page, I think there is no logical way I could find a download without using a search engine, but via google I managed to download a copy at http://www.gtk.org/download-linux.html – but it forced me to sudo apt-get install gettext in order to ./configure and make. It has dependencies on 6 other libraries, and I don’t want to think about what would have happended if I lacked those.

I think it’s worth saying that during this compilation, make called another make, which called bash, which called another bash, which called make, which called another make, which called bash, which called another bash, which called make, which called gcc which in turn called gc1. Is this depth of recursion really needed to build a low level helper library?

Whatever. After this, I have a glib.h in /usr/local/include/glib-2.0/. After adding this path to the include directory of the preprocessor, I end up with 363 errors inside glib’s header files. And with not a single idea how this is possible.

This is the standard case.

I’m totally used to create a hello world project, include a single .h file (like windows.h in the old Microsoft days) and start “fixing” 23 errors in that header. I can’t really believe there are real errors in major headers like windows.h but on the other hand, I don’t remember any project without them. Normally, it takes about 2 hours until my hello word can be compiled again, but from that point on, I can program anything I like without hitting any trouble.

But facing 363 errors, I’m completely convinced that

#include <iostream>
#include <curl/curl.h>
#include <openssl/md5.h>
#include <glib.h>

int main()
{
    std::cout << "Hello shit";
}

is better left as it was, without encrypted network access.

Return top