{
  "id": "P134",
  "slug": "log-sampling",
  "key": "P134-log-sampling",
  "title": "Log sampling",
  "summary": "A stream of requests and four ways to keep one record in ten - every 10th, rotated, random, and every error kept - each answering the same questions about latency, errors and phases, and getting different ones wrong.",
  "entry": "main.eml",
  "ui": "terminal",
  "readme": "# P134 - Log sampling\n\nA stream of 1000 requests, each with a latency and an error flag, and four\nways to keep about one record in ten. Each sample answers the same\nquestions, and gets different ones wrong.\n\n- `main.eml` - the menu, the stream, the four samplers side by side, and\n  the period of the latency pattern\n- `sampling.eml` - the stream, which records each sampler keeps and what\n  each stands for, and the answers from a sample\n\nHow each part works:\n\n- Latency follows a pattern that repeats every 10 requests (it can be\n  set from 1 to 20); requests 400 to 439 are a burst of slow errors, and\n  about 1 in 100 of the rest fail.\n- The samplers:\n  - every 10th keeps requests 10, 20, 30, ...;\n  - rotated moves the kept place along by one every ten requests;\n  - random keeps a record when a mixed number of its index ends in 0;\n  - errors kept keeps every error, and the rest as rotated does.\n- Each kept record counts for 10 requests, except that errors kept counts\n  each error it keeps once, so what a sample stands for is about, not\n  exactly, 1000.\n- As in the corpus case `log-sampling-bias`, every 10th aliases with the\n  pattern: it sees 1 of the 10 phases, and reports a mean latency of 57.6\n  ms where all 1000 give 109.2. It sees period / gcd(period, 10) phases,\n  all of them only when the period shares no factor with 10.\n- No sample finds the maximum unless it keeps that one request; the\n  program names the samplers that miss it.\n\nWhat is checked: menu choices 1 to 4, and a period from 1 to 20. An empty\nanswer cancels.\n\nSessions: `sessions/basic.in` gives:\n- the stream, and the samplers at a period of 10;\n- a period of 7, where every 10th sees every phase, and of 5, where it\n  sees 1.\n\n`sessions/bad-input.in` gives:\n- menu choices 0 and x;\n- periods: a cancel, 0, 21 and x, then 1 and 20, with the samplers.\n\nBuilt on the verified corpus case `log-sampling-bias` (two samplers that\nkeep as many records and answer different questions).\n",
  "modules": [
    {
      "name": "main.eml",
      "eml": "# P134 log sampling: the stream, four samplers answering the same questions\n# side by side, and the period of the latency pattern.\nimport sampling\n\ndef plain(s):\n    0 => i\n    len(s) => j\n    while i < j and s[i] == \" \":\n        i + 1 => i\n    while j > i and s[j - 1] == \" \":\n        j - 1 => j\n    return s[i:j]\n\ndef pad(s, n):\n    s => out\n    while len(out) < n:\n        out + \" \" => out\n    return out\n\ndef lpad(s, n):\n    s => out\n    while len(out) < n:\n        \" \" + out => out\n    return out\n\ndef tenths_text(t):\n    return str(int(t / 10)) + \".\" + str(t % 10)\n\ndef rate_text(errs, total):\n    # errors as a percentage, one decimal, rounded half up\n    int((2000 * errs + total) / (2 * total)) => t\n    while t * 2 * total > 2000 * errs + total:\n        t - 1 => t\n    while (t + 1) * 2 * total <= 2000 * errs + total:\n        t + 1 => t\n    return str(int(t / 10)) + \".\" + str(t % 10) + \"%\"\n\ndef show(period):\n    sampling.stream(1000, period) => rs\n    \"1000 requests; the first 12 (latency in ms, E for an error):\" ^0\n    \"\" => line\n    for k in [0:11]:\n        rs[k] => r\n        if line != \"\":\n            line + \"  \" => line\n        line + str(r[1]) => line\n        if r[2]:\n            line + \"E\" => line\n    (\"  \" + line) ^0\n    (\"Latency follows a pattern that repeats every \" + str(period) + \" requests; requests 400 to 439 are a burst of slow errors, and about 1 in 100 of the rest fail.\") ^0\n\ndef compare(period):\n    sampling.stream(1000, period) => rs\n    [sampling.truth(rs, period)] => cols\n    for plan in sampling.samplers():\n        cols + [sampling.answers(sampling.sample(rs, plan), period)] => cols\n    (\"The same questions, from all 1000 and from each sample (period \" + str(period) + \"):\") ^0\n    \"  question        all    every 10th    rotated     random  errors kept\" ^0\n    [12, 7, 14, 11, 11, 13] => w\n    [\"records kept\", \"stand for\", \"mean latency\", \"p90 latency\", \"max latency\", \"error rate\", \"phases seen\"] => qs\n    for q in [0:6]:\n        \"  \" + pad(qs[q], 12) => line\n        for c in [0:4]:\n            cols[c] => a\n            if q == 0:\n                str(a[0]) => v\n            elif q == 1:\n                str(a[1]) => v\n            elif q == 2:\n                tenths_text(a[2]) => v\n            elif q == 3:\n                str(a[3]) => v\n            elif q == 4:\n                str(a[4]) => v\n            elif q == 5:\n                rate_text(a[5], a[1]) => v\n            else:\n                str(a[6]) + \" of \" + str(period) => v\n            line + lpad(v, w[c + 1]) => line\n        line ^0\n    \"  Each kept record counts for 10 requests, except that errors kept counts each error it keeps once.\" ^0\n    cols[1] => e\n    if e[6] < period:\n        (\"Every 10th sees \" + str(e[6]) + \" of the \" + str(period) + \" phases of the pattern, and reports them as the whole: the pattern's period shares a factor with 10.\") ^0\n    [] => missed\n    for c in [1:4]:\n        if cols[c][4] != cols[0][4]:\n            missed + [sampling.samplers()[c - 1]] => missed\n    if len(missed) > 0:\n        \"\" => who\n        for k in [0:len(missed) - 1]:\n            if k > 0 and k == len(missed) - 1:\n                who + \" and \" => who\n            elif k > 0:\n                who + \", \" => who\n            who + missed[k] => who\n        (\"The maximum, \" + str(cols[0][4]) + \" ms, is missed by \" + who + \": a sample finds it only by keeping that one request.\") ^0\n\ndef set_period(period):\n    plain(input(\"period of the latency pattern (1 to 20)> \")) => t\n    if t == \"\":\n        \"Cancelled.\" ^0\n        return period\n    if len(t) > 2:\n        \"Type a whole number from 1 to 20.\" ^0\n        return period\n    for c in t:\n        if c < \"0\" or c > \"9\":\n            \"Type a whole number from 1 to 20.\" ^0\n            return period\n    if int(t) < 1 or int(t) > 20:\n        \"Type a whole number from 1 to 20.\" ^0\n        return period\n    (\"The latency pattern now repeats every \" + t + \" requests.\") ^0\n    return int(t)\n\n10 => period\n\n\"== Log sampling ==\" ^0\n\"A stream of requests and four ways to keep about one record in ten: which questions can each sample still answer?\" ^0\nTrue => running\nwhile running:\n    \"\" ^0\n    \"1) the stream  2) compare samplers  3) period  4) quit\" ^0\n    plain(input(\"choice> \")) => choice\n    if choice == \"1\":\n        show(period)\n    elif choice == \"2\":\n        compare(period)\n    elif choice == \"3\":\n        set_period(period) => period\n    elif choice == \"4\":\n        False => running\n    else:\n        \"Pick a number from 1 to 4.\" ^0\n\"Bye.\" ^0\n",
      "python": "import sampling\n\ndef plain(s):\n    i = 0\n    j = len(s)\n    while i < j and s[i] == \" \":\n        i = i + 1\n    while j > i and s[j - 1] == \" \":\n        j = j - 1\n    return s[i:j]\n\ndef pad(s, n):\n    out = s\n    while len(out) < n:\n        out = out + \" \"\n    return out\n\ndef lpad(s, n):\n    out = s\n    while len(out) < n:\n        out = \" \" + out\n    return out\n\ndef tenths_text(t):\n    return str(int(t / 10)) + \".\" + str(t % 10)\n\ndef rate_text(errs, total):\n    t = int((2000 * errs + total) / (2 * total))\n    while t * 2 * total > 2000 * errs + total:\n        t = t - 1\n    while (t + 1) * 2 * total <= 2000 * errs + total:\n        t = t + 1\n    return str(int(t / 10)) + \".\" + str(t % 10) + \"%\"\n\ndef show(period):\n    rs = sampling.stream(1000, period)\n    print(\"1000 requests; the first 12 (latency in ms, E for an error):\")\n    line = \"\"\n    for k in range(0, 12):\n        r = rs[k]\n        if line != \"\":\n            line = line + \"  \"\n        line = line + str(r[1])\n        if r[2]:\n            line = line + \"E\"\n    print(\"  \" + line)\n    print(\"Latency follows a pattern that repeats every \" + str(period) + \" requests; requests 400 to 439 are a burst of slow errors, and about 1 in 100 of the rest fail.\")\n\ndef compare(period):\n    rs = sampling.stream(1000, period)\n    cols = [sampling.truth(rs, period)]\n    for plan in sampling.samplers():\n        cols = cols + [sampling.answers(sampling.sample(rs, plan), period)]\n    print(\"The same questions, from all 1000 and from each sample (period \" + str(period) + \"):\")\n    print(\"  question        all    every 10th    rotated     random  errors kept\")\n    w = [12, 7, 14, 11, 11, 13]\n    qs = [\"records kept\", \"stand for\", \"mean latency\", \"p90 latency\", \"max latency\", \"error rate\", \"phases seen\"]\n    for q in range(0, 7):\n        line = \"  \" + pad(qs[q], 12)\n        for c in range(0, 5):\n            a = cols[c]\n            if q == 0:\n                v = str(a[0])\n            elif q == 1:\n                v = str(a[1])\n            elif q == 2:\n                v = tenths_text(a[2])\n            elif q == 3:\n                v = str(a[3])\n            elif q == 4:\n                v = str(a[4])\n            elif q == 5:\n                v = rate_text(a[5], a[1])\n            else:\n                v = str(a[6]) + \" of \" + str(period)\n            line = line + lpad(v, w[c + 1])\n        print(line)\n    print(\"  Each kept record counts for 10 requests, except that errors kept counts each error it keeps once.\")\n    e = cols[1]\n    if e[6] < period:\n        print(\"Every 10th sees \" + str(e[6]) + \" of the \" + str(period) + \" phases of the pattern, and reports them as the whole: the pattern's period shares a factor with 10.\")\n    missed = []\n    for c in range(1, 5):\n        if cols[c][4] != cols[0][4]:\n            missed = missed + [sampling.samplers()[c - 1]]\n    if len(missed) > 0:\n        who = \"\"\n        for k in range(0, len(missed)):\n            if k > 0 and k == len(missed) - 1:\n                who = who + \" and \"\n            elif k > 0:\n                who = who + \", \"\n            who = who + missed[k]\n        print(\"The maximum, \" + str(cols[0][4]) + \" ms, is missed by \" + who + \": a sample finds it only by keeping that one request.\")\n\ndef set_period(period):\n    t = plain(input(\"period of the latency pattern (1 to 20)> \"))\n    if t == \"\":\n        print(\"Cancelled.\")\n        return period\n    if len(t) > 2:\n        print(\"Type a whole number from 1 to 20.\")\n        return period\n    for c in t:\n        if c < \"0\" or c > \"9\":\n            print(\"Type a whole number from 1 to 20.\")\n            return period\n    if int(t) < 1 or int(t) > 20:\n        print(\"Type a whole number from 1 to 20.\")\n        return period\n    print(\"The latency pattern now repeats every \" + t + \" requests.\")\n    return int(t)\n\nperiod = 10\nprint(\"== Log sampling ==\")\nprint(\"A stream of requests and four ways to keep about one record in ten: which questions can each sample still answer?\")\nrunning = True\nwhile running:\n    print(\"\")\n    print(\"1) the stream  2) compare samplers  3) period  4) quit\")\n    choice = plain(input(\"choice> \"))\n    if choice == \"1\":\n        show(period)\n    elif choice == \"2\":\n        compare(period)\n    elif choice == \"3\":\n        period = set_period(period)\n    elif choice == \"4\":\n        running = False\n    else:\n        print(\"Pick a number from 1 to 4.\")\nprint(\"Bye.\")\n"
    },
    {
      "name": "sampling.eml",
      "eml": "# P134 log sampling - a stream of requests, each with a latency and an\n# error flag, and four ways to keep about one record in ten. As in the\n# corpus case log-sampling-bias, the samplers keep about as many records\n# and answer different questions: keeping every 10th aliases with a\n# latency pattern whose period shares a factor with 10, and a sample that\n# keeps every error has to weigh the rest back up.\n#\n# A record is [index, latency in ms, error]. The latency follows a pattern\n# of the given period; requests 400 to 439 are an error burst, slow too.\n\ndef mix(i, salt):\n    i * 7919 + salt * 104729 + 12345 => x\n    for k in [1:3]:\n        (x * x + 7) % 1000000007 => x\n    return x % 1000000\n\ndef stream(n, period):\n    [] => out\n    for i in [1:n]:\n        40 + 12 * (i % period) + mix(i, 1) % 5 => lat\n        False => err\n        if i >= 400 and i <= 439:\n            True => err\n            400 + mix(i, 2) % 50 => lat\n        elif mix(i, 3) % 100 == 0:\n            True => err\n        out + [[i, lat, err]] => out\n    return out\n\ndef samplers():\n    return [\"every 10th\", \"rotated\", \"random\", \"errors kept\"]\n\ndef keep(plan, r):\n    # [kept, weight]: how many records of the stream this one stands for\n    r[0] => i\n    if plan == \"every 10th\":\n        return [i % 10 == 0, 10]\n    if plan == \"rotated\":\n        return [i % 10 == int(i / 10) % 10, 10]\n    if plan == \"random\":\n        return [mix(i, 5) % 10 == 0, 10]\n    # errors kept: every error, and the rest as rotated keeps them\n    if r[2]:\n        return [True, 1]\n    return [i % 10 == int(i / 10) % 10, 10]\n\ndef sample(records, plan):\n    # [record, weight] for the records kept\n    [] => out\n    for r in records:\n        keep(plan, r) => k\n        if k[0]:\n            out + [[r, k[1]]] => out\n    return out\n\ndef answers(ws, period):\n    # [records kept, records they stand for, mean latency in tenths, p90\n    #  latency, max latency, errors stood for, phases seen]\n    0 => n\n    0 => total\n    0 => lat\n    0 => errs\n    0 => most\n    {} => phases\n    for p in ws:\n        n + 1 => n\n        total + p[1] => total\n        lat + p[0][1] * p[1] => lat\n        if p[0][2]:\n            errs + p[1] => errs\n        if p[0][1] > most:\n            p[0][1] => most\n        1 => phases[p[0][0] % period]\n    0 => mean\n    0 => p90\n    if total > 0:\n        int((20 * lat + total) / (2 * total)) => mean\n        while mean * 2 * total > 20 * lat + total:\n            mean - 1 => mean\n        while (mean + 1) * 2 * total <= 20 * lat + total:\n            mean + 1 => mean\n        # the weight at each latency, then the smallest latency at or below\n        # which nine tenths of the weight lies\n        {} => at\n        for p in ws:\n            if p[0][1] in at:\n                at[p[0][1]] + p[1] => at[p[0][1]]\n            else:\n                p[1] => at[p[0][1]]\n        0 => run\n        False => found\n        for v in [0:most]:\n            if not found and v in at:\n                run + at[v] => run\n                if run * 10 >= total * 9:\n                    v => p90\n                    True => found\n    return [n, total, mean, p90, most, errs, len(phases)]\n\ndef truth(records, period):\n    [] => ws\n    for r in records:\n        ws + [[r, 1]] => ws\n    return answers(ws, period)\n",
      "python": "def mix(i, salt):\n    x = i * 7919 + salt * 104729 + 12345\n    for k in range(1, 4):\n        x = (x * x + 7) % 1000000007\n    return x % 1000000\n\ndef stream(n, period):\n    out = []\n    for i in range(1, n+1):\n        lat = 40 + 12 * (i % period) + mix(i, 1) % 5\n        err = False\n        if i >= 400 and i <= 439:\n            err = True\n            lat = 400 + mix(i, 2) % 50\n        elif mix(i, 3) % 100 == 0:\n            err = True\n        out = out + [[i, lat, err]]\n    return out\n\ndef samplers():\n    return [\"every 10th\", \"rotated\", \"random\", \"errors kept\"]\n\ndef keep(plan, r):\n    i = r[0]\n    if plan == \"every 10th\":\n        return [i % 10 == 0, 10]\n    if plan == \"rotated\":\n        return [i % 10 == int(i / 10) % 10, 10]\n    if plan == \"random\":\n        return [mix(i, 5) % 10 == 0, 10]\n    if r[2]:\n        return [True, 1]\n    return [i % 10 == int(i / 10) % 10, 10]\n\ndef sample(records, plan):\n    out = []\n    for r in records:\n        k = keep(plan, r)\n        if k[0]:\n            out = out + [[r, k[1]]]\n    return out\n\ndef answers(ws, period):\n    n = 0\n    total = 0\n    lat = 0\n    errs = 0\n    most = 0\n    phases = {}\n    for p in ws:\n        n = n + 1\n        total = total + p[1]\n        lat = lat + p[0][1] * p[1]\n        if p[0][2]:\n            errs = errs + p[1]\n        if p[0][1] > most:\n            most = p[0][1]\n        phases[p[0][0] % period] = 1\n    mean = 0\n    p90 = 0\n    if total > 0:\n        mean = int((20 * lat + total) / (2 * total))\n        while mean * 2 * total > 20 * lat + total:\n            mean = mean - 1\n        while (mean + 1) * 2 * total <= 20 * lat + total:\n            mean = mean + 1\n        at = {}\n        for p in ws:\n            if p[0][1] in at:\n                at[p[0][1]] = at[p[0][1]] + p[1]\n            else:\n                at[p[0][1]] = p[1]\n        run = 0\n        found = False\n        for v in range(0, most+1):\n            if not found and v in at:\n                run = run + at[v]\n                if run * 10 >= total * 9:\n                    p90 = v\n                    found = True\n    return [n, total, mean, p90, most, errs, len(phases)]\n\ndef truth(records, period):\n    ws = []\n    for r in records:\n        ws = ws + [[r, 1]]\n    return answers(ws, period)\n"
    }
  ],
  "sessions": [
    {
      "name": "bad-input",
      "input": "0\nx\n3\n\n3\n0\n3\n21\n3\nx\n3\n1\n2\n3\n20\n2\n4\n",
      "screen": "== Log sampling ==\nA stream of requests and four ways to keep about one record in ten: which questions can each sample still answer?\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 0\nPick a number from 1 to 4.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> x\nPick a number from 1 to 4.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 3\nperiod of the latency pattern (1 to 20)> \nCancelled.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 3\nperiod of the latency pattern (1 to 20)> 0\nType a whole number from 1 to 20.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 3\nperiod of the latency pattern (1 to 20)> 21\nType a whole number from 1 to 20.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 3\nperiod of the latency pattern (1 to 20)> x\nType a whole number from 1 to 20.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 3\nperiod of the latency pattern (1 to 20)> 1\nThe latency pattern now repeats every 1 requests.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 2\nThe same questions, from all 1000 and from each sample (period 1):\n  question        all    every 10th    rotated     random  errors kept\n  records kept   1000           100        100        101          142\n  stand for      1000          1000       1000       1010          997\n  mean latency   57.3          57.6       57.4       56.8         57.3\n  p90 latency      44            44         44         44           44\n  max latency     449           445        449        428          449\n  error rate     4.7%          4.0%       5.0%       4.0%         4.7%\n  phases seen  1 of 1        1 of 1     1 of 1     1 of 1       1 of 1\n  Each kept record counts for 10 requests, except that errors kept counts each error it keeps once.\nThe maximum, 449 ms, is missed by every 10th and random: a sample finds it only by keeping that one request.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 3\nperiod of the latency pattern (1 to 20)> 20\nThe latency pattern now repeats every 20 requests.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 2\nThe same questions, from all 1000 and from each sample (period 20):\n  question        all    every 10th    rotated     random  errors kept\n  records kept   1000           100        100        101          142\n  stand for      1000          1000       1000       1010          997\n  mean latency  166.8         115.2      168.3      174.1        167.4\n  p90 latency     259           164        270        260          270\n  max latency     449           445        449        428          449\n  error rate     4.7%          4.0%       5.0%       4.0%         4.7%\n  phases seen 20 of 20       2 of 20   10 of 20   20 of 20     20 of 20\n  Each kept record counts for 10 requests, except that errors kept counts each error it keeps once.\nEvery 10th sees 2 of the 20 phases of the pattern, and reports them as the whole: the pattern's period shares a factor with 10.\nThe maximum, 449 ms, is missed by every 10th and random: a sample finds it only by keeping that one request.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 4\nBye.\n",
      "interpreter": "equal"
    },
    {
      "name": "basic",
      "input": "1\n2\n3\n7\n2\n3\n5\n2\n4\n",
      "screen": "== Log sampling ==\nA stream of requests and four ways to keep about one record in ten: which questions can each sample still answer?\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 1\n1000 requests; the first 12 (latency in ms, E for an error):\n  52  64  76  90  100  115  126  137  151  43  56  68\nLatency follows a pattern that repeats every 10 requests; requests 400 to 439 are a burst of slow errors, and about 1 in 100 of the rest fail.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 2\nThe same questions, from all 1000 and from each sample (period 10):\n  question        all    every 10th    rotated     random  errors kept\n  records kept   1000           100        100        101          142\n  stand for      1000          1000       1000       1010          997\n  mean latency  109.2          57.6      110.7      112.3        110.3\n  p90 latency     149            44        150        148          150\n  max latency     449           445        449        428          449\n  error rate     4.7%          4.0%       5.0%       4.0%         4.7%\n  phases seen 10 of 10       1 of 10   10 of 10   10 of 10     10 of 10\n  Each kept record counts for 10 requests, except that errors kept counts each error it keeps once.\nEvery 10th sees 1 of the 10 phases of the pattern, and reports them as the whole: the pattern's period shares a factor with 10.\nThe maximum, 449 ms, is missed by every 10th and random: a sample finds it only by keeping that one request.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 3\nperiod of the latency pattern (1 to 20)> 7\nThe latency pattern now repeats every 7 requests.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 2\nThe same questions, from all 1000 and from each sample (period 7):\n  question        all    every 10th    rotated     random  errors kept\n  records kept   1000           100        100        101          142\n  stand for      1000          1000       1000       1010          997\n  mean latency   91.9          93.0       92.3       89.7         91.8\n  p90 latency     114           114        113        114          113\n  max latency     449           445        449        428          449\n  error rate     4.7%          4.0%       5.0%       4.0%         4.7%\n  phases seen  7 of 7        7 of 7     7 of 7     7 of 7       7 of 7\n  Each kept record counts for 10 requests, except that errors kept counts each error it keeps once.\nThe maximum, 449 ms, is missed by every 10th and random: a sample finds it only by keeping that one request.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 3\nperiod of the latency pattern (1 to 20)> 5\nThe latency pattern now repeats every 5 requests.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 2\nThe same questions, from all 1000 and from each sample (period 5):\n  question        all    every 10th    rotated     random  errors kept\n  records kept   1000           100        100        101          142\n  stand for      1000          1000       1000       1010          997\n  mean latency   80.4          57.6       80.7       79.6         80.5\n  p90 latency      91            44         90         90           91\n  max latency     449           445        449        428          449\n  error rate     4.7%          4.0%       5.0%       4.0%         4.7%\n  phases seen  5 of 5        1 of 5     5 of 5     5 of 5       5 of 5\n  Each kept record counts for 10 requests, except that errors kept counts each error it keeps once.\nEvery 10th sees 1 of the 5 phases of the pattern, and reports them as the whole: the pattern's period shares a factor with 10.\nThe maximum, 449 ms, is missed by every 10th and random: a sample finds it only by keeping that one request.\n\n1) the stream  2) compare samplers  3) period  4) quit\nchoice> 4\nBye.\n",
      "interpreter": "equal"
    }
  ],
  "builtOn": [
    {
      "slug": "log-sampling-bias",
      "caseId": "240-log-sampling-bias",
      "title": "Same number of records, different questions"
    }
  ],
  "updated": "2026-10-17"
}
