Test delle prestazioni su Google Kubernetes Engine

Per testare le prestazioni di lettura e scrittura di un carico di lavoro Google Kubernetes Engine (GKE) da più client GKE, utilizza lo strumento di benchmark IOR. Le seguenti istruzioni mostrano come automatizzare la configurazione del client e utilizzare IOR con mpirun tramite SSH senza password tra i pod Kubernetes per testare l'I/O aggregato.

Prerequisiti

  • Un'istanza Managed Lustre di cui è già stato eseguito il provisioning.

  • Un ambiente Docker locale configurato e autenticato per il push su Google Artifact Registry o Container Registry (vedi Metodi di autenticazione).

  • Assicurati che il valore mtu della rete sia impostato su 8896.

Crea un cluster GKE

Per testare le prestazioni, devi disporre di un cluster GKE con il driver CSI Managed Lustre abilitato. Per i carichi di lavoro di archiviazione ad alte prestazioni, configura i node pool GKE con famiglie di macchine ottimizzate per il calcolo (ad es. c2 o c3) e la rete TIER_1.

Esegui il comando seguente per creare un cluster GKE Standard ottimizzato per i test sulle prestazioni:

gcloud container clusters create CLUSTER_NAME \
    --zone=ZONE \
    --machine-type=MACHINE_TYPE \
    --addons=LustreCsiDriver \
    --network-performance-configs=total-egress-bandwidth-tier=TIER_1 \
    --network=NETWORK \
    --num-nodes=NUM_NODES
  • Sostituisci ZONE e NETWORK con i valori di deployment specifici. Il cluster deve risiedere nella stessa rete VPC dell'istanza Managed Lustre.

  • Scegli un MACHINE_TYPE. Per informazioni sulla scelta dei tipi di macchine per ottenere il miglior throughput, consulta Considerazioni sul rendimento.

  • Se il tipo di macchina non supporta la rete TIER_1, elimina la riga --network-performance-configs dal comando.

  • Specifica NUM_NODES. Per saturare il file system, la capacità di rete aggregata del cluster deve superare il throughput di cui è stato eseguito il provisioning del file system di circa il 20%.

    Per le macchine con la rete Tier 1 abilitata, un singolo nodo può eseguire il push tra 25 Gbps e 200 Gbps (~3000-25.000 MBps), a seconda della famiglia di VM e del numero di CPU. Per le istanze standard, l'uscita è in genere limitata a circa 2 Gbps per vCPU.

    Ad esempio, se la capacità dell'istanza Managed Lustre produce 100.000 MBps di throughput teorico, è necessaria un'uscita client aggregata di 120.000 MBps (100,000 * 1.2) per saturarla:

    • Con le istanze standard: se ogni nodo ha un'uscita pubblicata di 2000 MBps, devi eseguire il provisioning di almeno 60 nodi (120,000 / 2,000).
    • Con la rete Tier 1: se ogni nodo ha un'uscita pubblicata di 10.000 MBps (~80 Gbps), devi eseguire il provisioning di almeno 12 nodi (120,000 / 10,000).

Crea l'immagine Docker IOR

Crea un'immagine container con OpenMPI e IOR installati. Compila IOR con il supporto I/O asincrono (AIO) per prestazioni migliori.

  1. Crea un file denominato Dockerfile in locale:

    FROM ubuntu:22.04
    
    # Prevent interactive prompts during installation
    ENV DEBIAN_FRONTEND=noninteractive
    
    # Install dependencies, SSH, and required Autotools packages
    RUN apt-get update && apt-get install -y \
      openssh-server \
      openmpi-bin \
      libopenmpi-dev \
      wget \
      git \
      make \
      gcc \
      g++ \
      automake \
      autoconf \
      libtool \
      pkg-config \
      libaio-dev \
      sudo \
      && rm -rf /var/lib/apt/lists/*
    
    # Build IOR from source (version 4.0.0) with Asynchronous I/O (AIO) support
    RUN git clone -b 4.0.0 https://github.com/hpc/ior /tmp/ior \
      && cd /tmp/ior \
      && ./bootstrap \
      && ./configure --disable-dependency-tracking --with-aio \
      && make -j"$(nproc)" \
      && make install \
      && rm -rf /tmp/ior
    
    # Configure SSH for OpenMPI passwordless communication
    RUN mkdir /var/run/sshd
    RUN echo 'root:root' | chpasswd
    RUN sed -i 's/^#PermitRootLogin.*/PermitRootLogin yes/' /etc/ssh/sshd_config
    RUN sed -i 's/^#PasswordAuthentication.*/PasswordAuthentication yes/' /etc/ssh/sshd_config
    
    # SSH login fix so user isn't kicked out after container initialization
    RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
    
    EXPOSE 22
    CMD ["/usr/sbin/sshd", "-D"]
    
  2. Crea ed esegui il push di questa immagine nel registro container che preferisci. Le istruzioni riportate in questo documento utilizzano Artifact Registry.

    export IMAGE_TAG="gcr.io/PROJECT_ID/lustre-ior-benchmark:latest"
    docker build -t $IMAGE_TAG .
    docker push $IMAGE_TAG
    

Genera chiavi SSH senza password per MPI

OpenMPI richiede la comunicazione tra i nodi tramite SSH senza password. Crea una chiave SSH e archiviala in un secret Kubernetes.

  1. Genera le chiavi RSA:

    ssh-keygen -t rsa -b 4096 -C "mpi-user" -N '' -f "./id_rsa"
    
  2. Crea il secret Kubernetes:

    kubectl create secret generic mpi-ssh-secret \
      --from-file=id_rsa=./id_rsa \
      --from-file=id_rsa.pub=./id_rsa.pub \
      --from-file=authorized_keys=./id_rsa.pub
    

Crea volume permanente e richiesta

Collega i pod GKE all'istanza Managed Lustre utilizzando il provisioning statico.

  1. Crea un file denominato lustre-pv.yaml. Sostituisci quanto segue:

    • CAPACITY con la capacità di archiviazione dell'istanza in GiB.
    • EXTENDED_LUSTRE_ID con l'identificatore Managed Lustre, nel formato PROJECT_ID/ZONE/INSTANCE_NAME. Ad esempio, project-123/us-west1-a/my-lustre-instance.
    • LUSTRE_IP con l'indirizzo IP di montaggio dell'istanza.
    • FS_NAME con il nome del file system dell'istanza.

    Questi valori possono essere recuperati con il gcloud lustre instances describe comando.

    apiVersion: v1
    kind: PersistentVolume
    metadata:
      name: my-lustre-pv
    spec:
      storageClassName: ""
      claimRef:
        name: my-lustre-pvc
        namespace: default
      accessModes:
        - ReadWriteMany
      capacity:
        storage: CAPACITYGi   # retain `Gi` suffix
      persistentVolumeReclaimPolicy: Retain
      volumeMode: Filesystem
      csi:
        driver: lustre.csi.storage.gke.io
        volumeHandle: EXTENDED_LUSTRE_ID   # project-name/zone/instance-name
        volumeAttributes:
          ip: LUSTRE_IP
          filesystem: FS_NAME
    ---
    apiVersion: v1
    kind: PersistentVolumeClaim
    metadata:
      name: my-lustre-pvc
    spec:
      storageClassName: ""
      volumeName: my-lustre-pv
      accessModes:
        - ReadWriteMany
      resources:
        requests:
          storage: CAPACITYGi
    
  2. Applica il manifest:

    kubectl apply -f lustre-pv.yaml
    

Esegui il deployment dei worker MPI

Per scalare le attività IOR su più nodi, esegui il deployment di un StatefulSet con l'immagine di benchmark.

  1. Crea un file denominato mpi-workers.yaml. Specifica PROJECT_ID, e imposta NUM_NODES sul numero di nodi nel cluster.

    apiVersion: v1
    kind: Service
    metadata:
      name: mpi-workers
      labels:
        app: mpi-worker
    spec:
      clusterIP: None
      selector:
        app: mpi-worker
      ports:
      - port: 22
        name: ssh
    ---
    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: mpi-worker
    spec:
      serviceName: "mpi-workers"
      replicas: NUM_NODES
      selector:
        matchLabels:
          app: mpi-worker
      template:
        metadata:
          labels:
            app: mpi-worker
        spec:
          tolerations:
            - operator: "Exists"
          containers:
            - name: mpi-worker
              image: gcr.io/PROJECT_ID/lustre-ior-benchmark:latest
              command: ["/bin/sh", "-c"]
              args:
                - >-
                  mkdir -p /var/run/sshd &&
                  ssh-keygen -A &&
                  mkdir -p /root/.ssh &&
                  echo "Host *" > /root/.ssh/config &&
                  echo "    StrictHostKeyChecking no" >> /root/.ssh/config &&
                  echo "    UserKnownHostsFile=/dev/null" >> /root/.ssh/config &&
                  cp /mnt/mpi-ssh-keys/id_rsa /root/.ssh/id_rsa &&
                  cp /mnt/mpi-ssh-keys/id_rsa.pub /root/.ssh/id_rsa.pub &&
                  cp /mnt/mpi-ssh-keys/authorized_keys /root/.ssh/authorized_keys &&
                  chmod 700 /root/.ssh &&
                  chmod 600 /root/.ssh/* &&
                  exec /usr/sbin/sshd -D
              ports:
                - containerPort: 22
              volumeMounts:
                - name: lustre-mount
                  mountPath: /lustre
                - name: ssh-key-secret
                  mountPath: /mnt/mpi-ssh-keys
                  readOnly: true
          volumes:
            - name: lustre-mount
              persistentVolumeClaim:
                claimName: my-lustre-pvc
            - name: ssh-key-secret
              secret:
                secretName: mpi-ssh-secret
    
  2. Applica il manifest:

    kubectl apply -f mpi-workers.yaml
    

Esegui il benchmark IOR

Avvia il benchmark dal primo pod (mpi-worker-0), trattandolo come nodo head.

  1. Genera un file host contenente gli indirizzi IP interni dei worker e copialo nel nodo head:

    kubectl get pods -l app=mpi-worker -o jsonpath='{range .items[*]}{.status.podIP}{"\n"}{end}' > hosts.txt
    kubectl cp hosts.txt mpi-worker-0:/root/hostfile
    
  2. Apri una sessione bash all'interno del pod head:

    kubectl exec -it mpi-worker-0 -- /bin/bash
    
  3. All'interno del pod, crea una directory di test:

    mkdir -p /lustre/test
    
  4. Definisci le variabili di test:

    export NUM_NODES="NUM_NODES"
    export PROCESSES_PER_NODE="PROCESSES_PER_NODE"
    export NUM_PROCESSES=$(( NUM_NODES * PROCESSES_PER_NODE ))
    

    Dove:

    • NUM_NODES: il numero totale di pod worker che partecipano al test.

    • PROCESSES_PER_NODE: il numero di ranghi MPI da eseguire su ogni container. Ti consigliamo di iniziare impostando questo valore in modo che corrisponda al numero di core fisici (o alla metà del numero di vCPU) sulle macchine client. Per i tipi di macchine ad alte prestazioni, l'impostazione di questo valore tra 8 e 16 in genere produce il miglior throughput di rete.

  5. Esegui i comandi di benchmark:

    Throughput di scrittura

    Questo comando scrive continuamente per 60 secondi per testare il throughput di stato stabile di picco. La dimensione del file per attività è impostata su un limite massimo arbitrariamente grande di 50 TiB per mantenere le attività di scrittura fino alla scadenza del timer di 60 secondi.

    mpirun \
      --allow-run-as-root \
      --mca plm_rsh_no_tree_spawn 1 \
      --mca opal_set_max_sys_limits 1 \
      --mca plm_rsh_num_concurrent ${NUM_NODES} \
      --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
      --npernode ${PROCESSES_PER_NODE} \
      --np ${NUM_PROCESSES} \
      --hostfile ~/hostfile \
      /usr/local/bin/ior \
      -a AIO \
      --posix.odirect \
      -F -g -v -w -k \
      -t 4m -b 50t \
      -D 60 \
      -O stoneWallingWearOut=1 \
      -O stoneWallingStatusFile=/lustre/test/ior-easy.stonewall \
      -o /lustre/test/ior_file

    Throughput di lettura

    Questa fase legge esattamente la quantità di dati scritti correttamente durante il test del throughput di scrittura di 60 secondi. Sebbene la dimensione del file per attività (-b) sia impostata su 50 TiB in modo che corrisponda alla geometria della fase di scrittura, il flag -O stoneWallingWearOut=1 indica a IOR di interrompere la lettura non appena raggiunge il limite esatto dei dati registrato nel file di stato di stonewall.

    mpirun \
      --allow-run-as-root \
      --mca plm_rsh_no_tree_spawn 1 \
      --mca opal_set_max_sys_limits 1 \
      --mca plm_rsh_num_concurrent ${NUM_NODES} \
      --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
      --npernode ${PROCESSES_PER_NODE} \
      --np ${NUM_PROCESSES} \
      --hostfile ~/hostfile \
      /usr/local/bin/ior \
      -a AIO \
      --posix.odirect \
      -F -g -v -r -k \
      -t 4m -b 50t \
      -D 60 \
      -O stoneWallingWearOut=1 \
      -O stoneWallingStatusFile=/lustre/test/ior-easy.stonewall \
      -o /lustre/test/ior_file

    IOPS di scrittura

    Questo test utilizza dimensioni di trasferimento ridotte di 4 KiB e dimensioni di file per attività di 8 GiB per misurare il numero massimo di operazioni di input/output al secondo (IOPS) che il file system può gestire.

    mpirun \
      --allow-run-as-root \
      --mca plm_rsh_no_tree_spawn 1 \
      --mca opal_set_max_sys_limits 1 \
      --mca plm_rsh_num_concurrent ${NUM_NODES} \
      --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
      --np ${NUM_PROCESSES} \
      --oversubscribe \
      --map-by node \
      --bind-to socket \
      --hostfile ~/hostfile \
      /usr/local/bin/ior \
      -e \
      -t 4k \
      -b 8g \
      -s 1 \
      -a AIO \
      --posix.odirect \
      --aio.max-pending=256 \
      -w \
      -F \
      -z \
      -Q 1 \
      -G 1745405099 \
      -D 45 \
      -O stoneWallingWearOut=1 \
      -o /lustre/test/ior-random

    IOPS di lettura

    Per evitare la lettura da un file sparso, questo test utilizza due comandi: una scrittura per creare un file solido utilizzando dimensioni di trasferimento di 4 MiB e dimensioni di file per attività di 8 GiB, seguita dal test IOPS di lettura casuale di 4 KiB effettivo.

    1. Crea il file da leggere:

      mpirun \
        --allow-run-as-root \
        --mca plm_rsh_no_tree_spawn 1 \
        --mca opal_set_max_sys_limits 1 \
        --mca plm_rsh_num_concurrent ${NUM_NODES} \
        --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
        --npernode ${PROCESSES_PER_NODE} \
        --np ${NUM_PROCESSES} \
        --oversubscribe \
        --map-by node \
        --bind-to socket \
        --hostfile ~/hostfile \
        /usr/local/bin/ior \
        -a AIO \
        --posix.odirect \
        -w \
        -F \
        -k \
        -t 4m \
        -b 8g \
        -s 1 \
        -Q 1 \
        -G 1745405099 \
        -o /lustre/test/ior_rand_read
    2. Esegui il test di lettura IOR:

      mpirun \
        --allow-run-as-root \
        --mca plm_rsh_no_tree_spawn 1 \
        --mca opal_set_max_sys_limits 1 \
        --mca plm_rsh_num_concurrent ${NUM_NODES} \
        --mca plm_rsh_args "-o StrictHostKeyChecking=no" \
        --oversubscribe \
        --map-by node \
        --bind-to socket \
        --npernode ${PROCESSES_PER_NODE} \
        --np ${NUM_PROCESSES} \
        --hostfile ~/hostfile \
        /usr/local/bin/ior \
        -a AIO \
        --posix.odirect \
        --aio.max-pending 256 \
        -r \
        -F \
        -z \
        -t 4k \
        -b 8g \
        -s 1 \
        -Q 1 \
        -G 1745405099 \
        -D 45 \
        -O stoneWallingWearOut=1 \
        -o /lustre/test/ior_rand_read

    I flag mpirun sono:

    • --mca plm_rsh_no_tree_spawn 1: disabilita la generazione di daemon basata su albero per migliorare l'affidabilità di avvio tra i nodi.
    • --mca opal_set_max_sys_limits 1: tenta automaticamente di impostare i limiti di sistema sui valori massimi consentiti (ad esempio il numero massimo di file aperti).
    • --mca plm_rsh_num_concurrent: imposta il numero massimo di connessioni SSH simultanee che mpirun utilizzerà durante l'avvio dei daemon worker.
    • --mca plm_rsh_args ...: ignora il controllo rigoroso della chiave host per impedire che le richieste SSH interattive blocchino l'avvio del processo MPI.
    • --prefix ...: definisce esplicitamente il percorso di installazione di OpenMPI per Rocky Linux e RHEL in modo che i nodi worker possano trovare il daemon richiesto (orted).
    • --allow-run-as-root: consente a mpirun di essere eseguito come utente root.
    • --oversubscribe: consente a MPI di pianificare più processi su un nodo rispetto ai core fisici disponibili.
    • --map-by node: distribuisce i processi MPI in modo round robin uniformemente tra i nodi disponibili.
    • --bind-to socket: associa i processi MPI ai socket CPU fisici per ottimizzare l'accesso alla memoria e le prestazioni della cache.
    • --npernode: il numero di processi per nodo.
    • --np: il numero totale di processi MPI da avviare.
    • --hostfile: specifica il file contenente l'elenco degli host su cui eseguire.

    I flag ior sono:

    • -a AIO --posix.odirect: utilizza il motore I/O asincrono (AIO) combinato con I/O diretto POSIX. In questo modo viene ignorata la cache della pagina RAM lato client e le scritture simultanee non bloccanti vengono forzate direttamente sui server di archiviazione, assicurando che il benchmark misuri le prestazioni effettive dell'archiviazione di rete anziché i buffer di memoria.
    • --aio.max-pending=256: determina il numero massimo di operazioni di I/O asincrono simultanee in corso per processo.
    • -C: riordina le attività per prestazioni di lettura ottimali.
    • -F: modalità file per processo.
    • -g: utilizza le barriere per separare le fasi di scrittura e lettura del test.
    • -v: output di logging dettagliato.
    • -w / -r: indica a IOR di eseguire il test delle prestazioni di scrittura (-w) o lettura (-r) test delle prestazioni.
    • -k: impedisce a IOR di eliminare il file di test dopo la scrittura, rendendolo disponibile per il test di lettura.
    • -e: esegue un fsync dopo la fase di scrittura per garantire che i dati vengano salvati sulle unità di archiviazione.
    • -z: indica a IOR di eseguire I/O ad accesso casuale anziché accesso sequenziale.
    • -s 1: imposta il numero di segmenti su 1.
    • -Q 1: imposta l'offset attività per nodo, allineando le attività in modo che il benchmark si coordini correttamente su tutti i nodi.
    • -G 1745405099: codifica in modo rigido il timestamp del seme casuale in modo che la fase di lettura generi gli stessi offset di file casuali utilizzati dalla fase di scrittura.
    • -t: imposta la dimensione del trasferimento per ogni operazione di I/O (ad es. 4m per throughput, 4k per IOPS).
    • -b: imposta la dimensione del blocco target per processo (ad es. 50t per il throughput, 8g per IOPS) per assicurarsi che il test non esaurisca i dati del payload durante l'esecuzione a tempo.
    • -D: limita la durata di esecuzione del test a un numero specifico di secondi (ad es. 60 o 45). Questo "stonewalling" termina il benchmark in modo uniforme per acquisire una misurazione di stato stabile effettiva.
    • -O stoneWallingWearOut=1: impone a tutti i thread simultanei di continuare a generare un carico di scrittura continuo per l'intera durata, impedendo ai thread più veloci di completare in anticipo e di ridurre la pressione di rete complessiva.
    • -O stoneWallingStatusFile=<path>: scrive un file di verifica dello stato alla fine della fase di scrittura. La fase di lettura successiva utilizza questo file per leggere solo i blocchi di cui è stato eseguito il commit correttamente, evitando errori di puntatore null durante le letture.
    • -o: il percorso del file di test nel file system Managed Lustre file system.

Visualizza i risultati

Al termine del benchmark, vengono visualizzate le metriche sul rendimento aggregate di tutte le VM o i pod client direttamente nel terminale. Cerca la tabella Risultati nella parte inferiore dell'output per trovare il throughput o le IOPS massime.

Metriche chiave

  • aggregate filesize: la quantità totale di dati scritti o letti durante il test su tutti i client partecipanti.

  • bw(MiB/s) / Max Write / Max Read: la metrica più importante per i test sequenziali. Mostra la larghezza di banda aggregata raggiunta dal file system Managed Lustre.

  • IOPS: la metrica più importante per i test I/O casuali. Mostra il numero massimo di operazioni di input/output al secondo.

Esporta i risultati in un file

Se vuoi analizzare i risultati a livello di programmazione, inserirli in un database o salvarli per un'analisi successiva, puoi indicare a IOR di esportare i dati di riepilogo in formato JSON e CSV anziché stamparli sullo schermo.

Per farlo, aggiungi i flag -O alla fine della stringa di comando ior:

-O summaryFormat=JSON \
-O summaryFile=/lustre/test/perf-results/summary.json \
-O saveRankPerformanceDetailsCSV=/lustre/test/perf-results/details.csv

La directory di output deve esistere nel file system prima di eseguire il benchmark.

Rendimento previsto rispetto a quello reale

Puoi calcolare il throughput massimo matematico del file system in base alla capacità di cui è stato eseguito il provisioning e al livello di prestazioni. Poiché la capacità di archiviazione viene sottoposta a provisioning in gibibyte (GiB) e i livelli sono valutati in tebibyte (TiB), devi prima convertire la capacità:

(Capacity GiB / 1024) * Tier MBps = MBps massimi teorici

Ad esempio, un'istanza 216.000 GiB nel livello 500 MBps per TiB fornisce matematicamente 105.469 MBps di throughput ((216000 / 1024) * 500).

Il throughput massimo osservato sarà sempre limitato dalla capacità di throughput di cui è stato eseguito il provisioning del file system o dai limiti di uscita di rete combinati delle macchine client, a seconda di quale sia inferiore.

Ecco alcuni motivi comuni per cui i numeri di benchmark potrebbero non raggiungere le velocità teoriche:

  • Overhead TCP/IP: l'incapsulamento di rete standard e le intestazioni dei pacchetti consumano circa il 5-10% della larghezza di banda non elaborata. Il massimo matematico include questo overhead, ma il benchmark IOR misura solo il payload non elaborato scritto su disco.

  • Limiti di rete client: le macchine client hanno limiti rigidi di larghezza di banda in uscita. Se utilizzi un numero ridotto di client o nodi o tipi di macchine senza la rete Tier 1 abilitata, i client limiteranno il benchmark prima che il file system Managed Lustre raggiunga il suo limite.

  • Cambio di contesto MPI: se PROCESSES_PER_NODE è impostato su un valore superiore al numero di core fisici sulle macchine client, la contesa della CPU e l'overhead di cambio di contesto ridurranno artificialmente le prestazioni I/O del benchmark.

  • I/O diretto mancante: se il flag --posix.odirect viene omesso, i dati passano attraverso la cache della pagina RAM del client. Ciò introduce colli di bottiglia della memoria e overhead della CPU che mascherano le prestazioni effettive dell'archiviazione di rete.

Libera spazio

Per evitare che al tuo Google Cloud account vengano addebitati costi relativi alle risorse utilizzate in questa pagina, segui questi passaggi:

  1. Elimina i file di test dal volume Managed Lustre:

    kubectl exec mpi-worker-0 -- rm -rf /lustre/test
    
  2. Elimina il cluster GKE:

    gcloud container clusters delete CLUSTER_NAME --zone=ZONE
    

    L'eliminazione del cluster comporta anche l'eliminazione dei pod GKE, del secret Kubernetes e della richiesta di volume permanente.

  3. Se hai eseguito il push dell'immagine Docker di benchmark e non ne hai più bisogno, eliminala dal repository:

    gcloud container images delete gcr.io/PROJECT_ID/lustre-ior-benchmark:latest --force-delete-tags
    
  4. Se hai creato l'istanza Managed Lustre appositamente per questo test e non ne hai più bisogno, eliminala:

    gcloud lustre instances delete INSTANCE_ID --location=LOCATION
    

Risoluzione dei problemi relativi ai colli di bottiglia di benchmarking comuni

Se i risultati del benchmark sono significativamente inferiori al livello di prestazioni di archiviazione previsto, consulta Risoluzione dei problemi relativi ai colli di bottiglia comuni.