Overblog Suivre ce blog
Administration Créer mon blog
11 novembre 2012 7 11 /11 /novembre /2012 15:29

 

25 ans pour Sparc et 20 ans pour Solaris !! Félicitation.

Le hardware Sparc et OS Solaris ont atteint une belle maturité qui je l'espère continuera encore longtemps. En tout cas, depuis le rachat de Sun par Oracle, il semble que l'investissement sur l'architecture Sparc et sur l'OS Solaris sont loin d'être à l'abandon : annonces jusqu'en 2016 (voir la roadmap public). L'arrivée prochaine du Sparc T5 associée à la nouvelle version de Solaris 11 semble très prometteuse. Affaire à suivre.

 

Quelques sources de lectures en ces jours pluvieux :

Published by gloumps - dans divers
commenter cet article
16 juin 2012 6 16 /06 /juin /2012 10:16

 

 

Petit compte rendu sur un problème de performance que je viens de rencontrer sur un serveur Solaris Sparc avec une base de donnée Oracle.  Le contexte étant le suivant : temps de réponse dégradés suite au reboot du serveur. Bien entendu, aucun changement entre les deux reboot et pourtant l'application fonctionne moins bien qu'avant.

 

Commençons par le début :

 

$ vmstat 1 60

 kthr      memory            page            disk          faults      cpu
 r b w   swap  free  re  mf pi po fr de sr s7 s8 s9 s1   in   sy   cs us sy id
 2 2 0 153281392 104614544 4824 7797 16312 457 457 0 0 6 2 0 0 12173 125078 25167 18 9 73
 4 1 0 110702776 64484544 8681 26172 36014 0 0 0 0 0 0 0 0 28270 284267 39452 51 45 4
 27 2 0 110701000 64466128 8187 25244 33717 0 0 0 0 0 0 0 0 30699 317983 40125 56 43 0
 58 4 0 110655752 64437344 6890 35606 35200 0 0 0 0 0 0 0 0 29945 270086 39936 51 46 4
 81 2 0 110652760 64419824 2422 4687 21878 0 0 0 0 0 0 0 0 19933 146223 21668 56 42 2
 68 1 0 110640232 64442472 3117 7019 36429 0 0 0 0 0 0 0 0 17947 153021 21306 56 40 4
 82 2 0 110673872 64459640 3740 19469 15517 0 0 0 0 0 0 0 0 17143 197402 23112 55 45 0
 53 1 0 110817840 64541056 16751 85478 37213 0 0 0 0 13 0 0 0 32290 400389 43440 50 49 2
 27 1 0 110804904 64526728 9514 25054 29034 0 0 0 0 24 24 24 24 32222 362887 43524 57 41 2
 22 3 0 110760264 64497288 8110 10600 27836 0 0 0 0 10 24 24 24 33012 368583 46368 54 42 4
 46 1 0 110219560 64480488 5238 9330 16615 0 0 0 0 24 24 24 24 33111 293475 41391 54 45 1
 31 2 0 109691888 64462816 6337 5855 35649 0 0 0 0 24 24 24 24 32564 324041 41930 51 47 3
 8 1 0 110828328 64515976 7183 15999 60116 7 0 0 0 24 24 24 24 30930 363314 48875 55 37 8
 4 3 0 110738808 64452664 4294 4912 33406 0 0 0 0 24 24 24 24 25878 284752 40035 49 43 9

[...]

 

La runqueue est quelque peu remplie, vous ne trouvez pas ? Normalement l'utilisation système de ce serveur avoisine les 15%. Actuellement nous consommons plus du double. Bizarre !?

 

En détaillant un peu plus l'utilisation par cpu, j'obient cela :

 

$ mpstat 1 60

CPU minf mjf xcal  intr ithr  csw icsw migr smtx  srw syscl  usr sys  wt idl
  0  130   2 3928   219    8   16   18    5  152    0    68   36  64   0   0
  1   52  17 668688   152   17  514   84  102  119    0  2700   19  78   0   3
  2  123  23 875479    80   11  190   41   37  273    0   835   20  78   0   2
  3   67  10 5639   186   19  596  108  171 2739    2  4200   45  50   0   5
  4   82   0 2238   359   10  715  278  131  315    0  4078   47  52   0   1
  5  106   0 3470   191   16  325  120   91  170    1  1498   46  53   0   1
  6   81   0 6341   893   24 2110  739  410  174    0 10915   72  25   0   2
  7   48   2 4116   198   16  378  103   90  139    0  1809   20  78   0   2
  8   30   0 1686   103   18  776   40  128 2272    0  6072   70  20   0  10
  9   77   1 2085   106   22  486   32  110 4239    1  5263   35  48   0  17
 10   57   1  830   119   25 1760   41  111 1146    1 11804   56  33   0  11
 11   50   0 39677   142   40  602   35  125   93    0  3952   67  15   0  18
 12   82   0 3574   156   15  607   72  143  298    1  3154   36  49   0  15
 13  118   0 1263    96   25  174   37   60  251    0  1072   47  49   0   4
 14   66   0  992   146   16  600   57  125   75    0  3470   66  12   0  22
 15   53   0  330    87   11  448   12   38   96    0  2328   30  57   0  12
 16   57   4 7363   318   36 1543  147  431  124    0  7300   52  24   0  25
 17   38   2 10889 10088 9791 1366  142  389  306    0  5889   20  59   0  20
 18   61   2 4960   251   33 1051  115  327  119    0  5081   49  32   0  20
 19   20   1 4050   235   22 1149  110  281  153    0  5047   28  49   0  23
 20   69   0 189652   226   22  579  131  155  224    0  3525   32  61   0   6
 21   12   1 1361611    57   16   27    4   13   96    0   131    4  95   0   1
 22   88   1 5381   423   38 1049  259  285  601    0  6239   60  30   0  10
 23  144   1 5722   374   40  899  223  246 2358    2  6196   41  50   0   8
512   33   2 17331    65   10  102   22   31  499    0   923   12  86   0   2
513   33  19 120216   279   22  717  143  170  106    0  3107   43  55   0   2
514   53  20 14957   582   29 2035  398  480  215    1  9802   46  43   0  11
515    5  13 2871  1303 1218  139   24   32 2545    0   952    6  93   0   1
516   57   0 4672   243   14  475  175  110  170    0  2339   42  57   0   1
517   83   0 2163  1314 1250   23    5    3   84    0    86   25  75   0   0
518  106   1 8336  1001   25 2445  863  415  231    2 11656   65  32   0   3
519   56   0 5720   819   25 1905  655  415  229    1  9969   61  38   0   2
520   45   0 3534   139   36  411   28  141  139    0  1675   43  28   0  29
521   27   2 4369   167   37  677   27  149  184    0  2423   31  24   0  45
522   49   0 2994   128   27  644   20  114  143    0  2822   44  20   0  36
523   52   0 5220   176   27  819   56  151 2977    1  6423   25  38   0  37
524  172   1  310    55    8  304   10   27  233    0  1564   55  32   0  13
525   73   2 1535   123   13  597   46  115   86    0  3898   64  22   0  14
526   77   1 3821   242   29 1059   94  225  202    0  5572   50  28   0  22
527   52   1 2318   234   25 1106   87  234 1026    0  4908   39  25   0  36
528   59   0 4609   248   33 1145   98  285  164    0  5014   38  36   0  26
529   25   0 11442   341   41 1818  149  454   97    0  8854   37  31   0  32
530   33   0  553    81   10    4    5    1   48    0     0   34  66   0   0
531   51   1 6084   393   50 1754  172  468  113    0  7707   43  21   0  36
532   30   0 700781   139   12  263   85   65  135    0  1747   30  68   0   2
533   59   2 368218   183   29  394   73   95  252    0  2593   31  65   0   4
534  250   2 150619   255   32  685  145  228 2420    1  3932   39  59   0   2
535  108   4 906001   134   20  360   59  104  215    0  1804   24  72   0   4

[...]

 

Le nombre de smtx est anormalement haut. Regardons avec Dtrace ce qui se passe en mode kernel :

 

# ./hotkernel

Sampling... Hit Ctrl-C to end.
^C

FUNCTION                        COUNT   PCNT
genunix`rctl_set_tearoff            1   0.0%
[...]

unix`idle                        6622   2.8%
SUNW,UltraSPARC-IV              15472   6.6%
unix`default_lock_delay         18426   7.8%
unix`disp_getwork               44618  19.0%
unix`mutex_delay_default       115315  49.0%

 

Voilà pourquoi le nombre de smtx est élevé. Le temps d'utilisation kernel provient essentiellement de mutex. Voyons qui les génèrent :

 

# dtrace -n 'profile:::profile-1001hz /arg0/ { @[func(arg0), execname] = count(); }'

[...]

  SUNW,UltraSPARC-IV+`gettick      oracle            5062
  unix`mutex_enter                 oracle            6222
  unix`mutex_delay_default         svc.startd        6768
  unix`kcage_cageout               pageout           8347
  unix`mutex_delay_default         tnslsnr           8811
  unix`page_numtopp_nolock         pageout           9325
  unix`generic_idle_cpu            sched             9829
  unix`idle                        sched            76849
  unix`default_lock_delay          oracle           96305
  unix`disp_getwork                sched           275834
  unix`mutex_delay_default         oracle          573610

 

Il s'agit des process Oracle. L'analyse de la stack() peut nous en dire un peu plus :

 

# dtrace -n 'profile:::profile-1001hz /arg0 && execname == "oracle"/ \
{ @[stack()] = count(); } tick-60s { trunc(@,10); exit(0); }'
 

dtrace: description 'profile:::profile-1001hz ' matched 2 probes
CPU     ID                    FUNCTION:NAME
 16  85099                        :tick-60s

[...]
              unix`mutex_delay_default+0x4
              unix`current_thread+0x164
              unix`default_lock_delay+0x6c
              unix`mutex_vector_enter+0x460
              unix`sfmmu_hat_enter+0x2c
              unix`sfmmu_tlb_range_demap+0x88
              unix`hat_unload_callback+0x7dc
              genunix`segvn_unmap+0x28c
              genunix`as_unmap+0xf0
              genunix`munmap+0x78
              unix`syscall_trap+0xac
             5736
[...]
              unix`mutex_delay_default+0x4
              unix`current_thread+0x164
              unix`default_lock_delay+0x6c
              unix`mutex_vector_enter+0x460
              unix`sfmmu_hat_enter+0x2c
              unix`sfmmu_size_tsb+0x4
              unix`sfmmu_check_page_sizes+0x17c
              unix`hat_do_memload+0xf4
              genunix`segvn_faultpage+0x560
              genunix`segvn_fault+0xbf0
              genunix`as_fault+0x4c8
              unix`pagefault+0xac
              unix`trap+0xd50
              unix`utl0+0x4c
             7342

              unix`mutex_delay_default+0x4
              unix`current_thread+0x164
              unix`default_lock_delay+0x6c
              unix`mutex_vector_enter+0x460
              unix`sfmmu_hat_enter+0x2c
              unix`sfmmu_size_tsb+0x4
              unix`sfmmu_check_page_sizes+0x17c
              unix`hat_unload_callback+0x898
              genunix`segvn_unmap+0x28c
              genunix`as_unmap+0xf0
              mm`mmsegmap+0xa8
              genunix`cdev_segmap+0x60
              specfs`spec_char_map+0x104
              specfs`spec_map+0x94
              genunix`fop_map+0x40
              genunix`smmap_common+0x3ac
              genunix`smmap64+0x80
              unix`syscall_trap+0xac
             8367

              unix`mutex_delay_default+0x4
              unix`current_thread+0x164
              unix`default_lock_delay+0x6c
              unix`mutex_vector_enter+0x460
              unix`sfmmu_hat_enter+0x2c
              unix`sfmmu_tlb_range_demap+0x88
              unix`hat_unload_callback+0x7dc
              genunix`anon_private+0x20c
              genunix`segvn_faultpage+0x7d4
              genunix`segvn_fault+0xbf0
              genunix`as_fault+0x4c8
              unix`pagefault+0xac
              unix`trap+0xd50
              unix`utl0+0x4c
            12659

              unix`mutex_delay_default+0x4
              unix`current_thread+0x164
              unix`default_lock_delay+0x6c
              unix`mutex_vector_enter+0x460
              unix`sfmmu_hat_enter+0x2c
              unix`sfmmu_size_tsb+0x4
              unix`sfmmu_check_page_sizes+0x17c
              unix`hat_do_memload+0xf4
              genunix`segvn_faultpage+0x32c
              genunix`segvn_fault+0xbf0
              genunix`as_fault+0x4c8
              unix`pagefault+0xac
              unix`trap+0xd50
              unix`utl0+0x4c
            27669

              unix`mutex_delay_default+0x4
              unix`current_thread+0x164
              unix`default_lock_delay+0x6c
              unix`mutex_vector_enter+0x460
              unix`sfmmu_hat_enter+0x2c
              unix`sfmmu_tsbmiss_exception+0x6c
              unix`utl0+0x4c
            98775

 

Un des avantages de l'ISM est de diminuer l'impact sur les tables TLB/TSB. Au vu des appels, il semble que cela soit le contraire. L'appel à la fonctions sfmmu_check_page_sizes() est assez étrange : normalement un segment ISM utilise des larges de 4Mo sur Sparc. Alors pourquoi rechercher une taille de page ?

 

En parcourant le code source d'Opensolaris pour la fonction sfmmu_tsbmiss_exception() on peut lire cela :

 

/*
* Handle exceptions for low level tsb_handler.
*
* There are many scenarios that could land us here:
*
* If the context is invalid we land here. The context can be invalid
* for 3 reasons: 1) we couldn't allocate a new context and now need to
* perform a wrap around operation in order to allocate a new context.
* 2) Context was invalidated to change pagesize programming 3) ISMs or
* TSBs configuration is changeing for this process and we are forced into
* here to do a syncronization operation. If the context is valid we can
* be here from window trap hanlder. In this case just call trap to handle
* the fault.
*
[...]

 

Le cas 3 est assez surprenant : un changement de configuration ISM pour un process donné ? Vérifions un peu le mapping mémoire du segment ISM :

 

# pmap -xs 5514 | more

5514:   ora_pmon_XXXX01
         Address   Kbytes     RSS   Anon   Locked Pgsz Mode   Mapped File
0000000100000000    73728   73728      -        -   4M r-x--  oracle
0000000104800000     8192    8192      -        -    - r-x--  oracle
0000000105000000    20480   20480      -        -   4M r-x--  oracle
[...]

0000000380000000     8192    8192      -     8192   4M rwxsR  [ ism shmid=0x3 ]
0000000380800000    16384   16384      -    16384    - rwxsR  [ ism shmid=0x3 ]
0000000381800000    16384   16384      -    16384   4M rwxsR  [ ism shmid=0x3 ]
0000000382800000     4096    4096      -     4096    - rwxsR  [ ism shmid=0x3 ]
0000000382C00000    20480   20480      -    20480   4M rwxsR  [ ism shmid=0x3 ]
0000000384000000     4096    4096      -     4096   8K rwxsR  [ ism shmid=0x3 ]
0000000384400000    36864   36864      -    36864   4M rwxsR  [ ism shmid=0x3 ]
0000000386800000       16      16      -       16    - rwxsR  [ ism shmid=0x3 ]
0000000386804000        8       8      -        8   8K rwxsR  [ ism shmid=0x3 ]
0000000386806000        8       8      -        8    - rwxsR  [ ism shmid=0x3 ]
0000000386808000       24      24      -       24   8K rwxsR  [ ism shmid=0x3 ]
000000038680E000       32      32      -       32    - rwxsR  [ ism shmid=0x3 ]
0000000386816000       16      16      -       16   8K rwxsR  [ ism shmid=0x3 ]
000000038681A000        8       8      -        8    - rwxsR  [ ism shmid=0x3 ]
[...]
000000038683A000        8       8      -        8   8K rwxsR  [ ism shmid=0x3 ]
000000038683C000       24      24      -       24    - rwxsR  [ ism shmid=0x3 ]
0000000386842000       16      16      -       16   8K rwxsR  [ ism shmid=0x3 ]
0000000386846000        8       8      -        8    - rwxsR  [ ism shmid=0x3 ]
0000000386848000        8       8      -        8   8K rwxsR  [ ism shmid=0x3 ]

[...]

 

Quelque chose cloche !! Pour le même segment ISM nous avons une multitude de pages de tailles différentes mais surtout l'allocation du segment ISM est complètement fragmentée. Les sessions Oracle perdent un temps important dans la gestion de mémoire ISM. L'origne reste cependant inconnu !

 

L'ouverture d'un call au support Oracle confirme bien cette analyse (merci Alain). Cependant rien de bien précis concernant l'origine. Lors d'une activitée mémoire soutenue sur un serveur, ce bug peut se produire mais dans notre cas le serveur venait de rebooter. S'agissant d'une base Oracle 10.2.0.4, l'option NUMA est activée. Du coup le segment ISM est découpé entre les différents lgrp disponibles sur le serveur. La recherche de page par sous segment ISM lors de l'activation du NUMA peut poser un peu plus de problème (cela fonctionnait avant non ?). La taille de l'ARC peut aussi influencer lors de la recherche des pages pour la création de l'ISM. Mystère...

 

 

Ci-joint quelques références sur ce sujet :

 

Published by gloumps - dans kernel
commenter cet article
1 mai 2012 2 01 /05 /mai /2012 19:13

 

Petit retour sur la mise oeuvre d'une carte Fusion IO sous Solaris 10x64. J'ai été amené à tester un des produit de la gamme Fusion IO pour répondre à différentes problèmatiques liées aux bases de données Oracle et Sybase (les différents tests ont été effectués avec la carte ioDrive Duo à 1,28 To).

 

L'installation du driver n'a rien de bien sorcier (un simple pkgadd, merci du peu). Il se peut que le module ne soit pas chargé automatiquement après l'installation du package, il vous suffit alors d'utiliser add_drv pour le faire. Une fois le package installé et le module chargé, vous pouvez utiliser votre carte.

 

# cd /opt/fusionio/bin
# ./fio-status -a

Found 2 ioDrives in this system with 1 ioDrive Duo
Fusion-io driver version: 2.3.1 build 123

Adapter: ioDrive Duo
    Fusion-io ioDrive Duo 1.28TB, Product Number:FS3-202-641-CS SN:100364
    ioDrive Duo HL, PN:00190000107, Mfr:004, Date:20110104
    External Power: NOT connected
    Powerloss protection: available
    PCIE Bus voltage: avg 12.20V, min 12.11V, max 12.21V
    PCIE Bus current: avg 0.91A, max 2.76A
    PCIE Bus power: avg 11.07W, max 27.49W
    PCIE Power limit threshold: 24.75W
    Connected ioDimm modules:
     fct0: Fusion-io ioDrive Duo 1.28TB, Product Number:FS3-202-641-CS SN:72376
     fct1: Fusion-io ioDrive Duo 1.28TB, Product Number:FS3-202-641-CS SN:72417

fct0  Attached as 'fioa' (block device)
      Fusion-io ioDrive Duo 1.28TB, Product Number:FS3-202-641-CS SN:72376
      ioDIMM3 640GB MLC, PN:00276700501, Mfr:004, Date:20110103
      Located in slot 1 Lower of ioDrive Duo SN:100364
      Powerloss protection: protected 

      PCI:0c:00.0 

      Vendor:1aed, Device:1005, Sub vendor:1aed, Sub device:1010
      Firmware v5.0.7, rev 101971
      640.00 GBytes block device size, 812 GBytes physical device size
      Format: block, v300, 1,250,001,920 sectors, 512 bytes per sector
      Error correction: 39 bits per 960 bytes
      FPGA ID:0 Format UID:000000011ab80132db170041f8755400
      Internal temperature: 49.7 degC, max 54.1 degC
      Board temperature: 40 degC
      Internal voltage: avg 0.996V, max 1.005V
      Aux voltage: avg 2.429V, max 2.429V
      Media status: Healthy; Reserves: 100.00%, warn at 10.00%
      Lifetime data volumes:
        Physical bytes written: 238,962,192,171,536
        Physical bytes read   : 233,379,513,217,664
        RAM usage:
           Current: 206,100,480 bytes
           Peak   : 275,838,976 bytes

fct1  Attached as 'fiob' (block device)
      Fusion-io ioDrive Duo 1.28TB, Product Number:FS3-202-641-CS SN:72417
      ioDIMM3 640GB MLC, PN:00276700501, Mfr:004, Date:20110103
      Located in slot 0 Upper of ioDrive Duo SN:100364
      Powerloss protection: protected
      PCI:0b:00.0
      Vendor:1aed, Device:1005, Sub vendor:1aed, Sub device:1010
      Firmware v5.0.7, rev 101971
      640.00 GBytes block device size, 812 GBytes physical device size
      Format: block, v300, 1,250,001,920 sectors, 512 bytes per sector
      Error correction: 39 bits per 960 bytes
      FPGA ID:0 Format UID:000000011ae10132db170041f8755400
      Internal temperature: 54.6 degC, max 59.6 degC
      Board temperature: 44 degC
      Internal voltage: avg 1.017V, max 1.025V
      Aux voltage: avg 2.435V, max 2.438V
      Media status: Healthy; Reserves: 100.00%, warn at 10.00%
      Lifetime data volumes:
        Physical bytes written: 247,334,121,450,136
        Physical bytes read   : 244,476,258,760,136
        RAM usage:
           Current: 209,283,072 bytes
           Peak   : 277,673,984 bytes

 

 

Quelques précausions avant de commencer à l'utiliser la carte : mettre à jour le firmware de la carte (fio-update-iodrive) et la formater avant utilisation.

 

# ./fio-detach /dev/fct0
Detaching: [====================] (100%) |

# ./fio-detach /dev/fct1 
Detaching: [====================] (100%) |

# ./fio-format /dev/fct0
Creating a standard block device of size 640.00GBytes (596.05GiBytes).
  Using block (sector) size of 512 bytes.

WARNING: Formatting will destroy any existing data on the device!
Do you wish to continue [y/n]? y
Formatting: [====================] (100%) \
Format successful.

# ./fio-format /dev/fct1
Creating a standard block device of size 640.00GBytes (596.05GiBytes).
  Using block (sector) size of 512 bytes.

WARNING: Formatting will destroy any existing data on the device!
Do you wish to continue [y/n]? y
Formatting: [====================] (100%) |
Formatting: [====================] (100%)
Format successful.

# ./fio-attach /dev/fct0
Attaching: [====================] (100%) -
fioa

# ./fio-attach /dev/fct1
Attaching: [====================] (100%) -
fiob

 

 

Nous voiçi donc avec une unité de stockage prête à l'emploi. A vous de choisir le LVM (SVM, ZFS) selon vos uses et coutumes. Pour les amateurs de VxVM sous Solaris, je pense qu'il n'y a pas de problèmes (les tests restent à être réalisés, je susi preneur de l'information).

 

Ci-joint quelques tests comparatifs entre du stockage SAN et la carte Fusion IO. Tous les tests ont été réalisés avec l'utilitaire filebench.

 

Configuration SAN :

  •  Solaris s10x_u10wos_17b (kernel 147441-11)
  • Stockage EMC VMAX (52 Luns de 34 Go)
  • VxVM (stripe 4 colonnes - stripe unit 64 Ko)
  • UFS largefile
  • Option de montage directio et non directio

 

Configuration Fusion IO :

  • Solaris s10x_u10wos_17b (kernel 147441-11)
  • Stockage Fusion IO
  • ZFS (avec compression)
  • Dataset (logbias à throuput)

 

Résultats :

 

Configuration SAN sans directio

 

filebench> load oltp
 [...]
filebench> set $dir=/filebench
filebench> set $iosize=8192
filebench> set $filesize=2147483648
filebench> run runtime
[...]
 9894: 2585.561: IO Summary: 87982 ops, 1466.331 ops/s, (741/719 r/w), 11.2mb/s, 2890us cpu/op, 243.7ms latency
 9894: 2585.561: Shutting down processes
 9894: 2588.876: Deleting ISM...

 

 

Configuration SAN avec directio


filebench> load oltp
[...]
filebench> set $dir=/filebench
filebench> set $iosize=8192
filebench> set $logfilesize=2147483648
filebench> run runtime
[...]
12702: 2205.474: IO Summary: 485747 ops, 8095.346 ops/s, (4038/4016 r/w),  62.9mb/s,    523us cpu/op,  13.6ms latency
12702: 2205.474: Shutting down processes
12702: 2207.606: Deleting ISM...

 

 

Configuration Fusion IO

 

filebench> load oltp
[...]
filebench> set $dir=/fusionio
filebench> set $iosize=8192
filebench> set $filesize=2147483648
filebench> run runtime
[...]
24859: 2337.767: IO Summary: 2287573 ops, 38045.769 ops/s, (18937/18914 r/w), 296.9mb/s,    223us cpu/op,   8.4ms latency
24859: 2337.767: Shutting down processes
24859: 2339.914: Deleting ISM... 

 

 

Les résultats parlent d'eux-mêmes, non ? Le débit sur la carte Fusion IO avoisine les 300 Mb/s ?! Le fait d'utiliser de ZFS compressé permet en plus d'augmenter de manière significative la capacité de stockage de la carte (sans altérer ses incroyables capacités).

 

Juste un petit bémol, sur une infrastructure de production, il est conseillé d'avoir une solution de secours. Avec ce type de configuration, l'utilisation d'outils de clustering classique ne permettent pas une bascule efficace (récupération des données entre les deux serveurs). Il faut donc se poser la question suivante : Comment répliquer les données ? Il faut donc mettre en oeuvre d'autres outils : par exemple Dataguard pour Oracle ou des outils de réplication de données sur IP comme AVS.

 

 

Ci-joint quelques références sur ce sujet :

 

Published by gloumps - dans administration
commenter cet article
22 mars 2012 4 22 /03 /mars /2012 20:48

 

Le 5 avril prochain Oracle France organise l'évènement : Oracle SPARC Supercluster, Performance, Souplesse et Ouverture.

 

Le SuperCluster est une solution totalement intégrée conçue pour héberger, en mode hautement disponible et avec des performances extrêmes, vos applications, vos bases données et vos middleware au sein d'un même châssis. Sa capacité multi-fonctions (support de multiples versions de bases de données, de différentes typologies d'applications...) lui confère une souplesse d'utilisation unique.

 

L'ouverture de SPARC SuperCluster (connexion au SAN, évolutivité verticale et horizontale...) rend son intégration aisée au sein de votre infrastructure existante. Le SPARC SuperCluster est notamment composé de serveurs T4-4, d'un réseau Infiniband, d'une applicance Oracle ZFS Storage et de Solaris 11.

 

Je vous invite donc rapidement à vous inscrire à cet évènement via l'agenda du GUSES ou directement sur le site Oracle pour décourvrir dans le détail cette nouvelle machine intégrée.

 

 

Ci-joint quelques références sur ce sujet :

Published by gloumps - dans divers
commenter cet article
15 mars 2012 4 15 /03 /mars /2012 17:32

 

Lors des deux précédents articles (disponibles ici et ), j'ai évoqué à plusieurs reprises la notion de NUMA sans trop la détailler. NUMA (NonUniform Memory Access) est devenue l'une des architectures matérielles la plus utilisée dans la conception des serveurs. Je profite donc de cet article pour revenir sur son intégration dans Solaris (notamment les versions 10 et 11).

 

En théorie, une machine NUMA est composée d'une ou plusieurs nodes disposant chacune d'un certain nombre de CPU(s) et d'une certaine quantité de mémoire. Toutes les nodes sont interconnectées entre elles et partagent l'intégralité mémoire de la machine. Les temps d'accès mémoire contenue dans une node sont inférieurs aux temps d'accès mémoire contenue dans une node distante (modèle de latence).

 

Un modèle de latence consiste le plus souvent à un ou plusieurs locality groups (lgrps). Chaque lgrp est constitué :

  • d'une ou plusieurs CPU(s)
  • d'une ou plusieurs pages de mémoire physiques

lgroup

 

A noter qu'il existe plusieurs modèles de latence plus ou moins complexes (différents niveaux de latence).

 

Solaris est "aware" de l'architecture matérielle NUMA : les différentes nodes sont des éléments connus du système Solaris. L'association mémoire / CPUs est connue de Solaris sous la forme de groupe de localité (locality group).

 

Le framework MPO (Memory Placement Optimization) est un composant essentiel à l'architecture NUMA. Pour une application en cours de fonctionnement, le système Solaris tente de l'exécuter sur une CPU la plus proche de la mémoire pour minimiser le plus possible les temps d'accès à celle-ci.

 

Quelques notions importantes à connaître :

  • Pour chaque nouveau thread un locality group est sélectionné (home lgrp)
  • L'algorithme d'ordonnancement tentera d'exécuter un thread sur une des CPUs de son home lgrp
  • La classe d'ordonnancement RT n'est pas prise en compte dans cet algorithme

Un thread peut changer de home lgrp uniquement si :

  • Le locality group est détruit
  • Le thread est binder sur une autre CPU d'un autre locality group

Plusieurs paramètres sont disponibles pour modifier le comportement des lgrps. Voir la section suivante : Locality Group Parameters dans Oracle Solaris Tunable Parameters Reference Manuel.

 

 

Maintenant, passons un peu à la pratique... Pour connaître le nombre de lgrps disponible sur un système, il existe deux méthodes : en utilisant la commande kstat ou en passant par mdb :

 

# kstat -m lgrp  
module: lgrp             instance: 1    
name:   lgrp1            class:    misc
    alloc fail           294068397
    cpus                 8
    crtime               343.726918435
    default policy       0
    load average         11296
    lwp migrations       1309
    next-seg policy      0
[...]


# mdb -k

Loading modules: [...]

> ::walk cpu |::print cpu_t cpu_lpl |::print lgrp_t lgrp_id !sort -u
lgrp_id = 0x6bdd
lgrp_id = 0x8356
lgrp_id = 0x840b
lgrp_id = 0xa232

 

La macro lgrp disponible dans mdb permet d'obtenir bien plus d'informations sur les lgrps dont notamment le nombre de CPUs et leurs répartitions. Attention cette macro n'est pas disponible dans toutes les updates de Solaris 10 :

 

# mdb -k
Loading modules: [...]
> ::lgrp
 LGRPID             ADDR           PARENT    PLATHAND   #CPU    CPUS
      0 fffffffffbc20580                0     DEFAULT      0     
      1 fffffffffbc0d440 fffffffffbc20580           0      8    0-7
      2 fffffffffbc0d4a8 fffffffffbc20580           1      8    8-15
      3 fffffffffbc0d510 fffffffffbc20580           2      8    16-23
      4 fffffffffbc0d578 fffffffffbc20580           3      8    24-31

 

Les statistiques des lgrps sont disponibles facilement via la commande kstat. Par exemple pour le lgrp 3, il  suffit de saisir la commande suivante :

 

$ kstat -m lgrp -i 3
module: lgrp                       instance: 3    
name:   lgrp3                      class:    misc
    alloc fail                     557701
    cpus                           8
    crtime                         345.278084135
    default policy                 0
    load average                   48125
    lwp migrations                 41345
    next-seg policy                0
    next-touch policy              9959223943
    pages avail                    33554432
    pages failed to mark           0
    pages failed to migrate from   0
    pages failed to migrate to     0
    pages free                     6976717
    pages installed                33554432
    pages marked for migration     0
    pages migrated from            0
    pages migrated to              0
    random policy                  5496062
    round robin policy             0
    snaptime                       8170819.92639302
    span process policy            0
    span psrset policy             0

 

Pour obtenir le home lgrp d'un thread en cours d'exécution, il suffit d'utiliser mdb (l'adresse du lgrp est stockée dans la structure kthread_t) :

 

# mdb -k

Loading modules: [...]

> 0t26116::pid2proc |::walk thread |::print kthread_t t_lpl |::print struct lgrp_ld lpl_lgrpid

lpl_lgrpid = 0x4

 

Lors de la création d'un thread, il suffit d'utiliser le one-liner Dtrace ci-dessous pour connaître rapidement son home lgrp :

 

# dtrace -qn 'thread_create:return { printf("Created thread (PID %d LWP %d) with home lgroup %d\n", pid, tid, curthread->t_lpl->lpl_lgrpid); }"
Created thread (PID 26539 LWP 1) with home lgroup 3
Created thread (PID 26743 LWP 1) with home lgroup 2
Created thread (PID 26745 LWP 1) with home lgroup 4
Created thread (PID 5913 LWP 1) with home lgroup 3
Created thread (PID 26745 LWP 1) with home lgroup 4
Created thread (PID 18609 LWP 26478) with home lgroup 3
Created thread (PID 18609 LWP 26478) with home lgroup 3
Created thread (PID 26757 LWP 1) with home lgroup 4
Created thread (PID 2473 LWP 7) with home lgroup 4
Created thread (PID 26754 LWP 1) with home lgroup 4
^C
Created thread (PID 26763 LWP 1) with home lgroup 1
Created thread (PID 26771 LWP 1) with home lgroup 2

 

En théorie, un thread sera le plus souvent exécuté sur les CPUs disponibles dans son home lgrp. Pour vérifier cela, j'utilise un petit script Dtrace (inspiré du script getlgrp.d disponible dans Solaris Internals - attention j'ai du modifié quelque peu le code pour qu'il fonctionne sur les dernières versions de Solaris 10) :

 

# mdb -k

Loading modules: [...]

> 0t11517::pid2proc |::walk thread |::print kthread_t t_lpl |::print struct lgrp_ld lpl_lgrpid
lpl_lgrpid = 0x4

 

# ./lgrp.d 11517
^C
Threads CPUs and lgrps for PID 11517

TID   LGRP     CPUID    COUNT  
================================
1     2        8        2      
1     1        2        4      
1     1        7        5      
1     1        3        6      
1     1        5        6      
1     1        6        6      
1     2        9        6      
1     2        10       6      
1     2        13       6      
1     1        0        7      
1     2        11       7      
1     1        4        8      
1     2        12       8      
1     2        15       8      
1     1        1        9      
1     3        16       9      
1     3        20       9      
1     3        22       9      
1     2        14       10     
1     3        21       10     
1     3        17       11     
1     3        23       11     
1     3        19       12     
1     3        18       13     
1     4        26       216    
1     4        31       226    
1     4        28       246    
1     4        24       247    
1     4        29       298    
1     4        25       308    
1     4        27       342    
1     4        30       370 

 

Dans cet exemple, le processus 11517 contient un seul lwp. On constate que celui-ci est exécuté majoritairement sur les différentes CPUs du lgrp 4. L'algorithme du MPO effectue correctement son travail pour favoriser l'exécution du processus sur son home lgrp.

 

Lors de la création d'un fils (processus ou thread), le système Solaris tente de sélectionner une CPU dans le home lgrp du père. Cependant si les ressources souhaitées (notamment mémoire) ne sont pas disponibles, le système choisit alors un nouveau home lgrp pour ce fils.

 

Pour observer ces évènements, j'utilise la fonction lgrp_move_thread() :

 

# ./lgrpmove.d

Thread 1 (pid 13222) from Home lgrp 4 rehomed to New lgrp 3
Thread 1 (pid 18776) from Home lgrp 1 rehomed to New lgrp 2
Thread 1 (pid 18774) from Home lgrp 1 rehomed to New lgrp 4
Thread 864 (pid 18800) from Home lgrp 4 rehomed to New lgrp 2
Thread 1 (pid 18816) from Home lgrp 3 rehomed to New lgrp 1
Thread 1 (pid 18822) from Home lgrp 2 rehomed to New lgrp 1
Thread 1 (pid 15869) from Home lgrp 4 rehomed to New lgrp 3
Thread 1 (pid 15944) from Home lgrp 2 rehomed to New lgrp 1
Thread 1 (pid 18843) from Home lgrp 2 rehomed to New lgrp 3
Thread 1 (pid 15869) from Home lgrp 4 rehomed to New lgrp 3
Thread 1 (pid 15869) from Home lgrp 4 rehomed to New lgrp 3
Thread 1 (pid 18864) from Home lgrp 4 rehomed to New lgrp 1
Thread 1 (pid 15944) from Home lgrp 2 rehomed to New lgrp 1
Thread 1 (pid 18855) from Home lgrp 3 rehomed to New lgrp 2
Thread 1 (pid 18880) from Home lgrp 2 rehomed to New lgrp 3

^C

Thread 1 (pid 18863) from Home lgrp 1 rehomed to New lgrp 3
Thread 1 (pid 18857) from Home lgrp 4 rehomed to New lgrp 3

 

Dans Solaris 11, nous disposons deux nouvelles commandes lgrpinfo et plgrp pour consulter et changer le home lgrp d'un thread (Je vous encourage à consulter avec attention les pages de manuels de ces deux nouvelles commandes).

 

La commande lgrpinfo affiche toutes les informations sur les lgrps :

 

# lgrpinfo
lgroup 0 (root):
        Children: 1 2
        CPUs: 0-11
        Memory: installed 48G, allocated 2.8G, free 45G
        Lgroup resources: 1 2 (CPU); 1 2 (memory)
        Latency: 70197
lgroup 1 (leaf):
        Children: none, Parent: 0
        CPUs: 0 2 4 6 8 10
        Memory: installed 24G, allocated 915M, free 23G
        Lgroup resources: 1 (CPU); 1 (memory)
        Load: 0.168
        Latency: 48058
lgroup 2 (leaf):
        Children: none, Parent: 0
        CPUs: 1 3 5 7 9 11
        Memory: installed 24G, allocated 1.9G, free 22G
        Lgroup resources: 2 (CPU); 2 (memory)
        Load: 0.0259
        Latency: 48058

 

Pour obtenir le home lgrp d'un thread, il suffit simplement simplement de saisir la commande plgrp :

 

# plgrp $$
     PID/LWPID    HOME
    2947/1        2    

 

L'exécution d'une application bénéficiant du meilleur placement est un axe d'optimisation de plus en plus important. Plusieurs recherches vont dans ce sens : après MPO dans Solaris 9 et 10, Solaris 11 utilise aussi des algorithmes de placements pour les I/O (NUMA I/O). Affaire à suivre...

 

 

Ci-joint quelques références sur ce sujet :

 

Published by gloumps - dans kernel
commenter cet article
16 février 2012 4 16 /02 /février /2012 08:20

 

C'est une question que plusieurs d'entre nous (admistrateurs de base de données ou adminstrateurs systèmes) se posent. Quelques éléments de réponses évoqués dans cette article.

 

Pour rappel, il s'agit d'une option cachée dans la base de données Oracle (_enable_NUMA_support en Oracle 11g et _enable_numa_optimization en Oracle 10g). Cette option lorsqu'elle est activée permet de découper la mémoire partagée par les processus Oracle en plusieurs segments (la fameuse SGA). Cependant ce découpage dépend exclusivement de l'architecture matérielle sur laquelle la base Oracle s'exécute. En Oracle 10g jusqu'à la version 10.2.0.3, cette option était active par défaut. Bizarrement, cette option a été désactivé dans toutes les autres versions (encore actuellement avec la 11gr2). Pourtant, activer cette option peut s'avérer fort utile (voir le workaround concernant un bug dans l'ISM avec Solaris x86).

 

Que devons nous faire alors ? Si vous posez la question au support Oracle bases de données la réponse est clair : ne pas l'activer. Par contre si vous posez la question su support Oracle système la réponse est légérement différente : oui vous pouvez l'activer si votre architecture est NUMA. Cette option active par défaut dans les versions inférieurs à la 10.2.0.4 pose plusieurs problèmes si la base de données s'exécute sur une architecture non NUMA (bizarrement, c'est ce qu'il s'est notamment produit avec les serveurs HP Superdome). Suite à plusieurs incidents remontés au support Oracle bases de données, les équipes de dev ont tout simplement décidé de désactiver cette option (bien avant le rachat de Sun par Oracle).

 

Pour répondre à un besoin particulier, nous avons décidé de l'activer sur plusieurs bases de données. Pour le moment aucun disfonctionnement nous a été remonté vis-à-vis de la gestion de la mémoire partagée mais voilà ce que nous avons détecté lors de sa mise en place sur des serveurs Solaris 10u9... 

 

Lors du démarrage de la base de données, nous avons constatés les messages suivants dans le fichier d'alertes d'Oracle :

 

[...]
2012-01-20 14:52:17.564000 +01:00

WARNING: Local memory allocation shmadvice failure, errno = 22
2012-01-20 14:52:32.994000 +01:00
WARNING: Local memory allocation shmadvice failure, errno = 22
2012-01-20 14:52:49.119000 +01:00
WARNING: Local memory allocation shmadvice failure, errno = 22
2012-01-20 14:53:04.047000 +01:00
WARNING: Local memory allocation shmadvice failure, errno = 22
[...]   

 

Les différents segments ont tous été activés correctement ( 4 segments + 1 pour la gestion) :

 

# pmap -x 2993
[...]
0000000060000000 14024704 14024704 - 14024704 2M rwxsR [ism shmid=0x7000003]
00000003C0000000 11796480 11796480 - 11796480 2M rwxsR [ism shmid=0x7000004]
00000006A0000000 11796480 11796480 - 11796480 2M rwxsR [ism shmid=0x7000005]
0000000980000000 11927552 11927552 - 11927552 2M rwxsR [ism shmid=0x7000006]
0000000C60000000 11796480 11796480 - 11796480 2M rwxsR [ism shmid=0x7000007]
0000000F40000000       20       20 -       20 4K rwxsR [ism shmid=0x7000008]
[...] 

 

En traçant le démarrage de la base Oracle, on obtient les informations suivantes :

 

[...]
shmget(IPC_PRIVATE, 12079595520,0640|IPC_CREAT|IPC_EXCL) = 117440545

shmsys(5, 0x07000021, 0x00000001, 0xFFFFFC7FFFDFA2F8) = Err#22 EINVAL
[...] 

 

Le syscall shmsys() est uniquement utilisé lorsque l'option NUMA est activée dans la base. Le 1er argument de shmsys() permet de déterminer quelle sous fonction est exécutée. Il y a 4 choix possible et un par défaut. Etrangement le code retour du choix par défaut est EINVAL (code source). Pourquoi Oracle base de données utilise la valeur 5 pour cet argument ? S'agit'il d'un bug ? Pour info, l'erreur se produit autant de fois qu'il y a de segments.

 

Réponse du support Oracle : il s'agit d'un problème d'interfaçage entre Oracle bases de données et Solaris (bug 12596470). Ce bug est corrigé dans Solaris 10u10 et Solaris 11.

 

Malgré la présence de ce bug, l'activation de NUMA ne semble pas poser de problème. Les segments de la base de données utilisent les lgrps de Solaris. Mais les utilisent-ils correctement ?

 

En attendant un statut officiel d'Oracle sur l'activation ou non de cette option, vous pouvez tenter de l'activer au moins sur vos architectures de dev/test/uat avant de franchir le cap en production. Pour l'heure, plusieurs bases en production fonctionnent avec cette option active sans avoir eu de problème (à l'exception du bug cité ci-dessus).

 

 

Ci-joint quelques références sur ce sujet : 

 

Published by gloumps - dans divers
commenter cet article
12 février 2012 7 12 /02 /février /2012 15:20

 

Après avoir rencontré quelques anomalies dans la gestion de ISM sous Solaris x86 (voir l'analyse du bug), nous allons étudier la manière de le contourner. Pour rappel le bug est le suivant : non partage de la table de pages en ISM. Les workarounds mis en oeuvre ici concernent uniquement les bases de données Oracle. Cependant certains d'entre eux peuvent vous aider à adresser ce type de problème dans contextes différents. Je remercie Alain et Thierry (consultants Oracle) pour l'aide apportée sur la mise en place de ces workarounds (notamment sur la partie Oracle base de données).

 

 

Ce bug a toujours existé dans Solaris 10x86, et pourtant personne ne l'a remarqué. Et pourquoi donc !? Il faut deux éléments pour qu'il devienne visisble sur le système :

  • Une taille de ISM importante (supérieur à 80 Go environ)
  • Une multitude d'attachements / détachements à cette ISM

 

Sans ces deux conditions, le dysfonctionnement n'est pas impactant pour le système (la consommation du serveur n'est pas affectée par des Spin locks provenant du bug). Il y a deux manières de controurner ce problème :

  • La taille de l'ISM
  • Diminuer le nombre d'attachements / détachements

 

Diminuer la taille de l'ISM va un peu à l'encontre de l'histoire !! Possédant des serveurs de plus en plus capacitifs (512 Go de RAM voir plus maintenant), et ne pas en profiter pleinement, c'est un peu ridicule. Une approche plus constructive serait de découper le segment ISM par plusieurs segments de plus petites tailles. Solaris a bien des qualités mais ne posséde malheuresement pas celle de découper un segment ISM (à l'inverse de Linux : voir shmmax et shmall).

 

Reste que le monde informatique est bien fait !! L'architecture des serveurs x86 (je parle des serveurs produits actuellement) fonctionne en utilisant le schéma mémoire NUMA. Pour simplifier, le temps d'accès à la mémoire dépend de sa localisation par rapport aux processeurs. Solaris utilise pleinement ces fonctionnalités à travers les locality groups (lgrp). La mémoire est implicitement découpée par le système Solaris. La base de données Oracle est capable de découper son segment de mémoire partagée sur les différents locality groups disponibles sur le serveurs. Quand je vous disais que le monde informatique était bien fait !! Il s'agit d'activer une option lors du démarrage de la base de données.

 

L'autre approche est de limiter le nombre d'attachements / détachements. Même si diminuer le nombre d'utilisateurs reste une solution, je ne vous la conseille pas !! Par contre utiliser les fonctionnalités d'Oracle base de données nous permet de répondre à ce besoin. Il s'agit d'utiliser soit la fonctionnalité de Shared Server soit la fonctionnalité de Database Resident Connection Pooling. La dernière fonctionnalité étant disponible en version 11g. 

 

Le protocol de tests est assez simple : lancement de 50 connexions simultanées (via sqlplus). Chaque sqlplus provoque une connexion / déconnexion à la base toutes les 2 secondes. L'activité du système est surveillée par la commande vmstat, les locks (et leurs temps) sont tracés avec un petit script Dtrace. Tous les tests ont été réalisés avec une SGA de 200 Go et 25 Go de shared pool.

 

Résultats obtenus :      

 

Cas 1 : Reproduction du problème

 

Paramétrage Aucun
Durée des 50 connexions 2m16s
Charge CPU Saturé en mode Système
Nombre de locks Spin et Block Des milliers de Spin et Block
Temps des locks Spin

Spin de quelques ms à 700ms

Temps des locks Block

Block de quelques ms à plusieurs milliers de ms

 

 

Cas 2 : Utilisation de NUMA

 

Paramétrage Activation de NUMA
Durée des 50 connexions 32s
Charge CPU 60% en mode système - 5% en mode user
Nombre des locks Spin et Block Des milliers de Spin et Block
Temps des locks Spin Spin inférieur à 1ms
Temps des locks Block Block compris entre 10ms et 100ms

 

Remarques :

  • 4 lgrps disponibles sur le serveur
  • 3 segments ISM de 50 Go + 1 segment ISM de 75 Go (50 Go de SGA et 25 Go PGA)
  • 1 segment ISM de quelques Mo pour la gestion des 4 autres segments

 

Cas 3 : Utilisation de Data Resident Connection Pooling dans Oracle

 

Paramétrage Activation du Data Resident Connection Pooling
Durée des 50 connexions 26s
Charge CPU Inférieur à 5% en mode système et user
Nombre des locks Spin et Block Quelques appels lors de la création des processus de pool
Temps des locks Spin Quelques nanosecondes
Temps des locks Block

Aucun

 

Remarques :

  • Lors du test, un hang non expliqué est apparu
  • Les limitations fonctionnelles de connexions au même schéma sont à valider par l'applicatif

 

Cas 4 : Utilisation de Shared Server      

 

Paramétrage Activation des Shared Server
Durée des 50 connexions 24s
Charge CPU Inférieur à 5% en mode système et user
Nombre des locks Spin et Block Quelques appels lors de la création des processus de pool
Temps des locks Spin Quelques nanosecondes
Temps des locks Block Aucun

 

Remarques :

  • Quelques ajustements à faire : nombre de serveurs, large pool, taille de la UGA
  • Fonctionnalités présentes depuis plusieurs versions d'Oracle base de données

 

Les 3 workarounds présentés ici permettent d'augementer la taille de la SGA de votre base Oracle sur Solaris x86 sans saturer votre système. Les fonctionnalités présentes dans Oracle (Data Resident Connection Pooling et Shared Servers) permettent même de masquer complétement le bug ISM : les attachements / détachements sont supprimés. Cependant leur mise en oeuvre nécessite un paramétrage à faire valider par les utilisateurs. L'option NUMA est plus simple à mettre en oeuvre mais dépend surtout de votre architecture matérielle : nombre de lgrps disponibles sur votre système (j'écris en ce moment un petit artcile à ce sujet).

 

 

Ci-joint quelques références sur ce sujet : 

 

Published by gloumps - dans kernel
commenter cet article
31 janvier 2012 2 31 /01 /janvier /2012 23:03

 

Continuons un peu cette formidable aventure dans la gestion de l'ISM sous Solaris x86. Dans l'article précédent, j'évoque un problème d'initialisation de l'ISM provenant des tailles de pages. Dans cet article, j'ai découvert un bug dans la gestion de l'ISM toujours sous Solaris x86.

 

Suite à une migration d'une base de données Oracle d'une architecture Solaris Sparc à une architecture Solaris x86, l'équipe DBA a décidé d'utiliser pleinement la mémoire disponible sur cette nouvelle infrastructure. Disposant d'un serveur avec 512 Go de mémoire, la SGA de la base Oracle a été positionnée à 290 Go (afin de diminuer les lectures physiques et d'éviter les locks R/W). L'augmentation de cette SGA a eu un bénéfice important sur les opérations de lectures (plus d'activité sur les disques SAN concernant les lectures) par contre le système Solaris saturait...

 

# vmstat 3
kthr memory page disk faults cpu
r b w swap free re mf pi po fr de sr s0 s1 s6 s7 in sy cs us sy id
11 2 0 274157192 335523004 1348 8439 1506 2 2 0 1 5 -1 158 105 15844 31218 10183 5 7 88
2 12 0 86340852 144652404 1996 43583 0 25 24 0 0 0 0 0 0 64086 182685 44871 13 34 53
2 0 0 86352032 144645428 4773 45640 0 17 17 0 0 0 0 0 0 179020 200275 59466 16 31 53
0 1 0 86327500 144637200 1680 42171 0 35 33 0 0 0 0 0 0 69311 178558 44632 14 40 46
2 0 0 86357008 144655832 2035 35481 0 13 13 0 0 0 0 0 0 62857 162021 45164 13 25 63
2 0 0 86334148 144631452 1940 44848 0 11 11 0 0 0 0 0 0 64294 188696 43993 13 38 49
1 1 0 86171376 144496048 3014 52949 0 5 5 0 0 0 0 0 0 64821 192942 46708 17 30 52
52 1 0 86025360 144381188 1779 38176 0 16 16 0 0 0 0 0 0 47234 129932 29021 13 64 24
2 0 0 85953152 144301940 1766 50384 0 21 20 0 0 5 0 0 0 68138 181369 40882 18 46 37
0 2 0 86124088 144497016 2889 38238 0 11 11 0 0 0 0 0 0 53142 151981 36137 11 46 43
50 0 0 86065384 144470520 1806 46570 0 27 24 0 0 0 0 0 0 41055 147273 26207 9 71 20
2 0 0 86020672 144434312 1818 30717 8 3 1 0 0 0 0 0 0 59711 155183 37919 11 55 33
20 1 0 86000472 144415592 2892 46429 0 24 23 0 0 0 0 0 0 48937 161600 32703 12 66 23

^C

 

Le système saturait complètement lors de l'utilisation massive de la base de données. Avec un load de plus 200 sur 5 minutes, un pourcentage de 80 pour le SYS et 20 pour le USER, quelques choses ne fonctionnait pas correctement.

 

Passons à l'analyse de ce problème. D'abord, qui utilise le temps système ?

 

# dtrace -n 'profile-1001hz /arg0/ { @[execname] = count(); }'
dtrace: description 'profile-1001hz ' matched 1 probe
^C
[…]
mpathadm 1102
fsflush 2160
tnslsnr 4541
sched 37200
oracle 496331

 

Le temps système provient des process Oracle DB. Une bonne chose mais cela reste étrange. Que fait Oracle pour consommer autant de temps système ?

 

# dtrace -n 'profile-1001hz /arg0 && execname == "oracle" / { @[stack()] = count(); } tick-60s { trunc(@,5); exit(0);}'
dtrace: description 'profile-1001hz ' matched 2 probes
CPU ID FUNCTION:NAME
19 73222 :tick-60s

unix`mutex_delay_default+0x7
unix`mutex_vector_enter+0x99
ipc`ipc_get+0x62
shmsys`shmget+0x4a
shmsys`shmsys+0x7e
unix`sys_syscall+0x17b
83649

unix`mutex_delay_default+0xa
unix`mutex_vector_enter+0x99
ipc`ipc_lock_internal+0x4b
ipc`ipc_lock+0x11
shmsys`shm_detach+0x5c
shmsys`shmdt+0x90
shmsys`shmsys+0x6d
unix`sys_syscall+0x17b
94488

unix`mutex_delay_default+0x7
unix`mutex_vector_enter+0x99
ipc`ipc_lock_internal+0x4b
ipc`ipc_lock+0x11
shmsys`shm_detach+0x5c
shmsys`shmdt+0x90
shmsys`shmsys+0x6d
unix`sys_syscall+0x17b
108405

unix`mutex_delay_default+0xa
unix`mutex_vector_enter+0x99
ipc`ipc_lock_internal+0x4b
ipc`ipc_lookup+0x29
shmsys`shmat+0x70
shmsys`shmsys+0x59
unix`sys_syscall+0x17b
129651

unix`mutex_delay_default+0x7
unix`mutex_vector_enter+0x99
ipc`ipc_lock_internal+0x4b
ipc`ipc_lookup+0x29
shmsys`shmat+0x70
shmsys`shmsys+0x59
unix`sys_syscall+0x17b
147262

Fort intéressant !? Lors des appels systèmes shmat() et shmdt(), le système consomme son temps dans des mutex. Regardons cela de plus près. S'aggissant de locks type adaptive mutex, deux choses sont à vérifier : 

  • le temps d'acquisition de la ressource (cpu off donc mutex adaptive block)
  • le temps écoulé pendant l'obtention de la ressource (cpu on donc mutex spin)

 

J'ai écrit rapidement un petit script Dtrace me permettant de quantifier rapidement ces deux temps (j'utilise notamment la probe lockstat). Ci-joint le résultat

 

# ./ipc_lock.d

558462664068813 cpu  4 exec oracle pid 23796: adaptive-block(0) took 1015 ms
558461944173547 cpu 28 exe oracle pid 23864: adaptive-block(0) took 1185 ms
558462329451173 cpu 30 exe oracle pid 23886: adaptive-spin(0) took 2570 ms
558462329430767 cpu 31 exe oracle pid 23724: adaptive-spin(0) took 1930 ms
558463436775114 cpu  0 exec oracle pid 23906: adaptive-spin(0) took 1963 ms
558463900687630 cpu  0 exec oracle pid 22498: adaptive-spin(0) took 1598 ms
558463900815833 cpu  0 exec oracle pid 23165: adaptive-block(0) took 1088 ms
558463119973512 cpu  1 exec oracle pid 23840: adaptive-spin(0) took 2979 ms
558463900250335 cpu  2 exec oracle pid 23868: adaptive-spin(0) took 3515 ms
558463436925731 cpu  5 exec oracle pid 23786: adaptive-block(0) took 1397 ms
558463900448070 cpu  6 exec oracle pid 23808: adaptive-block(0) took 1199 ms
558463900426025 cpu 10 exec oracle pid 22343: adaptive-spin(0) took 1766 ms
558463436944972 cpu 14 exec oracle pid 23881: adaptive-block(0) took 1203 ms
558463775141403 cpu 15 exec oracle pid 23903: adaptive-spin(0) took 3979 ms
558463646477100 cpu 16 exec oracle pid 23858: adaptive-spin(0) took 3374 ms
558463545080417 cpu 17 exec oracle pid 23842: adaptive-block(0) took 1299 ms
558463775195434 cpu 20 exec oracle pid 23838: adaptive-block(0) took 1164 ms
558463775112272 cpu 21 exec oracle pid 23900: adaptive-spin(0) took 1893 ms
558464220990762 cpu  8 exec oracle pid 23471: adaptive-spin(0) took 1754 ms
558464221051681 cpu 15 exec oracle pid 23136: adaptive-spin(0) took 1967 ms
558466485966584 cpu  9 exec oracle pid 23903: adaptive-spin(0) took 1040 ms
558466153296593 cpu 16 exec oracle pid 23918: adaptive-spin(0) took 1597 ms
558467238545528 cpu  1 exec oracle pid 23855: adaptive-spin(0) took 1206 ms
558467660401004 cpu  8 exec oracle pid 23888: adaptive-spin(0) took 1917 ms
558466980614425 cpu  9 exec oracle pid 23938: adaptive-block(0) took 1141 ms
558466980595351 cpu 11 exec oracle pid 23930: adaptive-block(0) took 1354 ms
558467779687829 cpu 14 exec oracle pid 23955: adaptive-spin(0) took 2318 ms
558467976549814 cpu  4 exec oracle pid 23908: adaptive-spin(0) took 1210 ms
558467976490096 cpu  5 exec oracle pid 23641: adaptive-spin(0) took 1278 ms
558469750980230 cpu  3 exec oracle pid 23936: adaptive-spin(0) took 3297 ms
558469308862236 cpu  5 exec oracle pid 23911: adaptive-spin(0) took 1332 ms
558469308776939 cpu  7 exec oracle pid 23920: adaptive-spin(0) took 3390 ms
558469308793235 cpu  8 exec oracle pid 23890: adaptive-spin(0) took 3219 ms
558469308812116 cpu 10 exec oracle pid 23955: adaptive-spin(0) took 1413 ms
ˆC
558469750890183 cpu 11 exec oracle pid 23991: adaptive-spin(0) took 1774 ms

 

Ca se passe de commentaire non !? Plus de 3 secondes en moyenne pour les adaptive spin !!! Mais que se passe t'il exactement ? Lors de chaque attachement ou détachement à la SGA, le système lock la ressource IPC. En moyenne, il y a environ 20 attachements / détachements seconde sur cette base de données avec plus de 1000 connexions actives en simultanées (voir la colonne NATTCH).

 

# ipcs -mopi -z zonexxxx
IPC status from <running system> as of Tue Oct 23 10:14:51 CET 2011
T         ID      KEY        MODE        OWNER    GROUP NATTCH  CPID  LPID ISMATTCH
Shared Memory:
m  520093698   0x77adb4f8 --rw-rw----   oracle      dba   1338 29340 18826     1338    

 

Voyons un peu plus dans le détail les différentes stack() kernel obtenus lors des locks adaptive spin et block.

 

# ./ipc_stack.d

   unix`htable_release+0x93
   unix`hati_load_common+0x12d
   unix`hat_share+0x281
   genunix`segspt_shmattach+0xd2
   genunix`as_map_locked+0x102
   genunix`as_map+0x4a
   shmsys`shmat+0x500
   shmsys`shmsys+0x59
   genunix`dtrace_systrace_syscall+0xc7
   unix`sys_syscall+0x17b
   225

 

   unix`htable_lookup+0x8c
   unix`hati_load_common+0x5b
   unix`hat_share+0x281
   genunix`segspt_shmattach+0xd2
   genunix`as_map_locked+0x102
   genunix`as_map+0x4a
   shmsys`shmat+0x500
   shmsys`shmsys+0x59
   genunix`dtrace_systrace_syscall+0xc7
   unix`sys_syscall+0x17b
   606 

 

   unix`htable_lookup+0x8c
   unix`hat_unshare+0x7e
   genunix`segspt_shmunmap+0x81
   genunix`as_unmap+0x137
   shmsys`shm_detach+0x4b
   shmsys`shmdt+0x90
   shmsys`shmsys+0x6d
   genunix`dtrace_systrace_syscall+0xc7
   unix`sys_syscall+0x17b
   897

 

La fonction hat_share() semble assez intéressante à étudier. En regardant d'un peu plus près le code source, on constate l'élément suivant : suite à différentes conditions, soit la table de pages est partagée soit elle ne l'est pas (goto share - goto unshare). Si vous avez lu l'article précédant, un des avantages d'utiliser un segment ISM est justement de pouvois partager sa table de pages entre les différents processus se connectant à ce segment.

 

La fonction hati_load_command() exécutée dans la fonction hat_share() se déclenche uniquement dans le goto unshare. Tient donc, on utilise ISM et on ne partage pas la table de pages entre les différents processus !? Une des conditions provoque ce dysfonctionnement mais laquelle ? La taille de la SGA influence t'elle quelques choses ? Y a t'il une limite à la SGA ?

 

J'ai décidé de reprendre cette analyse sur différentes bases Oracles ayant des tailles de SGA différentes. Le résultat est surprenant... Pour chaque attachement à la SGA, la stack est identique. Cela veut dire que la table de pages n'est jamais partagée sur un Solaris 10x86 quand l'ISM est activé !!! Oupppsss !!! Cependant les temps de locks sont nettement inférieurs à la seconde et augementent quand la taille de la SGA augmente.

 

Pour résumé, l'ISM activé sur Solaris 10x86 ne partage pas la table de pages entre les différents processus qui y accèdent. Plus il y a d'attachements simultanés plus le phénomène s'accentue. Plus la taille de l'ISM est important plus les temps de locks sont importants. Avec toute ces petites informations j'ai ouvert un call chez Oracle. Le diagnostique s'avère exact, un bug a été ouvert en interne avec la référence suivante Bug 7127336: page table not shared for ISM segment on x64.

 

La correction du Bug semble assez complexe à mettre en oeuvre. J'ai donc travaillé avec les ingénieurs Oracle afin de trouver une solution temporaire à ce problème... Il va falloir attendre un peu pour les solutions...

 

Ci-joint quelques références sur ce sujet :

 

 

Published by gloumps - dans kernel
commenter cet article
28 janvier 2012 6 28 /01 /janvier /2012 16:32

 

Retour sur le dernier évènement Oracle The Extreme Performance Tour qui s'est déroulé le 25 janvier dernier à Paris (cet évènement se déroule dans plusieurs villes d'Europe). 

 

image001

 

Dans un magnifique cadre, devant 300 invités, Oracle a réaffirmé son ambition d'innover à travers sa gamme de produits hardware et systèmes. Avant de participer aux deux ateliers thématiques, les invités ont eu le plaisir d'écouter tour à tour Loic le Guisquet (Vice Président EMAA) et John Fowler (Vice Président Systems Oracle Corp).

 

Deux idées à retenir de ces discours :

  • Malgré la conjoncture délicate, c'est le moment d'innover !?
  • Oracle nous accompagne dans cette période délicate du mieux possible !? 

 

John Fowler est revenu sur l'offre complète Oracle Systems de la manière suivante :

  • Présentation d'une Roadmap Hardware : T4, Mxxxx, T5 (rien sur l'offre x86 !?)
  • Présentation de l'offre Extreme (Exadata, Exalogic, Exalytic, Big Data)
  • Présentation du Sparc Super Cluster (à base de T4-4)
  • Présentation de Solaris 11
  • Présentation de l'offre storage (SAN, NAS, Tape)

 

Pour ceux qui doutent encore de la périnité du Hardware Oracle et du système d'exploitation Solaris (sur les architectures Intel et Sparc), voici quelques messages clés à retenir : 

  • Fusion des deux puces Tx avec le Mxxxx
  • Investissement logiciels (Solaris et Unbreakable Linux) sur les architectures Intel et Sparc (pour Solaris)      
  • Renforcement de l'offre Extreme en essayant de l'adapter aux besoins des clients (boxes adaptées !?)

 

Etant moi-même intervenu pour le GUSES, je ne reviendrai pas sur l'ensemble des ateliers qui se sont déroulés. Au sujet de ma présentation, j'ai évoqué 3 retours d'expériences autour des technologies Solaris dans des environnements de production :

  • Consolidation d'une infrastructure de DEV/UAT sur Mxxxx avec des zones
  • Activation de la compression ZFS pour diminuer l'espace de stockage
  • Utilisation massive de zones dans un environnement de production avec le bon outilage

Ma présentation est disponible dans mon album.

 

En fin de journée, les invités ont pu assister à une table ronde sur l'innovation au service de la performance emmené par deux grands spécialistes : Joël de Rosnay et Pascal Picq. Discussion passionante autour de l'innovation, de ses enjeux, sa mise en oeuvre, ses origines, ses directions, etc.

 

Un évènement fort intéressant. N'oublier pas : ce type d'évènement (forcément commercial) permet surtout l'échange entre personnes d'entreprises issues de secteurs différents. Par exemple, j'ai été surpris de voir autant d'entreprises adopter l'architecture T4 avec Oracle VM (ldom) mais aussi leur intérêt grandissant pour Linux Unbreakable.

 

En conclusion, penser détenir la meilleur solution sans se remettre en cause (par l'innovation), peut provoquer votre "perte". Optez alors pour Solaris 11...

 

Ci-joint quelques références sur ce sujet : 

 

Published by gloumps - dans divers
commenter cet article
9 janvier 2012 1 09 /01 /janvier /2012 18:13

 

Petit sujet qui m'a tenu en haleine. Pour faciliter sa compréhension je le découpe en deux parties : une première partie sur un problème d'initialisation d'un segment de type ISM et une seconde partie sur un dysfonctionnement de l'ISM. Les deux sous Solaris x86 uniquement.

 

Mais de quoi parlons nous ? Quelques explications sont nécessaires. Pour partager des données et synchroniser des évènements entre processus, le système Solaris utilise un framework nommé IPC (InterProcess Communication). Ce framework contient plusieurs objets IPC dont le standard POSIX IPC : POSIX semaphores, POSIX shared memory et POSIX message queues. 

 

J'évoque ici l'objet IPC : POSIX shared memory. Cet objet est notamment utilisé dans les bases de données (en tout cas Oracle et Sybase). Pour les "spécialistes" de ces produits, il s'agit ni plus ni moins de la fameuse SGA. Pour nous, les "spécialistes" du système nous appelons cela un segment SHM (Segment sHared Memory). Lors du démarrage d'une instance Sybase ou Oracle, un segment SHM est initialisé avec une taille spécifique. Si cette taille n'est pas disponible, l'instance ne s'active pas. 

 

Par défaut, la création d'un segment SHM : 

  • n'est pas locké en mémoire (donc swappable).
  • utilise des tailles de pages par défaut (soit 4K sous Solaris x86 et 8K sous Solaris sparc).
  • n'utilise pas de table de translation d'addresse commune entre tous les processus utilisants ce segment.

Les ingénieurs Solaris ont donc optimisé la gestion de ce segment SHM : ISM (Intimate Shared Memory).

 

L'ISM corrige les problèmatique d'un segment SHM classique : 

  • taille de pages optimisée.
  • création d'une table de partage d'adresse pour optimiser les translation.
  • segment automatiquement locké en mémoire.

L'utilisation de ce type de segment est devenu le standard pour les bases de données : la SGA fonctionne donc avec un segment ISM sous Solaris.

 

D'où mon problème : ma base de données Oracle 11g r2 sous Solaris 10x86 (update 9) n'utilise pas un segment ISM mais un simple segment SHM !!! Analysons un peu tout cela. 

 

En espectant l'espace d'adresse du process Oracle (ici pmon), j'ai étais surpris de constater que la SGA utilisait un segment SHM classique : 

 

# pmap -x 10735
10735:  ora_pmon_XXXX22
         Address   Kbytes       RSS    Anon   Locked Mode   Mapped File
0000000000400000   222240     91144       -       - r-x--   oracle
000000000DD17000     1180       676     208       - rw---   oracle
000000000DE3E000      136        32      32       - rw---   oracle
000000000DE60000     1828      1644    1632       - rw---   [ heap ]
0000000060000000        4         4       -       - r--s-   [ shmid=0x4000003c ]
0000000060001000  2097156   2028692       -       - rwxs-   [ shmid=0x4000003c ]
FFFFFD7FFCAA0000       64         8       8       - rwx--   [ anon ]
FFFFFD7FFCABE000       72         8       8       - rw---   [ anon ]
FFFFFD7FFCAD0000       64        12      12       - rw---   [ anon ]
[...] 

 

L'initialisation d'un segment type ISM provient du demandeur et non du système. J'ai donc décidé de vérifier les logs de démarrage de l'instance Oracle (fichier alert.log). Je suis tombé sur ce message fort intéressant : 

 

Mon Nov 21 16:38:40 2011
Starting ORACLE instance (normal)
WARNING: Not enough physical memory for SHM_SHARE_MMU segment of size 0x0000000080002000 [flag=0x4000] 

 

Lors de l'activation de l'instance, Oracle a tenté d'activer un segment type ISM sans y être parvenu. Le message indiquant l'erreur suivante : Not enough physical memory for SHM_SHARE_MMU segment. Tiens donc pas assez de mémoire ? Alors que la SGA demandée correspondait à seulement 2 Go ? La vérité était ailleurs... 

 

Pour mieux reproduire le problème, j'ai décidé d'écrire un petit programme C me permettant de créer un segment type ISM. Contrairement à ce que je pensais, ce n'est pas lors de la création du segment que le type ISM est spécifié mais lors d'un attachement. 

 

La création et l'attachement correspondent aux appels suivants :

 

shmget(2, size, 0660 | IPC_CREAT | IPC_EXCL)

shmat(shmid, (void *)0, SHM_SHARE_MMU) 

 

Le flag SHM_SHARE_MMU de la fonction shmat permet l'utilisation de l'ISM. L'exécution de mon petit programme C m'a permis d'activer sans problème un segment ISM de 10 Go. 

 

# ./ishm
shmid: 1526726689


# ipcs -m
IPC status from <running system> as of Tue Jan 10 11:26:10 CET 2012
T         ID      KEY        MODE        OWNER    GROUP
Shared Memory:
m 1526726689   0x2        --rw-rw----     root     root

[...]

 

# pmap -x 24680
24680:  ./ishm
         Address   Kbytes       RSS  Anon    Locked Mode   Mapped File
0000000000400000        4         4     -         - r-x--  ishm
0000000000410000        8         8     8         - rw---  ishm
FFFFFD7F80000000  1048576   1048576     -   1048576 rwxsR  [ ism shmid=0x5b000021 ]
FFFFFD7FFF210000       64        64    64         - rwx--  [ anon ]
FFFFFD7FFF230000       24        12    12         - rwx--  [ anon ]
FFFFFD7FFF240000     1276       712     -         - r-x--  libc.so.1
FFFFFD7FFF380000        4         4     4         - rwx--  [ anon ]
FFFFFD7FFF38F000       36        36    36         - rw---  libc.so.1
FFFFFD7FFF398000       16         4     4         - rw---  libc.so.1
FFFFFD7FFF3AE000      244       244     -         - r-x--  ld.so.1
FFFFFD7FFF3F0000        4         4     4         - rwx--  [ anon ]
FFFFFD7FFF3FB000        8         8     8         - rwx--  ld.so.1
FFFFFD7FFF3FD000        8         8     8         - rwx--  ld.so.1
FFFFFD7FFFDFE000        8         8     8         - rw---  [ stack ]
---------------- -------- --------- ----- ---------
        total Kb  1050280   1049692   156   1048576 

 

Mais où était mon problème ? Oracle doit en faire un peu plus ? J'ai donc tracé les appels systèmes lors du démarrage d'une instance. 

 

[...]
6362:   shmget(672617948, 1073754112, 0660|IPC_CREAT|IPC_EXCL) = 83886086
6362:   shmget(672617949, 0, 0)                         Err#2 ENOENT
6362:   shmget(672617950, 0, 0)                         Err#2 ENOENT
6362:   shmget(672617951, 0, 0)                         Err#2 ENOENT
6362:   shmat(83886086, 0x60000000, 040000)             Err#22 EINVAL
6362:   shmat(83886086, 0x60000000, 0)                  = 0x60000000
[...]

 

Oracle s'attache en spécifiant une adresse mémoire 0x60000000. J'ai donc modifié mon petit programme C en spécifiant la même adresse d'attachement et j'ai obtenu à ma grande surprise l'erreur suivante : 

 

# ./ishm
shmat: Invalid argument

 

J'ai obtenu la même erreur que le démarrage de la base Oracle. Bingo ! Lors de l'appel à la fonction shmat (si on spécifie l'adresse 0x60000000) l'attachement ne s'effectue pas. Mais pourquoi ? Dépassant un peu mes compétances j'ai ouvert un call au support Oracle. 

 

Réponse du support Oracle : la valeur 0x60000000 n'est pas divisible (valeur entière) par l'ensemble des tailles de pages disponibles sur le système Solaris 10x86. Il faut donc désactiver la taille de pages posant problème (option désactivée dans le kernel patch suivant 144489-17). Le workaround n'est pas applicable en production (boot en mode kernel debugging + modification avant chargement du kernel de la valeur largepagesupport). 

 

En vérifiant mes tailles de pages disponibles sur mon serveur DL380 G7, j'obtiens le résultat suivant : 

 

# pagesize -a
4096
2097152
1073741824 

 

Tiens donc, on peut utiliser des tailles de pages de 1Go !? Et bizarrement c'est avec cette taille de pages où la valeur 0x60000000 n'est pas divisible en une valeur entière. L'application du patch supprime la possibilité d'utiliser cette taille de pages. 

 

Voilà donc la fin de la 1er partie sur ISM et Solaris 10x86. La 2ème partie fait référence à un bug dans la gestion de l'ISM uniquement pour Solaris 10x86 (et Solaris 11x86). Bug que j'ai eu le privilège de découvrir en exclusivité... 

 

Ci-joint quelques références sur ce sujet : 

 

Published by gloumps - dans kernel
commenter cet article