Rapperswil 2-7 augustus 2010: een C++ vergadering
Van 2 tot en met 7 augustus werd in Rapperswil, Zwitserland vergaderd door de ISO C++ standaardisatiecommissie. Ik was daar voor Nederland als Head of Delegation aanwezig namens het NeN voor AT Computing en de NLUUG.
Je kunt je afvragen waar in zo'n vergadering over gesproken wordt. Waarom moet er zo lang gepraat worden?
In de vergadering in Rapperswil waren 8 landen vertegenwoordigd door zo'n 60 mensen. Het grootste blok komt traditiegetrouw uit de verenigde staten. Ieder land heeft tijdens de stemmingen één stem. Daarom wordt tijdens de officiele zittingen altijd eerst over de Amerikaanse mening gestemd, waarna ieder "head of delegation" van de landen hun nationale stem mag uitbrengen. De leden van de standaardisatiecommissie werken bij vendors (compilerleveranciers zoals Microsoft, HP, Sun, RedHat (g++) en EDG (Edison Design Group een OEM compilerbouwer), C++ grootgebruikers zoals Bloomberg en Fermilabs, onderwijsinstellingen zoals universiteiten (en AT Computing!) en vele andere bedrijven en instellingen. Al deze mensen hebben belang bij een standaard die implementeerbaar is, bruikbaar is en onderwijsbaar is. Er zijn dus verschillende belangen, waardoor soms ook spannende discussies kunnen ontstaan.
De eerste C++ standaard (C++98) kwam uit in 1998. Daar is toen lang aan gewerkt. In 2003 kwam er een "tussenversie" waarin kleine onvolkomenheden werden gerepareerd, maar geen grote features werden toegevoegd. Er zit nu een echt nieuwe standaard aan te komen. De werktitel is C++0X hoewel de standaard niet in het eerste decennium van deze eeuw uit is gekomen. Er is vertraging opgelopen omdat op een vrij laat moment een groot feature uit de taal is verwijderd dat maar niet goed gespecifieerd leek te kunnen worden ("concepts"). Een reële datum lijkt nu medio 2011 te zijn.
Geen enkel commissielid kent de hele standaard, of begrijpt van alle ontwerp-beslissingen waarom die genomen zijn. Daarom wordt de vergadering opgesplitst in werkgroepen: Eén of twee werkgroepen over de bibliotheek, Eén of twee over de kern van de taal ("core") en een over concurrency (een van de nieuwe features in de taal is multi-threading). De werkgroepen lopen de voor hun relevante problemen door en doen dan een voorstel voor de gehele vergadering.
Hoewel de atmosfeer ontspannen en vriendschappelijk is, zijn met name de ISO zittingen erg officieel. Er mag absoluut niet de indruk ontstaan dat bedrijven hun mening proberen door te drukken of dat er gefraudeerd wordt. Tijdens de werkgroepvergaderingen wordt er ook regelmatig gestemd, maar dan veel informeler. Vaak worden er "straw polls" gehouden waar alle deelnemers aan de commissie mogen stemmen: "Stel dat we dit probleem oplossen op de besproken manier, zou je daar dan voor of tegen zijn". Meestal kun je kiezen uit vier standpunten: Strongly in Favor, Weakly in Favor, Weakly Against, Strongly Against. Afgekort tot SF, WF, WA en SA. Heel soms kun je ook stemmen voor OMDB ("over my dead body"), maar dat kwam tijdens deze vergadering niet voor. Vaak gaat het dan over nieuwe features, maar omdat in het stadium waarin de commissie nu zit geen nieuwe features worden toegevoegd, speelt dat nu niet.
De commissie heeft een werkdocument dat in feite de standaard in
aanbouw is. In juni 2010 hebben de leden van de ISO (de nationale
standaardisatiecommissies) mogen stemmen over de toenmalige versie
van dat document. Dat document had de status FCD - Final Committee
Draft. De landen hadden de gelegenheid de FCD goed of af te keuren,
en ze konden daarbij commentaar op de tekst zelf leveren. Dat
commentaar kan groot zijn (wij vinden dat feature XYZ verwijderd moet
worden: veel consequenties) maar ook erg klein: "op pagina 123 staat
dat de libraryfunctie zusenmezo een int teruggeeft, terwijl op pagina
456 een voorbeeld staat waarin de functie een long teruggeeft". Deze
commentaren heten "National Body Comments". Tijdens de vergadering in
Rapperswil zijn alle national body comments langsgelopen. Dat waren
er honderden.
De verwachting is dat over twee vergaderingen (in maart 2011) alle commentaren adequaat kunnen zijn afgehandeld en dat het werkdocument met de status FDIS (Final Draft International Standard) naar het ISO gestuurd zal worden. De landen kunnen er dan nog een laatste Ja of Nee tegen zeggen en hopelijk hebben we dan medio 2011 een C++11 standaard. Deze standaard maakt C++ makkelijker te gebruiken en makkelijker te leren.
Daarna blijft de commissie tweemaal per jaar bijeenkomen. Ten eerste zullen er toch weer problemen opduiken in het 1200 pagina's tellende document. Maar ook zal een werkgroep weer nieuw leven ingeblazen worden: evolution. In deze werkgroep worden nieuwe features voorbereid voor de standaard na 2011. Hopelijk zal het mogelijk blijken om het belangrijke onderwerp "concepts" dat helaas niet in de huidige FCD meegenomen kon worden nu wél op een goede manier n de standaard opgenomen kan worden. Het zal foutmeldingen van compilers een stuk beter maken, en het programmeren in C++ nog verder vergemakkelijken.
In een volgende blog gaan we kijken welke spannende features er in C++0X zitten en in hoeverre deze nu al bruikbaar zijn.
Op zoek naar de bron van de datacorruptie...
Thuis gebruik ik al jaren met veel plezier mythtv (http://www.mythtv.org) op een Linux systeem als videorecorder. We kijken bijna nooit meer live TV, het meest recente journaal staat altijd klaar, en reclames spoelen we zo door omdat mythtv die voor ons markeert.
Op een zeker moment begonnen nieuwe opnamen her en der "blokjes" te vertonen. Van die typische MPEG-artefacten die je ook wel eens bij satelliet-TV ziet als het weer erg slecht is, of bij DVB-T (Digitenne en dergelijke) als een slecht afgeschermde brommer voorbij komt rijden.
Toen ik als test een aantal video-files naar een andere machine
kopieerde om dáár het bestand beter te bekijken, gaf rsync af en
toe foutmeldingen dat het kopieren niet goed gelukt was: de checksum
aan beide zijden was niet hetzelfde.
Pardon?
Er leek dus iets mis met de hardware. Het geheugen is het makkelijkst te testen. Ik heb memtest86 (http://www.memtest86.com/) een dag laten draaien om het geheugen te testen. Geen enkel probleem.
Dan de disk. In de logfiles was niets te zien. Het viel het me wel op
(bij de vele keren rebooten) dat er af en toe een filesystem op de
disk corrupt was. smartctl wist me te vertellen dat de disk zelf
niet het idee had dat hij "bijna defect" zou zijn. En bij het
controleren van de disk gekoppeld aan een ander systeem vond ook
badblocks dat er niets aan de hand was. Ook andere intensieve tests
op de disk aan een ander systeem lieten geen disk-problemen zien.
Vreemd.
De laatste test die ik deed gaf uitsluitsel. Ik schreef een klein programmaatje dat willekeurige bytes in een file zet:
#include <stdlib.h>
#include <stdio.h>
int main() {
srandom(0);
const int n=1024;
short ar[n];
long long i;
int idx;
for (i=0, idx=0; i<2L*1024*1024*1024 / sizeof(ar[0]); ++i) {
ar[idx++]=random();
if (idx==n) {
write(1, ar, sizeof(ar));
idx=0;
}
}
}
Dit programma schrijft 2GiB aan pseudo-willekeurige bytes naar
standard output. Die gegenereerde random getallen zijn voorspelbaar
als je het begingetal kent. Ze zijn niet goed genoeg voor
cryptografische doeleinden, maar wel goed genoeg om reproduceerbaar,
min of meer willekeurige bytes te maken. Iedere keer dat het
programma start, krijg je bij hetzelfde begingetal dezelfde reeks.
Dat begingetal wordt gezet met de functie srandom. Hier gebruiken
we het begingetal 0. De 2GiB aan gegenereerde data kun je vervolgens
in een file zetten:
./randfile > OUT
Door het programma nogmaals te draaien (met hetzelfde begingetal 0), kun je vergelijken of wat er in de file staat, overeenkomt met wat er door het programma wordt geschreven:
./randfile | cmp OUT -
En wat bleek? In ongeveer één op de miljoen bytes, was het meest significante bit (met de waarde 128) van 1 op 0 gevallen (zo werd een byte met de hexadecimale waarde C3 nu 43, en een byte met de waarde F9 werd 79). Het leek dat bij het schrijven naar de disk, soms de data niet goed bij de disk aankwam. Het probleem zat niet in het lezen: nadat ik de file gemaakt had, en het programma op een andere machine startte, bleken de bytes ook echt fout op de disk te staan. Ook met andere disks trad dit probleem op. En op een andere machine met dezelfde disk, trad het verschijnsel niet op. Het probleem leek dus niet aan de disk zelf te liggen.
Het probleem werd opgelost door een ander moederbord te nemen, en daar de videorecorder weer mee op te bouwen. Toen dat gebeurd was, waren nieuwe opnamen weer vrij van blokjes, en traden filesystem problemen niet meer op.
Performance-problemen oplossen zonder extra hardware
Laatst was een van onze consultants bij een klant die last had van ernstige performance-problemen. Na uitbreiding van het aantal clientprocessen was het systeem bij tijd en wijle onbruikbaar traag.
In dergelijke gevallen komt dan al snel het aloude programma top om de hoek zetten om te kijken waar het probleem nu werkelijk in zit.
Helaas laat top op systeemniveau niet zien hoe het resourcegebruik is van disk en netwerk; dus wachtsituaties die bij die resources ontstaan zijn niet te zien. Gelukkig laat atop deze wel zien.
Na installatie van atop bleek dat van de 24 CPUs er hooguit 6 werk hadden, en er 18 idle waren. De CPU-belasting kon dus niet het probleem zijn. Het beschikbare geheugen (48GiB) werd voor 70% benut door de cache en er was geen swapping actief. Geheugengebrek was dus ook niet de oorzaak van het performance-probleem. Ook de disks konden de vraag nog aan: ze waren gemiddeld 30% busy. En het netwerk (gigabit) kon de stroom data van circa 10 megabit/s ruimschoots aan.
Je kunt je natuurlijk afvragen: hoe kan een systeem waarvan deze vier hardware resources niet overbelast zijn, toch zo onwerkbaar traag zijn. Vaak denken mensen dat als een systeem te traag is, er door extra of snellere hardware verlichting verkregen kan worden. Helaas is dat niet altijd (of eigenlijk: meestal niet) het geval.
Laten we een voorbeeld nemen. Stel dat er tegelijkertijd 100 applicaties draaien op het systeem die allemaal een record in een bestand willen aanpassen. Ze zullen daarvoor een record lock aanvragen bij het systeem. Als ze allemaal een ander record willen aanpassen, kunnen ze tegelijkertijd op het bestand werken. Maar wat nu als de applicatie zo geschreven is dat (om welke reden dan ook) er geen lock wordt aangevraagd voor een enkel record, maar voor de gehele file? Dan kunnen de 100 applicaties niet meer tegelijkertijd de file aanpassen, en zullen ze een voor een aan het werk moeten gaan. Zelfs al heb je 24 CPUs en zou je dus 24 applicaties echt tegelijk kunnen afhandelen. Als er nu per seconde meer nieuwe aanvragen binnenkomen dan er een-voor-een per seconde kunnen worden afgehandeld, krijg je een steeds groter wordende achterstand.
Je kunt dit vergelijken met een 24-baans snelweg waarvan op een klein stukje van de weg maar één baan mag worden bereden. Als je het brede deel van de snelweg verbreedt van 24 rijstroken naar 48, levert dat helemaal niets op. Het is de wegversmalling die het probleem oplevert. Hier geldt: meer asfalt, niets wijzer. Als je de wegversmalling zou verbreden (waarschijnlijk een veel goedkopere oplossing dan de hele weg verbreden), heb je het probleem op een veel effectievere manier opgelost.
In de praktijk blijkt dat software resources (zoals locks en
semaforen) erg vaak de reden zijn van performance-problemen.
Dergelijke wachtsituaties kun je zien door te kijken naar het
wait-channel in de uitvoer van ps:
$ ps -o pid,wchan:20,s,cmd
PID WCHAN S CMD
32275 wait S -bash
32277 pipe_wait S awk {n+=$0} END {print n}
32278 fcntl_setlk S tstlock
32279 - R tstlock
32280 fcntl_setlk S tstlock
32281 fcntl_setlk S tstlock
32282 fcntl_setlk S tstlock
32283 fcntl_setlk S tstlock
32284 fcntl_setlk S tstlock
32285 fcntl_setlk S tstlock
32299 - R ps -o pid,wchan:20,s,cmd
We kunnen hier duidelijk zien dat er maar een tstlock proces is dat loopt (de status is R). De andere staan allemaal te wachten op het verkrijgen van een file lock (ze staan in de kernel te wachten op fcntl_setlk). Op een systeem met meerdere CPUs staan hier de andere CPUs duimen te draaien...
Moraal van dit verhaal: Kijk bij performance-problemen naar alle resources, en niet alleen naar de hardware resources. Voor je het weet heb je veel geld uitgegeven aan nieuwe hardware die het probleem niet oplost omdat de problemen in de applicatiesoftware zitten. Motto: extra ijzer, niets wijzer. En oh ja, bij die klant kwam het ook goed zonder andere hardware te hoeven kopen.
To bash or to ksh, what is the difference?
In onze Linux/UNIX deel 2 cursus gaat het over shell scripting, met awk en sed daarbij behandeld. We mikken niet op allerlei exotische shells, maar gaan ervan uit dat men op commerciele UNIX'en (Solaris, HP/UX, AIX) een ksh gebruikt, en bij Linux en ..BSD een bash. Toch willen we niet dat de cursus vol gaat zitten met "bij ksh doe je het zus, en bij bash doe je het zo". Er zijn best veel detailverschillen tussen die twee shells, maar die zitten gelukkig bijna allemaal in de categorie "speelgoed voor gevorderden". Je kunt flinke scripts bouwen zonder dat verschillen de kop opsteken.
Dus als je een keer een script moet porten van een ksh-omgeving naar een bash-omgeving, of omgekeerd, dan zou aanpassen van de ''#!/bin/ksh'' versus ''#!/bin/bash'' voldoende kunnen zijn
Het enige verschil waar we in bovengenoemde cursus op wijzen is het gedrag van ''echo'' wanneer je daarbij de regelovergang wilt onderdrukken:
echo 'Maak nu uw keuze: \c' # Posix-standaard
echo -n 'Maak nu uw keuze: ' # Berkeley-stijl
De Berkeley-versie is het meest verbreid, maar ze is niet conform de Posix standaard. Bij Linux zit die Berkeley-vorm zowel in de ''/bin/echo'' executable als in de built-in echo van ''bash''. De Posix-standaard vorm komt uit de Korn Shell, maar vind je daar momenteel niet meer in terug.
Dave Korn vertelde een keer dat hij zoveel mails kreeg dat zijn shell het fout deed, dat hij maar is opgehouden met te antwoorden dat de fout bij de andere partij zit omdat die van de standaard afwijkt. Dus in de huidige ''ksh'' werkt de built-in ''echo'' ook op de ''-n'' manier. Maar als je een mix van oudere en jongere ksh versies in je computerverzameling hebt, dan kan dat nog wel portabliteitsproblemen veroorzaken. De beste oplossing is om, als je speciale effecten in je ''echo'' wilt hebben, helemaal geen ''echo'' commando te gebruiken maar over te stappen op ''printf''. Echo blijft het gemakkelijkste werkpaard voor recht toe recht aan boodschappen.
In de praktijk ben ik ook geregeld gestoten op een ander gemeen verschil tussen ksh en bash, dat zit in de afhandeling van pipes:
commando1 | commando2
De ''bash'' zal het laatste commando in deze reeks uitvoeren in een soort "sub-shell" context, vergelijkbaar met wat ronde haakjes in shell-taal doen, en wat in shell-functies gebeurt. De ''ksh'' voert (in dit geval) het laatste commando uit in de context van de hoofd-shell van het script. Het verschil tussen die twee manieren merk je alleen als dat laatste commando in de shell een blijvende verandering maakt, zoals vullen van een shell-variabele:
VAR=tekst1
echo tekst2 | read VAR
echo $VAR; # ksh geeft nieuwe tekst2, bash geeft oude text1
Als je een shell-variabele wilt vullen met een brokje informatie dat gebouwd moet worden door een pipe line van commando's dan kun je dus beter een alternatief kiezen dat in beide shells werkt:
VAR=$(commando | ...)
Het is een erg handige construtie om na de pipe een ''while''-loop te gebruiken:
VAR=tekst1; LINECOUNT=0
echo 'tekst2
tekst3' | while read VAR; do
let LINECOUNT++
echo VAR in de loop is $VAR
done
echo $LINECOUNT regels gehad en VAR na afloop is $VAR
Binnen de loop gebeurt wat je verwacht, en in beide shells hetzelfde: achtereenvolgens zie je in de loop de ''tekst2'' en ''tekst3'' worden afgedrukt. Maar na afloop meldt ''bash'' dat VAR ''tekst1'' bevat. Dus die is terug naar de waarde van vóór de loop, en consistent met het vorige voorbeeld. ''Bash'' meldt ook een LINECOUNT van 0. ''Ksh'' meldt dat de VAR leeg eindigt. Dat komt omdat de laatste ''read VAR'' niks meer binnenkreeg, en daardoor eindigde de loop. De LINECOUNT is bij ''ksh'' 2, zoals het hoort.
De moraal blijft dus: let op bij een pipeline die een blijvend resultaat binnen de shell-toestand moet opleveren.
Mag het een bitje meer zijn?
Geplaatst door jacco op 2010-05-12 15:38:12 | Permanente link | Categorie: Systeembeheer, Whitepaper | Reacties: 0
Hoeveel bytes bevat een kilobyte?
Volgens sommigen: 1000. Volgens anderen: 1024. Weer anderen zeggen: "Het hangt er van af aan wie je het vraagt."
Er is spraakverwarring over en dat komt de duidelijkheid en transparantie niet ten goede.
Het SI-voorvoegsel (Uit het Frans: Système International d'unités) kilo staat voor 1000 (x 103). Mega staat voor x1000x1000 (x 106). Daarna komen nog giga (x 109), tera (x 1012), peta (x 1015), exa (x 1018), zetta (x 1021) en yotta (x 1024).
Computers werken met bits (binair, 0 of 1: 2 mogelijkheden) en rekenen daardoor makkelijker met grootheden van 2 tot de macht X. Het getal 1000 wordt daarbij het dichtst benaderd door 210 (= 1024).
Toen het computeren nog in de kinderschoenen stond, werden de SI-voorvoegsels misbruikt voor veelvouden van 1024. Bijvoorbeeld: 1 kilobyte = 210 bytes = 1024 bytes. 1 megabyte is dan 1024 kilobyte.
Handig in het gebruik en het verschil is ook niet zo groot.
Hoe worden de voorvoegsels in de praktijk gebruikt?
Een kachel van 2 kilowatt heeft een vermogen van 2.000 watt.
De afstand tussen Utrecht en Nijmegen is 85 kilometer, dat is dus 85.000 meter.
Deze foto kost 2 megabyte. Dat is 2 x 1024 x 1024 = 2.097.152 bytes (en niet 2.000.000).
Via mijn ADSL-aansluiting kan ik downloaden met een snelheid van maximaal 8 megabit per seconde. Dat is 8.000.000 bits per seconde.
Op mijn nieuwe harddisk past 1 terabyte, ofwel 1000 gigabyte, ofwel 1.000.000.000.000 bytes.
Op een 3,5" floppy past 1,44 megabyte. Dat is niet 1,44 x 1000 x 1000 bytes, ook niet 1,44 x 1024 x 1024, maar wel 1,44 x 1000 x 1024 (= 1.474.560).
Namelijk: 2 koppen x 80 cylinders x 18 sectoren x 512 bytes = 1.474.560.
Dit was niet tot ieders tevredenheid: afgezien van het feit dat er spraakverwarring optreedt, is 1000 gewoon niet gelijk aan 1024.
En is het verschil bij kilo nog niet zo groot (2,4%), bij tera (10004 t.o.v. 10244) is het verschil al opgelopen tot 9,95%. Om nog maar niet te spreken over yotta (20,89%).
Daarnaast is er ook een probleem met afkortingen: Het is niet duidelijk of met de afkorting kb nu kilobyte of kilobit wordt bedoeld. Een (stilzwijgende) afspraak is dat voor bit een kleine b wordt gebruikt, en voor byte een grote B.
Verwarring alom.
De International Electrotechnical Commission (IEC) heeft zich de kritiek aangetrokken. In 1998 is een standaard ingevoerd die orde in de chaos heeft geschapen door een handvol nieuwe voorvoegsels (prefixen) te introduceren. Deze IEC-prefixen verwijzen naar binaire veelvouden: kibi (210), mebi (220), gibi (230), enz.
| Decimale veelvouden volgens SI (1000X) | Binaire veelvouden volgens IEC (1024X) | |||||
|---|---|---|---|---|---|---|
| Macht | Afko | Prefix | Verschil | Prefix | Afko | Macht |
| 103 (10001) | k | kilo | 2% | kibi | Ki | 210 (10241) |
| 106 (10002) | M | mega | 5% | mebi | Mi | 220 (10242) |
| 109 (10003) | G | giga | 7% | gibi | Gi | 230 (10243) |
| 1012 (10004) | T | tera | 10% | tebi | Ti | 240 (10244) |
| 1015 (10005) | P | peta | 13% | pebi | Pi | 250 (10245) |
| 1018 (10006) | E | exa | 15% | exbi | Ei | 260 (10246) |
| 1021 (10007) | Z | zetta | 18% | zebi | Zi | 270 (10247) |
| 1024 (10008) | Y | yotta | 21% | yobi | Yi | 280 (10248) |
Storagefabrikanten - zoals producenten van harddisks - rekenen in megabytes en terabytes, dus in 1000-tallen. Dat zorgt nogal eens voor een stukje consumentenfrustratie: "Ik heb een nieuwe harddisk gekocht, maar die blijkt veel kleiner te zijn dan op de verpakking wordt aangegeven!"
Als je een harddisk van 1 terabyte (1 TB) koopt, krijg je een rauwe opslagcapaciteit van 1.000.000.000.000 bytes, ofwel 90.95% van de grootte die je verwacht als je ervan uitgaat dat 1 kilobyte 1024 bytes bevat. En daar gaat dan nog wat snijverlies en overhead van af omdat er partities en/of filesystemen gemaakt moeten worden.
De zebibyte (ZiB) en yobibyte (YiB) zijn momenteel nog niet daadwerkelijk in gebruik als je het over opslagcapaciteit hebt. Om een YiB aan informatie op te slaan op 3,5" floppies (wie gebruikt ze nog?), heb je een stapel floppies nodig ter grootte van 2 maal de afstand van de aarde naar de zon.
Meer leesvoer:
Rsync en performance
Geplaatst door jc op 2010-05-04 12:59:53 | Permanente link | Categorie: Tips and Tricks | Reacties: 0
Het Probleem
Ik was laatst een nieuwe disk aan het in-gebruik-nemen, waarbij ik veel grote files moest kopieren van de oude (kleinere) disk. Dat soort dingen doe ik normaliter met rsync (daarvan zitten de opties in mijn vingers). Maar nu zag ik dat de performance bedroevend was. Ik moest zo'n 700GiB aan data overpompen, en dat ging met een tempo van zo'n 30MiB/s. Beide disks kunnen ieder minstens 100MiB/sec lezen en/of schrijven. En ik haalde dus nog geen derde daarvan. (We hebben het over een totale doorlooptijd van ruim 2 uur versus 6 uur!)
Meten...
Ik ben toen eens wat gaan meten en gaan spelen. Hiervoor bedacht ik een simpele benchmark: het kopieren van een file van 10GiB. Zowel de bronfile als de bestemming stonden op een ext4 filesysteem dat ik op de buitenste (snelste) tracks van de twee fysieke disk formatteerde.
Als kopieerprogramma's gebruikte ik:
- rsync
- cpio
- cp
- cat
uiteraard voorafgegaan door commando's om de cache te legen en afgesloten door een sync om de cache te flushen. Dus bijvoorbeeld:
sync # forceer dirty buffers naar disk
echo 3 > /proc/sys/vm/drop_caches # gooi caches weg
time sh -c "cp $SRC $DEST; sync" # meet cp én sync tijd
De echo naar /proc/sys/vm/drop_caches forceert het volledig invalideren van de cache. Dat werkt alleen voor de niet-dirty pagina's, daarom dat we eerst een sync commando gebruiken om alle dirty pagina's naar disk te forceren. Het betreffende kopieer programma zal de 10GiB file kopieren, maar ook eindigen vóórdat de laatste blokken naar disk worden geschreven (die blijven nog 30 seconden in de cache plakken). Daarom meet het time commando de tijd die nodig is voor het kopieer programma, en de sync om de laatste restjes te flushen.
De metingen voor rsync, cpio, cp en cat wezen het volgende uit:
user sys elaps hog MiB/s test
158.75 108.71 320.08 83% 31 rsync
5.24 80.60 116.81 73% 87 cpio
0.73 53.41 109.36 49% 93 cp
1.42 62.03 108.80 58% 94 cat
Ik ben daarop wat nader gaan kijken. Wat blijkt: rsync heeft 3 processen nodig: een lezend, een schrijvend en een niets-doend (control?) proces. Op mijn 4-core systeem draaien ze bijna de hele tijd alledrie op één enkele CPU. Met het commando taskset kun je afdwingen op welke CPUs een proces mag draaien. Stel dat de drie rsync processen de PID's 1111, 1112, 1113 hebben, dan kun je afdwingen dat ze ieder op hun eigen CPU draaien met:
taskset -pc 0 1111 # forceer op CPU0
taskset -pc 1 1112 # forceer op CPU1
taskset -pc 2 1113 # forceer op CPU2
Door met het taskset commando meteen na het starten ieder rsync proces zijn eigen CPU te geven, gaat de throughput omhoog van 31MiB/s naar 39MiB/s. Als de drie rsync processen met taskset geforceerd worden op één CPU, loopt de performance terug naar 27MiB/s.
rsync heeft daarnaast erg veel user+sys CPU-tijd nodig. Ondanks dat, schaalt de on-demand cpufreq niet de frequentie omhoog. Als ik de frequentie forceer op de hoogst mogelijke met:
for i in 0 1 2 3 ; do
echo performance > /sys/devices/system/cpu/cpu$i/cpufreq/scaling_governor
done
dan gaat de throughput van rsync fors omhoog: 58MiB/sec. De CPU's draaien dan op de hoogst mogelijke frequentie (op dit systeem 2.6GHz). Als we dat combineren met de taskset truuk om de drie rsync processen ieder hun eigen CPU te geven, weten we er zelfs 79MiB/s uit te persen. Nog altijd zo'n 20% lager dan de andere, en tegen flink CPU-verbruik, maar toch.
De conclusie is dat je door in plaats van rsync, cp te gebruiken in de default instellingen, je van 30MiB/s naar 93MiB/s kan gaan. Maar ook door een beetje te spelen met de instellingen van het systeem, kun je zelfs met rsync flinke verbeteringen bereiken!
throughput #CPUs frequentie
22MiB/s 1 CPU, 0.8GHz
23MiB/s 1-3 CPUs, 0.8GHz
27MiB/s 1 CPU, ondemand
31MiB/s 1-3 CPUs, ondemand << default
38MiB/s 3 CPUs, 0.8GHz
39MiB/s 3 CPUs, ondemand
58MiB/s 1-3 CPUs, 2.6GHz
58MiB/s 1 CPU, 2.6GHz
79MiB/s 3 CPUs, 2.6GHz
In de tabel geeft de tweede kolom aan hoe de rsync processen over de CPU's verdeeld werden: 1 CPU wil zeggen dat met taskset de drie rsyncs alledrie op één en dezelfde CPU gedwongen werden. 1-3 CPus wil zeggen dat de scheduler zelf de vrije hand had, en 3 CPU's wil zeggen dat ieder rscyn proces met taskset zijn eigen CPU kreeg.
Je kunt duidelijk zien dat het slechter kan dan de default instellingen, maar ook heel veel beter!
De toekomst...
Op Linux Weekly News http://lwn.net/Articles/384132/ stond recentelijk een bericht dat de ondemand scheduler moeite heeft met processen die veel I/O doen en ook vrij veel CPU tijd nodig hebben: In de tijd dat de CPU op disk I/O staat te wachten, wordt de CPU weer naar een lage frequentie teruggeschaald. Als het proces dan weer wil rekenen duurt het enige tijd voordat er weer omhoog wordt geschaald. Arjan van de Ven van het Intel Open Source Technology Centre heeft een aanpassing op de ondemand scheduler aangebracht die de CPU pas omlaag schaalt als deze echt idle is (en niet op disk I/O staat te wachten).
Je kunt dit verschijnsel ook mooi zien:
Als je
modprobe cpufreq_stats
doet, krijg je precies (in jiffies gemeten) het aantal hits te zien voor de verschillende te gebruiken clock frequenties.
Bekijken we dit voor een rsync commando, dan zien we bijvoorbeeld voor cpu nummer 2:
cat /sys/devices/system/cpu/cpu2/cpufreq/stats/time_in_state
2600000 423293
1900000 363
1400000 534
800000 6645805
Je kunt hier dus zien dat cpu2 (sinds het laden van de module) het grootste deel van de tijd in de lage frequentie (0.8GHz) heeft gelopen.
De aanpassing van Arjan van de Ven is nog een lapje voor het bloeden, want hij heeft een hele nieuwe governor in voorbereiding.
Fontnamen wijzigen in een OO document
Geplaatst door hjt op 2010-04-09 17:51:33 | Permanente link | Categorie: Systeembeheer | Reacties: 0
Na mijn vorige blog over de verschillende versies van eenzelfde font, met alle lay-out ellende van dien, gaat dit blog-verhaal over het vervolg van de operatie.
We wilden meer controle over de fonts die in onze cursusdocumentatie voorkwamen. Helvetica (proprietary eigendom van Linotype) en Courier (proprietary eigendom van Monotype, oorspronkelijk voor IBM ontworpen), en Ariel en Verdana (beiden proprietary eigendom van Microsoft) wilden we toch maar uitbannen en vervangen door leden van de Nimbus-Sans familie, om meer controle over de weergave te krijgen. We wilden niet weer verrast worden door allerlei "automatische" font-substituties zoals die plaats kunnen vinden door het 'defoma'-mechanisme (Debian Font Manager): http://mintaka.sdsu.edu/GF/bibliog/latex/debian/defoma.html of zelfs door Adobe Acroread: http://www.creativepro.com/article/acrobat-tips-fonts-can-make-or-break-pdfs
Omdat .odg en .odp files XML-bestanden zijn kwamen we op het idee om een batchmatige fontnaam-zapper te bouwen. Dat werd een shellscript, plus een C-programma. Het script begint als volgt:
# Pak de .od[gp] file uit en onthoud in welke volgorde
# de onderdelen als aparte files eruit kwamen:
unzip "$1" > unzipsequence
ed -s unzipsequence << 'Here'
1,$g/^ *Archive:/d
1,$s/^ *[^:][^:]*: *//
1,$s/ *$//
w
q
Here
Dit script verwacht te starten in een lege directory, en $1 is de naam van de te bewerken .od[pg]-file (die dus in een andere directory moet staan). We unzippen die file, en vangen de outputboodschappen op. Die vertellen de volgorde waarin de onderdelen werden "ontzipt", en die volgorde willen we voor de zekerheid later weer reconstrueren.
In de daaropvolgende ed-sessie met Here-document trimmen we overbodig geachte boodschappen weg. Dat had ook wel met sed in een pipeline achter het unzip-commando gekund.
Het unzippen van een .od[pg] file levert een hele boom aan losse files en subdirectories op. Files met naam-extensie .xml vormen de kern van deze verzameling.
Die gaan we allemaal langs, en geven we aan ons C-programma dat in de scriptcode hieronder $ZAPFONTS is genoemd. Daarover straks meer:
# Selecteer uit de fileverzameling degenen waar fontnamen
# in kunnen staan. Geef die aan het 'zapfonts' programma.
# ODF files kunnen subdirs bevatten met z.g. embedded objects.
# Deze heten "Object 1" enz. met spatie in de filenaam.
# dus de dubbelquotes om "$name" zijn essentieel.
find . -type f -name '*.xml' | while read name; do
$ZAPFONTS "$name" > tt
mv tt "$name"
done
Nadat we alle fontnamen hebben vervangen, "zippen" we de verzameling losse files weer in elkaar. We gebruiken de output-boodschappen van de oorspronkelijke unzip om de files weer min of meer in hun oorspronkelijke volgorde te krijgen. Ik weet niet of dat nodig is, maar het leek me een nuttige (en niet zo moeilijk te realiseren) voorzorgsmaatregel.
# Voeg alle onderdeel-files weer bij elkaar:
cat unzipsequence | zip -X outfile.odp -@
mv outfile.odp "$1"
rm -rf *
De opnieuw ingepakte file schrijven we over de oorspronkelijk aangeleverde $1 filenaam heen, en we vegen de huidige directory weer net zo schoon als hij was aan het begin van de rit.
Een opmerking terzijde: als je in een shellscript het commando "rm -rf *" hebt staan, dan moet je wel heeeeel erg zorgvuldig alle cd-commandos in het script controleren. Want als een cd-commando mislukt dan ben je daarna met deze 'rm -rf *' goed de pineut. Gelukkig bevat het huidige script geen enkel cd-commando omdat het aanneemt in een lege directory te beginnen. Maar een 'if [ $(ls | wc -l) -ne 0 ]; then...' test aan het begin is toch verstandig. In andere scripts waarin ik zo'n 'rm -rf' moest verwerken heb ik na elk cd-commando een controle op de output van pwd toegevoegd.
Blijft over om een paar woorden te wijden aan het gebruikte ZAPFONTS C-programma. Ik zal u de source-code besparen maar liefhebbers kunnen op verzoek een kopietje krijgen.
Een xml-bestand bestaat uit tekstregels, dus in eerste instantie denk je in C aan een loopje in de trant van
while(fgets(......) != NULL) {
zap de fontnamen in deze regel
fputs(.......)
}
Dit is "Standard-I/O library voor beginners". Maar 'fgets' vereist dat je van tevoren een maximale regellengte moet inschatten. Toen ik wat XML-files bekeek om mijn schatting te onderbouwen bleek dat die soms waanzinnig lange regels bevatten: tot een paar duizend characters toe.
Uit mijn UNIX-jeugd, lang voordat het web bestond, herinner ik me een tijdschrift-artikel waarvoor iemand de meestgebruikte UNIX-commando's had getest op tekstfiles met lange regels: van 10000 characters per stuk. Bijna geen enkele utility overleefde (toen) de test. Bij deze XML-files moest ik ook oppassen.
Ik besloot mijn C-programma geen regels te laten lezen, maar porties van 1Kb. Dan loop je wel het gevaar dat een fontnaam precies over zo'n portiegrens heen ligt. Dus ik werk nu met een array van 2Kb, en ik begin met twee porties van 1Kb data uit de file te lezen, en achter elkaar in het array te plaatsen. Dan scan ik de eerste 1Kb-plus-een-paar-dozijn characters en zap de "foute" fontnamen. Dat stuk schrijf ik weer uit. Vervolgens schuif ik de tweede Kb in het array naar voren, en lees er een nieuwe 1Kb portie achteraan, enz.
Het feit dat een nieuwe fontnaam langer of korter kan zijn dan de oude naam die hij vervangt maakt het uitschrijven nog een beetje gecompliceerd, maar het is al met al best te doen. Ik heb dat in elk geval sneller zelf geprogrammeerd dan dat ik op het Internet moet zoeken naar een programma dat het kan, gevolgd door het beoordelen of dat wel solide genoeg is gemaakt.
Nadat een .odg of .odp bestand op deze manier gezapt is, is het verstandig om het even in OO te laden, en door te bladeren voor visuele inspectie. Wij vonden af en toe een plaats waar nog wat positioneringen op een pagina gecorrigeerd moesten worden. Maar in het algemeen is de operatie erg soepel verlopen.
Overigens: voor wie in typefonts is geïnteresseerd levert Wikipedia een schat aan informatie. Zoek maar eens naar een van de bekende font-namen.
OpenOffice font problemen
Geplaatst door hjt op 2010-04-01 14:09:36 | Permanente link | Categorie: Systeembeheer | Reacties: 0
Bij ATComputing maken we het merendeel van onze cursusdocumentatie zelf. Dat is, denken wij, een fundament onder onze goede naam, maar ook een flinke last op onze schouders. We zitten daarbij natuurlijk niet te wachten op problemen met de gebruikte software. Toch hebben we al het nodige voor onze kiezen gehad.
Al vele jaren geleden zijn we voor onze presentaties (toen nog overhead-projectie) OpenOffice gaan gebruiken. Voorheen hadden we een commercieel pakket "Island Draw" onder Solaris gekocht. Maar de makers werden op een gegeven moment opgekocht door een concurrent, die het pakket daarna vakkundig de nek omdraaide. Wij bleven zitten met honderden bestanden in proprietary formaat, en executables die afhankelijk waren van een license key waarin een specifiek CPU-id was verwerkt. Gelukkig is de voormalige importeur van het pakket ons nog lang behulpzaam geweest met "naleveren" van benodigde keys. Maar op een gegeven moment deed ook zijn key-generator het niet meer. Van proprietary bestandsformaten hadden we onze buik inmiddels wel vol.
In ons bedrijf proberen we wat UNIX- en Linux versies betreft te voorkomen dat we eenkennig worden. Onze medewerkers gebruiken op hun laptops en hun thuis-computers allerlei verschillende distributies. Ook binnen het bedrijf is variëteit. Maar bij OpenOffice "draw" bestanden merkten we keer op keer dat bij Courier- en Nimbus fonts verschillen ontstonden: op de ene computer tekende je een alinea tekst met een randje eromheen of pijltje ernaartoe, en op een andere computer toonde dat bestand de tekst half buiten de rand, en de pijl ver naast zijn doel. Het probleem zat niet in zo'n bestand zelf: als je dat ongewijzigd terugverhuisde naar de oorspronkelijke computer stond alles weer netjes op z'n plaats. Nauwkeurig kijken maakte duidelijk dat ergens een font-metrics probleem moest zitten, met verschillend gedefinieerde letterhoogten voor hetzelfde font.
Ik ben nog steeds geen expert in de vraag waar een OpenOffice programma nu eigenlijk zijn fonts vandaan haalt. Wel weet ik dat dat een reuzendoolhof is. Hier speelt ook de X font server zijn rol mee. Een commando als 'xlsfonts' meldt vaak al een paar duizend fonts. Ons probleem werd niet alleen beïnvloed door de fontverzameling op de lokale machine, maar ook nog door de netwerk-wijd aangesproken fontserver.
Om toch ergens te beginnen zette ik 's avonds laat onze centrale font-server maar eens stil. Hier loert een soort Heisenberg-onzekerheid waarbij de manier van meten een grote invloed kan uitoefenen op wat je meet. Als OpenOffice bij afwezigheid van een fontserver een fall-back doet naar lokale fonts, dan kijk je misschien tegen een heel nieuwe situatie aan. Maar het probleem in de tekeningen bleef bestaan, dus moest binnen een lokale machine te traceren zijn. Mijn kansen stegen.
OpenOffice starten met een grafische muisklik is mooi, maar voor trouble-shooting niet handig. Via het configuratie-menu'tje voor de iconen kwam ik achter de naam van de executable file, maar dat was een shellscript. Langs een heel spoor van shellscripts en symlinks kwam ik uiteindelijk bij een "echte" 'soffice.bin' executable. Maar die is slechts een paar duizend bytes groot, dus daar zouden nog wel wat kindprocessen bij gaan horen. Nu maar eens kijken welke files een startende OpenOffice allemaal aanspreekt met mijn problematische tekening:
strace -f -e trace=desc -o mijntracefile \
/usr/lib/openoffice/program/soffice.bin mijntekening.odg
Meteen na het zichtbaar worden van de tekening stopte ik OpenOffice weer. Mijn tracefile was "maar" 15000 regels groot geworden, hoewel 'trace=desc' het tracen beperkt tot file-descriptor gerelateerde system calls. Een tijdje rondbladeren gaf me de indruk dat de volgende selectie wel eens goed zou kunnen inzoomen: zoek naar de string 'font', maar ik hoef geen NOENT-regels (openen van een file mislukt) en geen configuratie-bestanden:
grep -i font mijntracefile | grep -v -e NOENT -e conf
En jawel: nog maar een kort lijstje over, in deze trant:
7986 read(47, "lias our fonts to common familie"..., 8192) = 2332
7986 open("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", O_RDONLY) = 45
7986 open("/home/ikzelf/.openoffice.org/3/user/psprint/pspfontcache", O_RDONLY) = 47
7986 open("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf", O_RDONLY) = 47
7986 open("/usr/share/fonts/type1/gsfonts/n021003l.pfb", O_RDONLY) = 58
7986 open("/usr/share/fonts/type1/gsfonts/n019003l.pfb", O_RDONLY) = 59
7986 open("/usr/share/fonts/type1/gsfonts/n019003l.afm", O_RDONLY) = 59
7986 open("/usr/share/fonts/type1/gsfonts/n019004l.pfb", O_RDONLY) = 62
7986 open("/usr/share/fonts/truetype/openoffice/opens___.ttf", O_RDONLY) = 62
7986 open("/usr/share/fonts/type1/gsfonts/n022004l.pfb", O_RDONLY) = 62
7986 open("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans-Bold.ttf", O_RDONLY) = 62
Interessante filenaam-extensies: .ttf voor TrueType font, .pfb voor PostScriptFont-binary, .afm voor AdobeFontMetrics
Vele jaren geleden heb ik eens als vingeroefening een compleet Adobe Type 1 font gebouwd, vanaf scratch. Ik had wel het allereenvoudigste gekozen: het KIX font. Dat is het alfabet van de barcodes waarmee de adres-sorteermachines van de NL posterijen werken. Je ziet het vaak op brieven onder de plaatsnaam staan. Geen ronde contouren, geen "hints" enz, alleen rechthoekjes in verschillende maten. Sindsdien weet ik nog de weg in .pfb en .pfa (PostScriptFont-ASCII) bestanden. .pfb-bestanden zijn lastig hanteerbaar: een mix van tekstregels en stukken binary. Commando's zoals vi, grep en less kunnen er niet mee omgaan, maar het kan wel zo:
strings /usr/share/fonts/type1/gsfonts/n019003l.pfb | grep FontName
/FontName /NimbusSanL-Regu def
Bingo! Dit is een van de fonts waar het om gaat; ondanks de absurde filenaam hebben we 'm gevonden. We kijken nu wat verder in die file met 'strings':
%!PS-AdobeFont-1.0: NimbusSanL-Regu 1.06
%%Title: NimbusSanL-Regu
%Version: 1.06
%%CreationDate: Thu Aug 2 14:35:58 2007
%%Creator: frob
%Copyright: Copyright (URW)++,Copyright 1999 by (URW)++ Design &
%Copyright: Development; Cyrillic glyphs added by Valek Filippov (C)
%Copyright: 2001-2005
% Generated by FontForge 20070723 (http://fontforge.sf.net/)
%%EndComments
Dan zoeken we op een van de andere hosts naar een file met dezelfde naam:
locate n019003l.pfb
.....
/usr/share/fonts/default/Type1/n019003l.pfb
Andere directory-padnaam, maar dat zal wel OK zijn. En we kijken met 'strings' ook in die file:
!PS-AdobeFont-1.0: NimbusSanL-Regu 1.06
%%Title: NimbusSanL-Regu
%%CreationDate: Tue Dec 31 16:51:01 2002
%%Creator: frob
%%DocumentSuppliedResources: font NimbusSanL-Regu
% Copyright (URW)++,Copyright 1999 by (URW)++ Design & Development; Cyri
% Generated by PfaEdit 1.0 (http://pfaedit.sf.net/)
%%EndComments
Wel wel... een duidelijk verschil. Toch ging het hier om twee actuele Linux-distributies, alleen van verschillend "merk"....
Om nu de rest van een lang verhaal kort te maken: we hebben op onze verschillende Linux'en geïnventariseerd welke versies van deze fonts voorkwamen. Dat bleek beperkt te blijven tot deze twee, hoewel de directorynaam bijna overal verschillend was. We hebben een directory met de 'CreationDate 2007' versies gepakt, en alle files daaruit botweg gekopieerd naar de Linux'en die de 'CreationDate 2002'-versies bevatten. Probleem opgelost..
Op onze checklist bij ingebruikname van "weer een nieuwe Linux"-distributie staat nu als vast punt erbij: font-files gelijktrekken.
Nabedrukt briefpapier
Geplaatst door gait op 2010-03-23 14:43:06 | Permanente link | Categorie: Tips and Tricks | Reacties: 0
Bij AT Computing zijn we overstapt van compleet voorbedrukt briefpapier naar papier met slechts het logo voorbedrukt. Daarvoor gebruiken we een OpenOffice.org-sjabloon met macro's: Voor een nieuw document kun je, uitgaande van zo'n sjabloon, kiezen uit drie briefhoofden: voorzien van de gegevens van een van de werkmaatschappijen ('oplossers' of 'opleiders') dan wel een algemene versie zonder bankrekeningnummers e.d.
Dat biedt geen soelaas voor bestaande documenten die voorheen op voorbedrukt briefpapier werden afgedrukt. En die zijn er: er wordt bijvoorbeeld gefactureerd vanuit een werkblad (spreadsheet). Daarvoor werd aanvankelijk eerst naar behoefte papier met briefhoofd afgedrukt waar in een tweede printgang de facturen op afgedrukt werden. Dat is omslachtig, alleen al omdat je er nog steeds een voorraad op na moet houden. Dat kan beter.
Filter
Om te beginnen wilde ik de vaste tekst van het briefhoofd electronisch
samenvoegen met de variabele factuurtekst. Dat was niet moeilijk,
hooguit wat omslachtig: beide componenten omzetten naar PDF, dan
deze met de PDF-toolkit (pdftk) samenvoegen en weer terug naar
PostScript vertalen. Dat trucje is zo gescript en daar hou je een
postscript-naar-postscript filter aan over waarbij elke pagina voorzien
is van het briefpapier.
Specifieke OO.o-printer
Het trucje is bruikaar bij een homebrew printer in OpenOffice.org. Als CUPS in gebruik is bij OpenOffice.org dan kun je met spadmin, het printerbeheerprogramma, normaal gesproken geen nieuwe printers maken. Maar je kunt nog wel zoals dat heet een 'PDF-conversieprogramma aansluiten'. Hierbij heb je zelf het hele traject van OO.o naar printer in de hand: Je stuurt dan het PostScript dat uit OO.o komt eerst door het filter waarna je de uitvoer naar de printer stuurt. Dan werkt het voor OO.o-gebruikers.
Implementatie in CUPS
Het mooiste zou zijn: de truc als optie bij het afdrukken beschikbaar
maken. Dat doe je door het traject van een printjob in CUPS aan te
passen. Een printtraject bestaat uit een pijplijn van filters die gekozen
worden op basis van het MIME-types van de invoer en het MIME-type dat
geschikt is voor een printer: Voor een overgang van het ene naar het
andere MIME-type worden filters gebruikt. Voor zo'n filter ligt vast dat
CUPS de opties als het vijfde argumenten doorgeeft. Mijn filter kijkt
of het bekende opties aantreft (bijvoorbeeld atc-printedlogo') en doet
dan het bijbehorende kunstje, anders filtert het ongewijzigd
(/bin/cat).
Om het eigen printfilter in het filterpad van CUPS op te nemen heb
ik een MIME-type toegevoegd aan de CUPS-configuratie door een nieuw
types-bestand te maken volgens mime.types(1). In het nieuwe bestand
/etc/cups/atc-letterhead.types staat
application/atc-letterhead
Vervolgens heb ik in het bestaande bestand /etc/cups/mime.convs een regel
vervangen door twee nieuwe regels:
# invoertype uitvoertype kosten filter
application/postscript application/vnd.cups-postscript 66 pstops
is vervangen door
application/postscript application/atc-letterhead 66 atc-letterhead2ps
application/atc-letterhead application/vnd.cups-postscript 66 pstops
Op die kosten kom ik later nog terug. Deze constructie zorgt ervoor dat
mijn filter in het filtertraject opgenomen wordt. Het genoemde filter
wordt gevonden als /etc/lib/cups/filter/atc-letterhead2ps en dat filter
weet zelf waar de PDF-bestanden met briefhoofden staan.
De facturen worden rechtstreeks vanuit OO.o afgedrukt op de printer 'Oplossersfactuur inclusief logo op briefpapier'. Hierachter gaat het volgende commando schuil:
lp -dnetlp -o atc-oplossersfactuur
Het filter wordt altijd gebruikt. Het speelt doorgeefluik (cat), tenzij
er een een optie voorbij komt die herkend wordt.
Printer instances
Ik heb meteen iets gemaakt waardoor je alle invoer kunt voorzien van een afgedrukt logo:
lp -dnetlp -oatc-printedlogo
Dat kan mooier als je in /etc/cups/lpoptions (of in je eigen
~/.cups/lpoptions) een zogenaamde printer-instance opvoert:
Dest netlp/printedlogo PageSize=A4 Duplex=DuplexNoTumble atc-printedlogo
Hierbij is netlp de printer en printedlogo de printer-instance. Let
wel: lpoptions wordt slechts door CUPS-clients geraadpleegd.
Zoals je ziet kun je zo ook andere opties vastleggen, die instellingen krijg je kado als je de instance gebruikt:
lp -dnetlp/printedlogo
Helaas zijn printer instances binnen CUPS nog niet helemaal goed
voorelkaar, want in de uitvoer van lptstat -t komen de
instances voorbij alsof het zelfstandige print queues zijn. OO.o
laat ze wel allemaal zien, maar ze werken allemaal gelijk omdat
OO.o niet naar lpoptions kijkt. Daarvoor is hier in de vorm van
een PDF-conversieprogramma een workaround gepresenteerd. Acrobat
Reader geeft je wel een lijst met printernamen maar zet daar niet de
instance-aanduiding achter ...
RPM
Ik heb van mijn oplossing een RPM gemaakt. Maar: ik had een bestaand
bestand aangepast (mime.convs), dat bestand zit tevens in de CUPS-RPM,
en als je een RPM met hetzelfde bestand wit installeren heb je
een conflict. Dan kijk je nogmaals in de manpages mime.convs(1) en
mime.types(1) en lees je het advies om geen bestaande files aan te passen
doch lokale aanpassingen in lokale bestanden op te slaan. Ik had al een
eigen .types-bestand gemaakt. Maar ja, hoe zet je dan dat filtertraject
naar je hand?
Toen had ik een droom over de kosten die in de derde kolom van een
.convs-bestand staan: hier staan de relatieve kosten van het filter en op
basis daarvan kiest CUPS altijd de goedkoopste route. Dat was de crux:
ik heb mijn alternatieve filterregels tegen lagere kosten in het nieuwe
bestand /etc/cups/atc-letterhead.convs gezet:
application/postscript application/atc-letterhead 22 atc-letterhead2ps
application/atc-letterhead application/vnd.cups-postscript 22 pstops
Dit is de alternatieve manier om mijn filter in het filtertraject op te nemen.
Bingo!
BTRFS
Geplaatst door miekg op 2010-03-18 15:37:01 | Permanente link | Categorie: Infrastructuur | Reacties: 0
In het kader van redundantie gebruikt AT Computing altijd meerdere disks in haar servers. Als je zoiets met Linux dan opzet kom je al gauw uit op LVM en/of RAID. Nu heeft SUN een paar jaar geleden ZFS gepresenteerd. ZFS is zo geavanceerd dat alle toen bestaande file systemen meteen verouderd waren. Helaas is de licentie van ZFS dusdanig (CDDL) dat de ZFS code niet in de Linux kernel mag worden opgenomen. Gelukkig is Chris Mason (van Oracle — de nieuwe eigenaar van SUN), begonnen aan een file systeem dat nog beter dan ZFS moet worden en wel de juiste licentie (GPLv2) heeft om in Linux te worden opgenomen. Dit nieuwe file systeem heet: BTRFS. Je spreekt dat uit als 'the Better File System', maar het staat voor 'B-TRee FS'.
BTRFS:
- heeft RAID ingebouwd (natuurlijk gestolen van ZFS;
- verzorgt checksumming tussen verschillende devices; dus als een disk stuk aan het gaan is, zal BTRFS dat merken;
- heeft snapshotting, een snapshot is een momentopname van een bestandssysteem; vergelijkbaar met snapshots in LVM (maar dan zonder het performance verlies van LVM);
- heeft subvolumes, vergelijkbaar met logical volumes in LVM;
- bevindt zich nog in een alpha/béta stadium.
Om eens te kijken wat BTRFS nu precies kan, hebben we even gespeeld met de nieuwe Ubuntu 10.04 Alpha-3, zodat we in ieder geval de nieuwste versie van BTRFS hebben.
Linux kan met grub2 nog niet booten van een BTRFS volume. Om dit
euvel te verhelpen booten we nog gewoon van een RAID1 partitie met
ext4. Er
blijven uiteindelijk twee partities over voor BTRFS: /dev/sda4 en
/dev/sdb4. Deze willen we inrichten als RAID0. BTRFS ondersteunt
ook RAID1 en RAID10 en aan RAID5 wordt gewerkt. Voor het verdere verhaal
maak de RAID versie niet uit.
Ingebruikname
We beginnen met het aanmaken van een BTRFS filesysteem op de twee partities: (naar de 'WARNING!' regels moet je nog even niet kijken)
mkfs.btrfs /dev/sda4 /dev/sdb4
WARNING! - Btrfs Btrfs v0.19 IS EXPERIMENTAL
WARNING! - see http://btrfs.wiki.kernel.org before using
adding device /dev/sdb4 id 2
fs created label (null) on /dev/sda4
nodesize 4096 leafsize 4096 sectorsize 4096 size 451.46GB
Btrfs Btrfs v0.19
En hier valt dus al gelijk op dat je (anders dan de meeste mkfs.*
tools) twee (of nog meer) device namen kunt opgeven. Na deze
vrij vlotte operatie kunnen we onze fonkelnieuwe ruimte gaan mounten:
# mount -t btrfs /dev/sda4 /mnt
We hadden hier ook /dev/sdb4 mogen gebruiken, BTRFS weet dat deze
devices bij elkaar horen.
Nu kunnen we er files naar toe kopiëren en een beetje rondneuzen. Alles werkt zoals je verwacht dat het zou moeten werken. Er vallen geen bitjes op de grond.
Productie
Nu willen we natuurlijk het filesysteem gaan gebruiken vanaf
het booten van de machine. Daartoe zetten we het in de fstab
/dev/sda4 /mnt btrfs defaults 0 0
En rebooten we. En toen was het stuk. Het blijkt dat BTRFS het filesysteem
eerst even wil onderzoeken en het pas daarna gaat mounten (dit zal
in latere versies worden verbeterd). Je moet daarvoor btrfsctl
gebruiken:
# btrfsctl -A /dev/sda4
mount /mnt
mount: wrong fs type, bad option, bad superblock on /dev/sda4,
...
# btrfsctl -A /dev/sdb4
mount /mnt # nu is het wel succesvol
Allebei de partities van ons BTRFS volume moeten zo onderhanden worden genomen. De standaard Linux boot scripts snappen dit nog niet en dus wordt het zo wel erg moeilijk om productie te gaan draaien met BTRFS.
Performance
We hebben we paar hele kleine testjes gedaan op de (oude) test hardware:
# dd if=/dev/zero bs=10240 count=102400 of=LARGE
102400+0 records in
102400+0 records out
1048576000 bytes (1.0 GB) copied, 6.69901 s, 157 MB/s
# dd if=/dev/zero bs=10240 count=102400 of=LARGE
102400+0 records in
102400+0 records out
1048576000 bytes (1.0 GB) copied, 6.46881 s, 162 MB/s
# time rm LARGE # en weer weggooien
real 0m0.574s
Dat valt in de categorie bruikbaar. De insteek van de ontwikkelaars van BTRFS is: first make it work, then make it fast.
Subvolumes
Zoals gezegd zijn subvolumes vergelijkbaar met logical volumes van LVM. Je knipt eigenlijk een stuk ruimte uit je BTRFS volume en kunt dat apart gaan gebruiken. De grootte van een subvolume is net zo groot als het originele BTRFS volume waar die uit komt. Je kunt wel een soort quota zetten op een subvolume en zo de grootte beperken; dat hebben we hier niet getest.
Laten we een subvolume maken met de naam home, we gebruiken hiervoor
weer btrfsctl:
# btrfsctl -S home /mnt
operation complete
Btrfs Btrfs v0.19
Na deze operatie is er dus een subvolume home gemaakt dat net zo groot is
als het originele BTRFS volume.
En nu gebruiken:
# mount -t btrfs -o subvol=home /dev/sda4 /mnt/home
Subvolumes zijn ook de basis voor snapshotting. Een snapshot
is te maken door btrfsctl -s (kleine 's') te gebruiken. Ook die snapshots kun
je mounten alsof het een normaal volume is.
Standaard features
Zaken die we ondertussen gewend zijn van andere file systemen, zoals
bijveerbeeld online resizing worden gewoon ondersteund, zie voor de
details btrfsctl(8) en de -r vlag.
Conclusie
Op een single disk kun je best al BTRFS uitproberen. Het schijnt dat
Linus Torvalds al een half jaar geleden overgestapt is op BTRFS.
Wil je de geavanceerde features uitproberen (meerdere
disks, RAID, CRC-checking), dan kom je toch in een béta-wereld van zaken die wel werken,
maar nog niet lekker in de rest van het systeem zitten ingebakken: een
btrfsctl voordat je kunt mounten, subvolumes die niet meteen zichtbaar
zijn, etc.
Ik kijk reikhalzend uit naar een 1.0 release van BTRFS, maar vooralsnog blijf ik op ext4 + RAIDN zitten. Of Oracle moet ZFS opnieuw uitbrengen, maar dan met een GPLv2 licentie (maar die kans is heel klein).
Kijk voor meer informatie op de Wikipedia pagina over BTRFS, of de weinig up-to-date wiki pagina van het project zelf.
