Skip to content

Medir bloqueio e perda ​

Quando o sistema tem capacidade limitada, parte da demanda não é atendida. Medir esse "quanto" é tão importante quanto medir o tempo de resposta — e é a métrica que mais some dos relatórios.

A métrica básica ​

A fração de tempo em que o sistema está cheio:

P{#Vagas = 0} * 100

P{ } mede quanto tempo a condição se sustentou, então isso dá a porcentagem do tempo em que não havia vaga. Veja Médias e probabilidades.

Bloqueio ou perda? ​

Duas coisas diferentes acontecem quando o sistema enche, e a escolha muda o modelo.

BloqueioPerda
O que acontecequem chega espera do lado de foraquem chega vai embora
Exemplolinha de produção que paraligação que cai por falta de linha
Como modelara chegada consome uma vagadois caminhos: aceita ou recusa

Bloqueio ​

O mais simples: a transição de chegada consome uma ficha de Vagas. Sem vaga, ela não dispara — a demanda fica represada até alguém sair.

Perda ​

Quando quem não consegue entrar vai embora, o modelo precisa mostrar isso. A chegada sempre acontece, e dois caminhos imediatos decidem o destino:

  • Aceita — precisa de uma vaga, e leva a ficha para a fila
  • Recusa — tem um arco inibidor em Vagas, então só dispara quando não há vaga, e leva a ficha para Perdidos
json
{
  "modelName": "Fila com recusa de clientes",
  "definitions": [
    {
      "name": "TEMPO_ENTRE_CHEGADAS",
      "type": "DOUBLE",
      "value": "10"
    },
    {
      "name": "TEMPO_DE_ATENDIMENTO",
      "type": "DOUBLE",
      "value": "5"
    },
    {
      "name": "VAGAS",
      "type": "INTEGER",
      "value": "3"
    },
    {
      "name": "PASSAGEM",
      "type": "DOUBLE",
      "value": "0.0001"
    }
  ],
  "places": [
    {
      "name": "Vagas",
      "initialMarking": 3,
      "stringMarking": "VAGAS",
      "initialStringMarking": "VAGAS"
    },
    {
      "name": "Fila",
      "initialMarking": 0,
      "stringMarking": "0",
      "initialStringMarking": "0"
    },
    {
      "name": "Atendente",
      "initialMarking": 1,
      "stringMarking": "1",
      "initialStringMarking": "1"
    },
    {
      "name": "EmAtendimento",
      "initialMarking": 0,
      "stringMarking": "0",
      "initialStringMarking": "0"
    },
    {
      "name": "Chegando",
      "initialMarking": 0,
      "stringMarking": "0",
      "initialStringMarking": "0"
    },
    {
      "name": "Perdidos",
      "initialMarking": 0,
      "stringMarking": "0",
      "initialStringMarking": "0"
    }
  ],
  "rewardMeasures": [
    {
      "name": "cheio_pct",
      "expression": "P{#Vagas = 0} * 100"
    },
    {
      "name": "taxa_de_perda",
      "expression": "E{#Perdidos} / PASSAGEM"
    },
    {
      "name": "vazao",
      "expression": "E{#EmAtendimento} / TEMPO_DE_ATENDIMENTO"
    }
  ],
  "transitions": [
    {
      "name": "Chegada",
      "type": "TIMED",
      "firingPolicy": "SINGLE_SERVER",
      "raceType": "RACE_WITH_ENABLING_MEMORY",
      "priority": 1,
      "distribution": {
        "type": "exponential",
        "parameters": {
          "Mean delay": "TEMPO_ENTRE_CHEGADAS"
        }
      },
      "inputArcs": [],
      "outputArcs": [
        {
          "type": "OUTPUT",
          "place": "Chegando",
          "multiplicity": 1
        }
      ],
      "inhibitorArcs": []
    },
    {
      "name": "Inicio",
      "type": "IMMEDIATE",
      "firingPolicy": "SINGLE_SERVER",
      "raceType": "RACE_WITH_ENABLING_MEMORY",
      "priority": 1,
      "weight": 1,
      "inputArcs": [
        {
          "type": "INPUT",
          "place": "Fila",
          "multiplicity": 1
        },
        {
          "type": "INPUT",
          "place": "Atendente",
          "multiplicity": 1
        }
      ],
      "outputArcs": [
        {
          "type": "OUTPUT",
          "place": "EmAtendimento",
          "multiplicity": 1
        }
      ],
      "inhibitorArcs": []
    },
    {
      "name": "Fim",
      "type": "TIMED",
      "firingPolicy": "INFINITY_SERVER",
      "raceType": "RACE_WITH_ENABLING_MEMORY",
      "priority": 1,
      "distribution": {
        "type": "exponential",
        "parameters": {
          "Mean delay": "TEMPO_DE_ATENDIMENTO"
        }
      },
      "inputArcs": [
        {
          "type": "INPUT",
          "place": "EmAtendimento",
          "multiplicity": 1
        }
      ],
      "outputArcs": [
        {
          "type": "OUTPUT",
          "place": "Atendente",
          "multiplicity": 1
        },
        {
          "type": "OUTPUT",
          "place": "Vagas",
          "multiplicity": 1
        }
      ],
      "inhibitorArcs": []
    },
    {
      "name": "Aceita",
      "type": "IMMEDIATE",
      "firingPolicy": "SINGLE_SERVER",
      "raceType": "RACE_WITH_ENABLING_MEMORY",
      "priority": 1,
      "weight": 1,
      "inputArcs": [
        {
          "type": "INPUT",
          "place": "Chegando",
          "multiplicity": 1
        },
        {
          "type": "INPUT",
          "place": "Vagas",
          "multiplicity": 1
        }
      ],
      "outputArcs": [
        {
          "type": "OUTPUT",
          "place": "Fila",
          "multiplicity": 1
        }
      ],
      "inhibitorArcs": []
    },
    {
      "name": "Recusa",
      "type": "IMMEDIATE",
      "firingPolicy": "SINGLE_SERVER",
      "raceType": "RACE_WITH_ENABLING_MEMORY",
      "priority": 1,
      "weight": 1,
      "inputArcs": [
        {
          "type": "INPUT",
          "place": "Chegando",
          "multiplicity": 1
        }
      ],
      "outputArcs": [
        {
          "type": "OUTPUT",
          "place": "Perdidos",
          "multiplicity": 1
        }
      ],
      "inhibitorArcs": [
        {
          "type": "INHIBITOR",
          "place": "Vagas",
          "multiplicity": 1
        }
      ]
    },
    {
      "name": "Descarta",
      "type": "TIMED",
      "firingPolicy": "INFINITY_SERVER",
      "raceType": "RACE_WITH_ENABLING_MEMORY",
      "priority": 1,
      "distribution": {
        "type": "exponential",
        "parameters": {
          "Mean delay": "PASSAGEM"
        }
      },
      "inputArcs": [
        {
          "type": "INPUT",
          "place": "Perdidos",
          "multiplicity": 1
        }
      ],
      "outputArcs": [],
      "inhibitorArcs": []
    }
  ]
}

Perdidos precisa ser esvaziado, senão acumula para sempre. A transição Descarta faz isso, e a passagem por ali permite contar a taxa de perda:

E{#Perdidos} / PASSAGEM

Conferindo se o modelo fecha ​

Uma verificação que sempre vale a pena: o que entra tem que ser igual ao que sai mais o que se perdeu.

GrandezaValor
Chegadas0,1000
Vazão (atendidos)0,0933
Taxa de perda0,0067
Vazão + perda0,1000 ✓

Se essa conta não fechar, há um caminho no modelo por onde fichas somem ou aparecem. É a checagem mais rápida para achar erro de arco.

As duas medidas concordam ​

No mesmo modelo, a fração perdida e a fração de tempo cheio dão o mesmo número:

MedidaValor
Tempo com o sistema cheio6,66%
Fração das chegadas perdidas6,67%

Faz sentido: se as chegadas acontecem ao acaso, a chance de uma delas encontrar o sistema cheio é igual à fração de tempo em que ele fica cheio.

Aproveite isso

Se as chegadas são exponenciais, você não precisa modelar a perda explicitamente para saber quanto se perde — P{#Vagas = 0} já responde. O modelo de perda vale a pena quando você quer contar os perdidos, tratá-los de outra forma, ou quando as chegadas não são ao acaso.

Leia junto com o tempo de resposta ​

Esta é a razão de ser da página.

Reduzir a capacidade melhora o tempo de resposta — quem está dentro espera menos, porque há menos gente. Mas piora o serviço, porque mais gente fica de fora.

VagasTempo cheioVazãoTempo de resposta
133,4%0,0675,0 min
36,7%0,0937,9 min
100,0%0,10010,0 min

Com uma vaga só, o tempo de resposta é o melhor da tabela — e o sistema está recusando um terço da demanda.

Nunca apresente tempo de resposta sozinho

Num sistema com capacidade limitada, tempo de resposta sem a porcentagem de recusa ao lado é uma métrica enganosa. As duas juntas contam a história; qualquer uma sozinha conta metade dela.