Class Rules

java.lang.Object
org.acemq.workloads.rules.Rules

public final class Rules extends Object
The rules that run on every workload, whether or not anybody asked for them.

Validity first

The most valuable rules here are not the ones that judge the broker. They are the ones that decide whether the run measured the broker at all.

A load test that quietly failed to offer the load, or that spent half its time with publishers blocked by a disk alarm, still produces a full set of confident numbers. Those numbers describe something — just not the thing anybody wanted to know. generatorKeptUp() and brokerWasNotBlocked() exist to say so out loud, and they return Severity.INVALID rather than a failure, because blaming the broker for the client's limits is worse than reporting nothing.

Diagnosis, not prescription

Nothing here says "set prefetch to 250". A tool cannot know your handler's processing time, your message sizes, or what else shares the broker, and a confident wrong recommendation gets followed. Every rule reports what it measured and what that rules in or out.

  • Method Details

    • generatorKeptUp

      public static Rule generatorKeptUp()
      Did the generator actually offer the rate it was asked for?

      The single most important check in the set, and the one homemade load tools do not have. If message n was due at t and went out at t+4s, the offered rate was not the configured rate — and every throughput number from the run describes what the client managed, not what the broker could take.

      The cause is usually the client: too few publisher threads, a saturated CPU, or a network the generator shares with something else. It can also be the broker applying back-pressure, which is why this reports the observation rather than the cause.

      Returns:
      the rule
    • brokerWasNotBlocked

      public static Rule brokerWasNotBlocked()
      Was the broker refusing publishes during the run?

      A memory or disk alarm blocks publishing connections. The broker keeps running, the consumers keep working, and the publishers stop — so the run measures how long the alarm lasted rather than how fast the broker is.

      Returns:
      the rule
    • consumersKeptUp

      public static Rule consumersKeptUp()
      Did the consumers keep up with the publishers?

      Not a failure on its own: a run that deliberately fills a queue is doing this on purpose. It is a warning because the end-to-end latency of a growing queue is a function of how long the run lasted, not of how fast the broker is — run it for twice as long and the p99 doubles.

      Returns:
      the rule
    • confirmsWereOn

      public static Rule confirmsWereOn()
      Returns:
      a warning when publisher confirms were off, because the throughput then counts messages handed to a socket rather than messages the broker accepted
    • tailIsNotExtreme

      public static Rule tailIsNotExtreme()
      Returns:
      a warning when the latency distribution has a long tail, which a median hides entirely and which is usually where the interesting behaviour is
    • runWasLongEnough

      public static Rule runWasLongEnough()
      Returns:
      a warning when the run was too short for its numbers to settle. A ten-second run measures JIT compilation and connection setup as much as it measures the broker
    • publishesSucceeded

      public static Rule publishesSucceeded()
      Returns:
      a note when publishes failed outright, which is different from being slow
    • defaults

      public static List<Rule> defaults()
      Returns:
      every rule above, which is what a workload runs unless told otherwise