Latence des process et kernel timing

From Deimos.fr / Bloc Notes Informatique
Jump to: navigation, search
Linux

Software version Kernel 2.6.32+
Operating System Red Hat 6.3
Debian 7
Website Kernel Website
Last Update 05/01/2014
Others

1 Les horloges

Il existe plusieurs horloges qui permettent d'obtenir ou de manipuler des opérations de temps :

  • RTC (Real Time Clock) : c'est la pile du BIOS qui permet de maintenir la date et l'heure sur une machine lorsque celle ci est éteint. Vous pouvez récupérer des informations sur celle ici dans le fichier /proc/driver/rtc.
  • TSC (Time Stamp Counter) : c'est un compteur qui est mis à la même fréquence que celle du CPU, même si celui ci oscille. Le kernel utilise le TSC avec le RTC pour calculer la date et l'heure
  • PIC (Programmable Interrupt Counter) : aussi connu sous le nom de PIT (Programmable Interval Timer) qui permet d'envoyer des interruptions au kernel après un certain temps passé. Il est généralement utilisé pour les process schedule.
  • APIC (Advanced Programmable Interrupt Controller) : Il se cale également sur l'horloge CPU et permet de tracer les process en cours d'exécution et envoie les interruptions locales à ce processeur.

Sur un kernel 2.6, la fréquence du PIC est de 1MHz ou d'1 tick/ms (appelé aussi jiffy). Cet interval peut être ajusté lors de la compilation kernel ou bien en paramètre de boot (pour certaines distributions). Une valeur de tick plus courte donnera des temps de résolution meilleurs, cependant, les applications risquent de tourner de façon légèrement plus ralenti.

Le paramètre de boot est :

Configuration File /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet tick_divider=<value>"

Les valeurs intéressantes sont :

  • 2 = 500 Hz
  • 4 = 250 Hz
  • 5 = 200 Hz
  • 8 = 125 Hz
  • 10 = 100 Hz

L'avantage est la réduction d'Overhead CPU, mais le scheduler est moins fair avec les processus interactifs.

2 Gérer la vitesse CPU

Il existe sous Red Hat un outil permettant de controler la vitesse de l'horloge CPU. Pour cela il faut installer le démon "cpuspeed" et le configurer dans /etc/sysconfig/cpuspeed :

Command /etc/sysconfig/cpuspeed
# /etc/sysconfig/cpuspeed
#
# This configuration file controls the behavior of both the
# cpuspeed daemon and various cpufreq modules.
# For the vast majority of users, there shouldn't be any need to
# alter the contents of this file at all. By and large, frequency
# scaling should Just Work(tm) with the defaults.
 
### DRIVER ###
# Your CPUFreq driver module
# Note that many drivers are now built-in, rather than built as modules,
# so its usually best not to specify one.
# default value: empty (try to auto-detect/use built-in)
DRIVER=
 
### GOVERNOR ###
# Which scaling governor to use
# Details on scaling governors for your cpu(s) can be found in
# cpu-freq/governors.txt, part of the kernel-doc package
# NOTES:
# - The GOVERNOR parameter is only valid on centrino, powernow-k8 (amd64)
#   and acpi-cpufreq platforms, other platforms that support frequency
#   scaling always use the 'userspace' governor.
# - Using the 'userspace' governor will trigger the cpuspeed daemon to run,
#   which provides said user-space frequency scaling.
# default value: empty (defaults to ondemand on centrino, powernow-k8,
#                       and acpi-cpufreq systems, userspace on others)
GOVERNOR=
 
### FREQUENCIES ###
# NOTE: valid max/min frequencies for your cpu(s) can be found in
# /sys/devices/system/cpu/cpu*/cpufreq/scaling_available_frequencies
# on systems that support frequency scaling (though only after the
# appropriate drivers have been loaded via the cpuspeed initscript).
# maximum speed to scale up to
# default value: empty (use cpu reported maximum)
MAX_SPEED=
# minimum speed to scale down to
# default value: empty (use cpu reported minimum)
MIN_SPEED=
 
### SCALING THRESHOLDS ###
# Busy percentage threshold over which to scale up to max frequency
# default value: empty (use governor default)
UP_THRESHOLD=
# Busy percentage threshold under which to scale frequency down
# default value: empty (use governor default)
DOWN_THRESHOLD=
 
### NICE PROCESS HANDLING ###
# Let background (nice) processes speed up the cpu
# default value: 0 (background process usage can speed up cpu)
# alternate value: 1 (background processes will be ignored)
IGNORE_NICE=0
 
 
#####################################################
########## HISTORICAL CPUSPEED CONFIG BITS ##########
#####################################################
VMAJOR=1
VMINOR=1
 
# Add your favorite options here
#OPTS="$OPTS -s 0 -i 10 -r"
 
# uncomment and modify this to check the state of the AC adapter
#OPTS="$OPTS -a /proc/acpi/ac_adapter/*/state"
 
# uncomment and modify this to check the system temperature
#OPTS="$OPTS -t /proc/acpi/thermal_zone/*/temperature 75"

Vous pouvez récupérer les informations actuelles comme ceci :

Command cpuspeed
cpuspeed ---help 2>&1 | more

Il est possible de voir les valeurs assignables possible :

Command cat
cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_frequencies 
3166000 2667000 2333000 2000000

Donc 3.16Ghz, 2.66Ghz, 2.33Ghz ou 2Ghz.

Et enfin le gouvernor permet de voir l'algorithme utilisé. Par exemple ici c'est le "on demand", ce qui modifie a la volée la vitesse du processeur en fonction de la demande :

Command cat
> cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors   
ondemand performance

Si vous souhaitez les meilleures performances, désactivez ce démon. L'inconvénient est biensure la consommation électrique (pensez à l'environnement).
Sachez que si vous avez besoin de très faibles latences, il est fortement conseillé de désactiver ce démon.

3 Le balancing IRQ

Assurez vous que ces informations sont bien compilées dans le kernel :

Command grep
> grep -e VOLUNTARY -e BKL /boot/config-2.6.32-279.2.1.el6.x86_64 | grep -v '#'
CONFIG_PREEMPT_VOLUNTARY=y
CONFIG_BKL=y

Ces options sont faites pour que le kernel puisse préempter et planifier certains process. Le gain se fera sentir au niveau de la latence (surtout réseaux). Par exemple, le kernel peut gérer des opérations IO disque et recevoir en même temps des interruptions de la part de la carte réseau. Le handler qui fait les IO disques peut être préempté en faveur de l'interruption de la carte réseau ce qui améliorerait la latence réseau.

Il est néanmoins possible de désactiver l'IRQ balancing via un paramètre de boot :

Configuration File /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet noapic"

Si les IRQ sont inégalement réparties sur le CPU, le résultat peut être un incohérence des performances lorsque les gestionnaires d'interruption feront préempter les processus qui sont sur le CPU.

Pour voir les interruptions sur les interruptions :

Command cat
> cat /proc/interrupts 
           CPU0       CPU1       
  0:        121         38   IO-APIC-edge      timer
  1:          3          0   IO-APIC-edge      i8042
  7:          0          0   IO-APIC-edge      parport0
  8:          1          0   IO-APIC-edge      rtc0
  9:          0          0   IO-APIC-fasteoi   acpi
 12:          2          2   IO-APIC-edge      i8042
 16:       9138       9221   IO-APIC-fasteoi   uhci_hcd:usb2
 17:     119477     120478   IO-APIC-fasteoi   uhci_hcd:usb4, uhci_hcd:usb7
 18:     235767     237579   IO-APIC-fasteoi   ata_generic, ata_piix, ata_piix, uhci_hcd:usb8
 22:     627101     627432   IO-APIC-fasteoi   ehci_hcd:usb1, uhci_hcd:usb5
 23:          0          0   IO-APIC-fasteoi   ehci_hcd:usb3, uhci_hcd:usb6
 40:    4752698          0  HPET_MSI-edge      hpet2
 41:          0    4481502  HPET_MSI-edge      hpet3
 47:     704766     717489   PCI-MSI-edge      eth0
 48:        722        764   PCI-MSI-edge      snd_hda_intel
 49:    1462373    1492905   PCI-MSI-edge      i915
NMI:       3001       2977   Non-maskable interrupts
LOC:        754        731   Local timer interrupts
SPU:          0          0   Spurious interrupts
PMI:       3001       2977   Performance monitoring interrupts
IWI:          0          0   IRQ work interrupts
RES:    9186852    9208409   Rescheduling interrupts
CAL:        607        596   Function call interrupts
TLB:     447954     362994   TLB shootdowns
TRM:          0          0   Thermal event interrupts
THR:          0          0   Threshold APIC interrupts
MCE:          0          0   Machine check exceptions
MCP:         82         82   Machine check polls
ERR:          0
MIS:          0

Les interceptions permettent d'exploiter l'affinité des caches pour CPU et l'égalisation du nombre de visites CPU. Pour donner une affinité IRQ à un CPU afin d'améliorer les performances en exploitant au mieux l'affinité du cache, il faut spécifier le bitmap d'un core en hexadécimal. Par exemple :

Command echo
echo <cpu_mask> > /proc/irq/<interrupt_number>/smp_affinity

Cela permettra de placer cet IRQ en tête de l'active queue et de préserver certains CPU d'être utiliser pour les assignations IRQ. Il est possible de configurer sur Red Hat de façon permanente dans /etc/sysconfig/irqbalance. Pour ceux qui le souhaites, il est possible de désactiver l'IRQ balancing :

Command chkconfig
chkconfig irqbalance off

Pour plus d'infos sur les affinités IRQ : http://kernel.org/doc/Documentation/IRQ-affinity.txt[1]

4 Activer/Désactiver des CPU à chaud

Il est possible d'activer ou désactiver des CPU à chaud ! C'est d'ailleurs très facile. Vérifiez dans un premier temps que votre kernel permet ce genre de choses :

Command /boot/config-`uname -r`
CONFIG_HOTPLUG
CONFIG_SMP
CONFIG_HOTPLUG_CPU
CONFIG_ACPI_HOTPLUG_CPU

Récupérez la liste des processeurs :

Command grep
> grep processor /proc/cpuinfo 
processor	: 0
processor	: 1

Vérifiez ensuite vos interruptions :

Command cat
> cat /proc/interrupts 
           CPU0       CPU1       
  0:        109         36   IO-APIC-edge      timer
  1:          3          0   IO-APIC-edge      i8042
  7:          0          0   IO-APIC-edge      parport0
  8:          1          0   IO-APIC-edge      rtc0
  9:          0          0   IO-APIC-fasteoi   acpi
 12:          1          3   IO-APIC-edge      i8042
 16:      13500      13486   IO-APIC-fasteoi   uhci_hcd:usb3
 17:     122633     122322   IO-APIC-fasteoi   uhci_hcd:usb4, uhci_hcd:usb7
 18:     157011     157338   IO-APIC-fasteoi   ata_piix, ata_piix, uhci_hcd:usb8, ata_generic
 22:     365980     365602   IO-APIC-fasteoi   ehci_hcd:usb1, uhci_hcd:usb5
 23:          0          0   IO-APIC-fasteoi   ehci_hcd:usb2, uhci_hcd:usb6
 40:    3995517          0  HPET_MSI-edge      hpet2
 41:          0    4003499  HPET_MSI-edge      hpet3
 47:     188227     196024   PCI-MSI-edge      eth0
 48:        472        468   PCI-MSI-edge      snd_hda_intel
 49:    1079730    1075353   PCI-MSI-edge      i915
NMI:       2169       2188   Non-maskable interrupts
LOC:        756        733   Local timer interrupts
SPU:          0          0   Spurious interrupts
PMI:       2169       2188   Performance monitoring interrupts
IWI:          0          0   IRQ work interrupts
RES:    7945496    7982861   Rescheduling interrupts
CAL:        586        482   Function call interrupts
TLB:     397248     414104   TLB shootdowns
TRM:          0          0   Thermal event interrupts
THR:          0          0   Threshold APIC interrupts
MCE:          0          0   Machine check exceptions
MCP:         68         68   Machine check polls
ERR:          0
MIS:          0

Pour désactiver le CPU 1 :

Command echo
echo 0 > /sys/devices/system/cpu/cpu1/online

On peut voir qu'il n'y a plus que le CPU 0 :

Command cat
> cat /proc/interrupts                        
           CPU0       
  0:        109   IO-APIC-edge      timer
  1:          3   IO-APIC-edge      i8042
  7:          0   IO-APIC-edge      parport0
  8:          1   IO-APIC-edge      rtc0
  9:          0   IO-APIC-fasteoi   acpi
 12:          1   IO-APIC-edge      i8042
 16:      13606   IO-APIC-fasteoi   uhci_hcd:usb3
 17:     123361   IO-APIC-fasteoi   uhci_hcd:usb4, uhci_hcd:usb7
 18:     157302   IO-APIC-fasteoi   ata_piix, ata_piix, uhci_hcd:usb8, ata_generic
 22:     366042   IO-APIC-fasteoi   ehci_hcd:usb1, uhci_hcd:usb5
 23:          0   IO-APIC-fasteoi   ehci_hcd:usb2, uhci_hcd:usb6
 40:    4010597  HPET_MSI-edge      hpet2
 41:          1  HPET_MSI-edge    
 47:     188715   PCI-MSI-edge      eth0
 48:        472   PCI-MSI-edge      snd_hda_intel
 49:    1085415   PCI-MSI-edge      i915
NMI:       2177   Non-maskable interrupts
LOC:        756   Local timer interrupts
SPU:          0   Spurious interrupts
PMI:       2177   Performance monitoring interrupts
IWI:          0   IRQ work interrupts
RES:    7981178   Rescheduling interrupts
CAL:        587   Function call interrupts
TLB:     397336   TLB shootdowns
TRM:          0   Thermal event interrupts
THR:          0   Threshold APIC interrupts
MCE:          0   Machine check exceptions
MCP:         68   Machine check polls
ERR:          0
MIS:          0

On réactive ensuite le CPU 1 :

Command echo
echo 1 > /sys/devices/system/cpu/cpu1/online

Et tout le monde se replace correctement :-). Il faut savoir que certains CPU ne peuvent pas être désactivé comme le CPU de boot.

5 Egaliser l'utilisation des CPUs

Chaque core a sa propre run queue. Pour les processeurs HyperThreadés, le processeur logique utilise la même run queue que le core physique. Par défaut, il existe une certaine affinité et les tâches qui se produisent sur un CPU reviennent dessus plus ou moins automatiquement si d'autres associées se trouvaient à aller voir un autre CPU. Sachant que chaque CPU a son propre cache, c'est mieux comme cela. Cependant, si un core est plus chargé qu'un autre, le scheduleur regarde les run queues toutes les 100ms (ou 1ms sur le core ne fait rien) et décide de rééquilibrer la charge . Le problème se situe dans le cas ou ce système de balancing se fait trop souvent, on peut se prendre de la latence pour éviter des caches miss (tout dépends des applicatifs) ! Il faut alors choisir ce que l'on souhaites le plus. Pour voir la liste des programmes ainsi que leur core associés :

Command ps
> ps axo comm,psr
COMMAND         PSR
init              1
kthreadd          0
ksoftirqd/0       0
migration/0       0
watchdog/0        0
migration/1       1
ksoftirqd/1       1
watchdog/1        1
cpuset            0
khelper           1
kdevtmpfs         1
netns             1
sync_supers       1
bdi-default       0
kintegrityd       0
kblockd           1
khungtaskd        1
kswapd0           0

Vous pouvez voir également un processus se balader d'un core à un autre :

Command watch
watch -n2 'ps axo comm,pid,psr | grep <process>'

5.1 taskset

Si l'on souhaites assigner à certains process des CPU en particulier, c'est possible ! La première étape est de connaitre le bitmap CPU. Pour vous donner une idée de comment les récupérer :

Command
> awk '/processor/{printf("CPU %s address : 0x0000000%s\n"), $3, $3}' /proc/cpuinfo ; echo 'All CPU       : xXFFFFFFFF'
CPU 0 address : 0x00000000
CPU 1 address : 0x00000001
CPU 2 address : 0x00000002
CPU 3 address : 0x00000003
All CPU       : xXFFFFFFFF

Ensuite nous utiliserons la commande taskset pour assigner à un CPU en particulier un PID :

Command taskset
taskset -p 0x00000001 <PID>

Il faut savoir que les processeurs Numa ont la mémoire RAM directement mappées avec les CPU pour augmenter les performances. Cela ne change en rien que les autres processeurs peuvent utiliser de la mémoire qui ne leur est pas associée. Voici un petit aperçu de Numa :

Numa.png[2]

Vous pouvez également spécifier les paramètres au niveau du grub pour isoler des CPU (isolcpus) :

Configuration File /etc/grub.conf
# grub.conf generated by anaconda
#
# Note that you do not have to rerun grub after making changes to this file
# NOTICE:  You have a /boot partition.  This means that
#          all kernel and initrd paths are relative to /boot/, eg.
#          root (hd0,0)
#          kernel /vmlinuz-version ro root=/dev/mapper/vgos-root
#          initrd /initrd-[generic-]version.img
#boot=/dev/sda
default=0
timeout=5
splashimage=(hd0,0)/grub/splash.xpm.gz
hiddenmenu
title Red Hat Enterprise Linux Server (2.6.32-279.2.1.el6.x86_64)
	root (hd0,0)
	kernel /vmlinuz-2.6.32-279.2.1.el6.x86_64 ro root=/dev/mapper/vgos-root rd_NO_LUKS  KEYBOARDTYPE=pc KEYTABLE=fr LANG=en_US.UTF-8 rd_LVM_LV=vgos/root rd_NO_MD rd_LVM_LV=vgos/swap SYSFONT=latarcyrheb-sun16 crashkernel=128M biosdevname=0 rd_NO_DM isolcpus=0	initrd /initramfs-2.6.32-279.2.1.el6.x86_64.img

Il est maintenant possible de faire du CPU pinning sur ce CPU. On aura donc une run queue plus petite et des temps de réponses améliorés pour les taches assignées à ce CPU.

Pour plus d'informations : http://kernel.org/doc/Documentation/kernel-parameters.txt[3]

5.2 cpuset/cgroup

cpuset est une version plus avancée de taskset qui permet d'avoir une méthode plus élégante, flexible et évolutive pour controler les runqueues ainsi que la latence sur les taches. Un cpuset est un groupe de CPU (scheduler domain/cgroups) sur lequel nous allons pouvoir y balanm cer des taches :

Cpuset.gif[4]

Pour s'assurer que ces fonctionnalités sont bien présentes dans le kernel :

Command grep
> grep -i cpuset /proc/filesystems /boot/config-`uname -r`    
/proc/filesystems:nodev	cpuset
/boot/config-3.2.0-3-amd64:CONFIG_CPUSETS=y
/boot/config-3.2.0-3-amd64:CONFIG_PROC_PID_CPUSET=y

L'implémentation de cpuset dans le kernel est toute petite et n'a pas d'impacts sur le scheduler de process. Ca utilise un nouveau VFS qui n'introduit pas les nouveaux appels systèmes. Ce VFS cpuset peut être monté n'importe ou sur le système. Nous allons par exemple monter ceci dans /mnt/cpuserts. Il suffit de créer des dossier pour faire des assignations à d'autres CPU. Un CPU peut appartenir à plusieurs cpusets.

5.2.1 Prérequis

Mettre le montage des cgroups au boot :

Configuration File /etc/fstab
cgroup  /sys/fs/cgroup  cgroup  defaults  0   0

Afin d'avoir toutes les options activés, il faut également modifier les options de Grub :

Configuration File /etc/default/grub
GRUB_CMDLINE_LINUX_DEFAULT="quiet cgroup_enable=memory swapaccount=1"

Puis mettre à jour Grub :

Command update-grub
update-grub

Rebootez ensuite.

5.2.2 Création

Pour créer un cgroup c'est très simple :

Command mkdir
mkdir /sys/fs/cgroup/mycgroup1

5.2.3 Assigner un cpu et sa mémoire à un cgroup

Nous allons assigner un CPU et sa mémoire à notre nouveau cgroup (ici, le CPU 0) :

Command echo
echo 0 > /sys/fs/cgroup/mycgroup1/cpuset.cpus
echo 0 > /sys/fs/cgroup/mycgroup1/cpuset.mems

Vous pouvez envoyer plusieurs processeurs en les séparant par des virgules, le tout encadré par des quotes.

5.2.4 Dédier un CPU à un cgroup

Pour dédier un CPU uniquement à certains processus :

Command echo
echo 0 > /sys/fs/cgroup/mycgroup1/cpuset.cpus

5.2.5 Ajouter un processus à un cgroup

Pour ajouter un processus, c'est très simple, il suffit d'envoyer son PID dans le fichier tasks :

Command echo
echo <PID> > /sys/fs/cgroup/mycgroup1/cpuset.tasks

Ou si vous avez plusieurs processus du même nom :

Command
for pid in $(pidof apache2); do
    echo $pid > /sys/fs/cgroup/mycgroup1/cpuset.tasks
done

5.2.6 Détacher un processus d'un cgroup

Il est possible de faire un détachement en rattachant un processus à un autre cgroup ou celui de la machine :

Command echo
echo <PID> > /sys/fs/cgroup/tasks

5.2.7 Supprimer un cgroup

Pour supprimer un cgroup c'est très simple, supprimez simplement le dossier en question :

Command rm
rm -Rf /sys/fs/cgroup/mycgroup1/cpuset.

5.2.8 Monitorer la pression sur un cpuset

Il est possible de monitorer la pression sur les cpusets en activant comme ceci :

Command echo
echo 1 > /sys/fs/cgroup/memory_pressure_enabled

Avec cette option, le kernel commencera à traquer l'utilisation mémoire des cpusets. Vous pourrez ensuite récupérer les statistiques dans chaque cgroup :

Command
cat
cat /sys/fs/cgroup/<cgroup>/memory_pressure

Vous retrouverez une moyenne d'exécution ou la vitesse a laquelle les pages frames se libères.

5.2.9 Divers

Voici divers astuces :

  • Pour connaitre a quel cgroup le PID est attaché :
Command cat
cat /proc/<pid>/cpuset

  • Pour savoir a quelle ressource un PID peut être planifié :
Command
cat /proc/<pid>/status | grep allowed

  • Pour savoir si un CPU peut appartenir à plusieurs cgroups :
Command cat
> cat /sys/fs/cgroup/cpu_exclusive 
1

  • Suppression automatique du cgroup lorsque aucune tache n'est active dessus :
Command echo
echo 1 > /sys/fs/cgroup/mycgroup1/cpuset.notify_on_release

5.3 Cgroups with cgconfig

To have cgroups working with cgconfig, be sure you've enabled cgroups in your fstab. Then install the daemon :

Command aptitude
aptitude install cgroup-bin daemon

It will checks all new running process and affect them to a correct cgroup if a rule exist.

Unfortunately, it's not well packaged yet on Debian so we need to adjust some things :

Command
cd /etc/init.d
cp skeleton cgconfig
cp skeleton cgred
chmod 755 cgconfig cgred
sed -i 's/skeleton/cgconfig/' cgconfig
sed -i 's/skeleton/cgred/' cgred
update-rc.d cgconfig defaults
update-rc.d cgred defaults
cd /usr/share/doc/cgroup-bin/examples/
cp cgred.conf /etc/default/
cp cgconfig.conf cgrules.conf /etc/
gzip -d cgconfig.gz
cp cgconfig cgred /etc/init.d/
cd /etc/init.d/
sed -i 's/sysconfig/defaults/' cgred cgconfig
sed -i 's/\/etc\/rc.d\/init.d\/functions/\/lib\/init\/vars.sh/' cgred
sed -i 's/--check/--name/' cgred
sed -i 's/killproc.*/kill $(cat $pidfile)/' cgred
sed -i 's/touch "$lockfile"/test -d \/var\/lock\/subsys || mkdir \/var\/lock\/subsys\n\t&/' cgconfig
chmod 755 cgconfig cgred

You now have your configuration files and all services installed correctly. Edit the configuration file :

Configuration File /etc/cgconfig.conf
#
#  Copyright IBM Corporation. 2007
#
#  Authors:     Balbir Singh <[email protected]>
#  This program is free software; you can redistribute it and/or modify it
#  under the terms of version 2.1 of the GNU Lesser General Public License
#  as published by the Free Software Foundation.
#
#  This program is distributed in the hope that it would be useful, but
#  WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
#
group mariadb_cgroup {
    perm {
        admin {
            uid = tomcat;
        }
        task {
            uid = tomcat;
        }
    }
 
        cpuset {
                cpuset.mems = 0;
                cpuset.cpus = "1,2";
                cpuset.cpu_exclusive = 1;
        }
}

Here is an example for tomcat user, where I want to have 2 dedicated CPU. Then you need to change the cgrules config :

Configuration File /etc/cgrules.conf
tomcat          cpu           tomcat_cgroup/

This indicates that tomcat user will change cpu settings and the cgroup folder is tomcat_cgroup (/sys/fs/cgroup/tomcat_cgroup). Now restart it :

Command
/etc/init.d/cgred stop 
/etc/init.d/cgconfig stop 
umount /sys/fs/cgroup 2>/dev/null 
rmdir /sys/fs/cgroup/* /sys/fs/cgroup 2>/dev/null 
mount /sys/fs/cgroup 
/etc/init.d/cgconfig start 
/etc/init.d/cgred start

Restart your tomcat service and it will automatically be placed in the cgroup :-)

6 References

  1. ^ http://kernel.org/doc/Documentation/IRQ-affinity.txt
  2. ^ http://en.wikipedia.org/wiki/Non-Uniform_Memory_Access
  3. ^ http://kernel.org/doc/Documentation/kernel-parameters.txt
  4. ^ http://menehune.opt.wfu.edu/Kokua/SGI/007-3700-015/sgi_html/ch04.html