[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6D24S245P7Q5380331PC75B":3,"skill-same:01M6D24S245P7Q5380331PC75B":64},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":23,"publishedAt":36,"linkOnly":37,"markdownContent":38,"markdownBody":39,"frontMatter":40,"refName":41,"commitSha":42,"skillDirectory":43,"forksCount":44,"repositoryHtmlUrl":45,"repositoryHomepageUrl":46,"ownerHtmlUrl":47,"ownerBlogUrl":46,"ownerDescription":48,"updatedAt":49,"install":50,"resources":63},"01M6D24S245P7Q5380331PC75B","performance",null,"Performance work that is measured: defining the metric and the workload, a baseline, profiling to find where time goes, changing one thing at a time, comparing with statistics, percentiles over averages, latency versus throughput, budgets, and reporting numbers with their conditions. The method and which skill holds each part. Read before any optimisation or performance investigation.","enowdev\u002Fenowxcli","enowdev","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F179420349?v=4","01M6D1MVX2KC0X3Z9NESE7P22K","Enow Dev.","01M6D1MW1FMZGBDKWAJY4GQX81",67,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fperformance\u002FSKILL.md",[18],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发","SCENARIO","使用场景",[5,24,25,26,27,28,29,30,31,32,33,34,35],"performance investigation","workload","reporting","baseline","investigation","profiling","work","find","read","time","statistics","latency","2026-11-10 10:12:30",false,"---\nname: performance\ndescription: \"Performance work that is measured: defining the metric and the workload, a baseline, profiling to find where time goes, changing one thing at a time, comparing with statistics, percentiles over averages, latency versus throughput, budgets, and reporting numbers with their conditions. The method and which skill holds each part. Read before any optimisation or performance investigation.\"\n---\n\n# Performance work, measured\n\nPerformance work done by default is a guess: code rewritten because it\nlooked slow, a cache put in front of everything, a loop micro-optimised\nthat takes 1% of the time, \"3x faster\" from one run on a laptop, an average\nthat hides a two-second tail, and a fix that quietly returns wrong answers.\nThis skill is the method an experienced engineer follows instead: define the\nmetric and the workload, measure a baseline, find where the time goes,\nchange one thing, compare with statistics, and report the numbers with the\nconditions they were measured under. Each step names the skill that holds\nthe detail.\n\n## 1. Define the problem as a number\n\nBefore reading any code, write down three things.\n\n- **The metric**, the one a user or an operator feels:\n\n  | Complaint | Metric |\n  |---|---|\n  | The page is slow | LCP, INP and CLS at p75 of real visits (`frontend-performance`) |\n  | The API is slow | latency p95 and p99 per endpoint, at a stated request rate |\n  | The job takes all night | wall-clock duration for a stated input size |\n  | We need more servers | throughput per instance at the latency target |\n  | It keeps getting killed | peak resident memory (`performance-memory`) |\n  | The download is huge | bundle, binary or payload size, compressed |\n  | The first request is slow | cold start, measured apart from warm requests |\n\n- **The target**: a number with its percentile and its condition. \"p95\n  under 300ms at 200 requests per second with a 50,000-order account\", not\n  \"faster\". It comes from an SLO, a budget, a product requirement or the\n  owner; if nobody has one, propose one and say it is proposed.\n- **The workload**: realistic data sizes (production row counts, the\n  largest customer, not a seed of 20 rows), realistic input shapes and\n  their distribution, the concurrency, and whether caches are warm or\n  cold. Query plans, hit rates and an algorithm's cost all change with\n  size; a toy workload optimises the wrong thing.\n\nDone means: the target is met on that workload, and the tests still pass.\n\n## 2. Measure a baseline first\n\n- Measure before changing anything, with the exact command, script or\n  query that will measure the after. Keep the raw output, not only a\n  summary, and the commit hash it ran on.\n- Write the environment down: machine or instance size (CPU model, cores,\n  memory), OS, runtime and compiler versions, build mode, configuration\n  flags, data size, and anything else running at the time.\n- Optimised builds only. A debug build, a framework's development mode\n  (React, Next.js, Django with `DEBUG`, Rails), Go's race detector (2 to\n  20x slower by its own documentation) or a sanitiser changes the numbers\n  by multiples and moves the hot spots.\n- Run the baseline three separate times. If the runs differ by as much as\n  the improvement you hope for, reduce the noise first\n  (`performance-benchmarks`).\n- Before and after on the same machine in the same session. Laptops\n  throttle on battery and when hot; shared CI runners vary between jobs.\n- Capture a profile with the baseline (`performance-profiling`): it is the\n  before half of the comparison later.\n\n## 3. Find where the time goes\n\nThe hot path is the one the measurement shows, not the one that looks slow.\n\n- Start coarse and split the total into parts. For a request: tracing\n  spans (database, external calls, serialisation, CPU, waiting for a pool).\n  For a page: the browser's Performance panel. For a command: `time`;\n  `real` far above `user + sys` means waiting (I\u002FO, network, locks,\n  sleeps), `user + sys` above `real` means several cores worked.\n- Then profile the biggest part (`performance-profiling`): a CPU profile\n  when a core is busy, an off-CPU or wall-clock view when it waits, a heap\n  profile for memory, `EXPLAIN` for a query (`database-queries`).\n- Amdahl's law sets the ceiling. A part taking a share `p` of the time,\n  made `s` times faster, makes the whole `1 \u002F ((1 - p) + p \u002F s)` times\n  faster:\n\n  | Part's share | Part made 2x faster | Part removed entirely |\n  |---|---|---|\n  | 5% | 1.03x | 1.05x |\n  | 20% | 1.11x | 1.25x |\n  | 50% | 1.33x | 2x |\n  | 80% | 1.67x | 5x |\n\n  A loop at 5% is not worth an afternoon; the part at 80% is the only\n  place a large win can come from.\n\n## 4. Change one thing, then measure again\n\n- One hypothesis, one change, the same measurement. Keep it if the number\n  moved beyond the noise, revert it if not. Two changes measured together\n  hide which one helped and whether the other hurt.\n- Cheapest first: configuration and build (release mode, production mode,\n  a pool size, a runtime flag, an index) before code, code before\n  architecture, architecture before a rewrite in another language.\n- Correctness is part of the measurement. Run the tests after every\n  change. For risky changes (a cache, concurrency, a new algorithm, a\n  denormalised column) add a test comparing old and new results on the\n  same inputs, edge cases included: empty, one item, duplicates, the\n  largest.\n- Revert what did not help. Complexity without a measured gain is a cost\n  someone pays later.\n- Keep a short log as you go (change, before, after, kept or reverted); it\n  becomes the report.\n- A change that helps one input shape and hurts another is a trade:\n  measure both and say which got slower (small versus large inputs, reads\n  versus writes, first request versus steady state).\n\n## 5. Statistics: distributions, not one number\n\n- **Repeat.** One run is an anecdote. Macro measurements: at least 10\n  runs, or a load test long enough for thousands of requests.\n  Micro-benchmarks: let the tool decide (`performance-benchmarks`).\n- **Percentiles over averages.** Report p50, p95 and p99, and the maximum\n  when samples are few. An endpoint answering in 50ms 98% of the time and\n  in 2s the other 2% has a mean of 89ms: a time no request took, hiding\n  the users who waited two seconds.\n- **Enough samples.** A p99 from 100 samples is one sample. Collect at\n  least 1,000 per p99 you report, and ten times more for p99.9.\n- **Never average percentiles.** The mean of ten instances' p95 is not the\n  fleet's p95. Merge histograms (HdrHistogram, Prometheus histograms,\n  OpenTelemetry exponential histograms) or compute from all the samples.\n- **Spread and significance.** Give the spread (interquartile range,\n  standard deviation or min to max) with the median. A difference smaller\n  than the run-to-run spread is no difference. When it is close, use a\n  statistical test: benchstat and criterion report one (hyperfine ships a\n  Welch t-test script for its JSON export); otherwise Mann-Whitney U or a\n  bootstrap confidence interval.\n- **Warm versus cold.** The first request after a deploy pays for JIT\n  compilation, empty caches, new connections and a cold disk cache. Say\n  which you measured; measure both when real users meet both.\n- **Tails multiply.** A request fanning out to 100 backends waits for the\n  slowest. If each is slow 1% of the time, 63% of those requests are slow\n  (`1 - 0.99^100`): a dependency's p99 becomes its caller's median. Fan-out\n  needs fewer calls, tight timeouts or hedged requests.\n\n## 6. Latency, throughput and saturation\n\n- **Latency** is how long one operation takes, what a user waits.\n  **Throughput** is how many complete per second, what the system carries.\n  Batching raises throughput and adds latency; more parallelism raises\n  throughput until something shared saturates.\n- **Little's law**: items in the system = arrival rate x time in the\n  system. 200 requests per second at 50ms keeps 10 in flight; at 500ms, 100\n  are in flight, and pools, threads and memory sized for 10 run out. This\n  is how one slow dependency takes a whole service down.\n- **Queueing near capacity**: in the simplest queue model, time in the\n  system is the service time divided by `(1 - utilisation)`: 2x at 50%\n  busy, 5x at 80%, 10x at 90%, 20x at 95%. Latency that is flat, then\n  climbs steeply, is a saturated resource, not slow code.\n- **The knee**: as load rises, throughput stops growing while p95 and p99\n  climb; past it, queues grow without bound and errors start. Find it with\n  a load test (`performance-load`) and plan peak traffic at 60 to 75% of\n  it.\n- A latency without its load is half a number: \"p95 120ms at 400 requests\n  per second on 8 instances\", not \"p95 120ms\".\n\n## 7. Budgets and regression guards\n\nA speed-up that nobody guards is gone within months.\n\n- Write budgets where the team sees them: endpoint latency (p95 and p99),\n  page metrics and JavaScript weight (`frontend-performance`), job\n  durations, binary or image size, memory per instance.\n- Guard each with the cheapest check that catches the regression:\n\n  | Regression | Guard in CI |\n  |---|---|\n  | A hot function got slower | benchmarks compared with the base branch (`performance-benchmarks`) |\n  | An N+1 crept in | a test asserting an endpoint's query count (Django `assertNumQueries`, Rails `assert_queries_count`, a query counter elsewhere) |\n  | A bundle or binary grew | a size limit (size-limit, a byte budget in the build) |\n  | Page metrics dropped | Lighthouse CI assertions (`frontend-performance`) |\n  | An endpoint slowed under load | a short k6 run with thresholds (`performance-load`) |\n\n- Thresholds sit above the measured noise (often 5 to 10%, more on shared\n  runners), never at zero, or the check fails at random and gets ignored.\n- In production, alert on the percentile against the SLO, not on the mean\n  (`backend-observability`).\n\n## 8. Where the big wins usually are\n\nAfter the profile points there, in rough order of how often they pay:\n\n| Area | Typical change | Detail |\n|---|---|---|\n| Algorithm and data structure | a lookup in a nested loop becomes a hash map or set; sort once, not per item; stop re-scanning a list | `code` |\n| Database | N+1 removed, a missing index added, fewer rows and columns fetched, keyset pagination | `database-queries`, `database-indexes` |\n| Repeated work | computed once per request, pure functions memoised, costly shared results cached, values precomputed on write | `backend-caching` |\n| Round trips | multi-get, bulk insert, one `IN` query instead of a loop, pipelining | `performance-backend` |\n| Loading everything | rows, lines and responses streamed instead of built in memory | `performance-memory` |\n| Independent work in series | independent I\u002FO run concurrently (bounded), CPU work spread over cores | `performance-backend` |\n| Payload size | fewer fields, pagination, compression, smaller images, less JavaScript | `frontend-performance` |\n| Work on the request path | moved to a background job | `backend-jobs` |\n| Build and runtime | release build, production mode, a current runtime, GC settings | `performance-memory` |\n\nCosts worth knowing when estimating, as orders of magnitude on current\nhardware:\n\n| Operation | Roughly |\n|---|---|\n| Main memory reference | 100ns |\n| Random 4 KB read from an NVMe SSD | 100 microseconds |\n| Round trip inside a data centre | 0.1 to 0.5ms |\n| Indexed lookup in a database, round trip included | 0.5 to 1ms |\n| Round trip across the internet | 20 to 150ms |\n| New HTTPS connection | 2 to 3 extra round trips (TCP, TLS) before the request is sent |\n\nFifty sequential queries at 1ms is 50ms whatever each query costs.\nMicro-optimisations (manual inlining, bit tricks, avoiding a call) come\nlast, and only inside a loop the profile shows is hot.\n\n## 9. Report numbers with their conditions\n\n```text\nMetric:       p95 and p99 latency of GET \u002Fapi\u002Forders?status=open\nWorkload:     \u003Ctool and script, arrival rate, duration, data size>\nEnvironment:  \u003Cinstance size, runtime versions, database size, commits before and after>\nMethod:       \u003Cruns or samples, warm or cold, warm-up excluded or not>\nBefore:       p50 \u003Cn> ms, p95 \u003Cn> ms, p99 \u003Cn> ms, errors \u003Cn>%\nAfter:        p50 \u003Cn> ms, p95 \u003Cn> ms, p99 \u003Cn> ms, errors \u003Cn>%\nChange:       \u003Cwhat changed, in one or two lines>\nTrade:        \u003Cwhat got slower or bigger, and for which inputs>\nNot measured: \u003Cwhat could not be run, and why>\n```\n\n- Absolute numbers with units plus the relative change; never \"much\n  faster\". Only numbers that were measured: no estimates presented as\n  results, no figures from a blog post as if they were yours.\n- Say what was traded: memory for speed, write cost for read speed (an\n  index), freshness for latency (a cache), simplicity for throughput.\n- Say plainly what could not be run (no staging, no permission, no\n  production-size data) and what the numbers therefore do not show.\n- Attach the raw output: benchmark tables, k6 summaries, profiles.\n\n## 10. Which skill for which job\n\n| Job | Skill |\n|---|---|\n| Where time or memory goes | `performance-profiling` |\n| A slow endpoint, service or worker | `performance-backend` |\n| Memory that grows, OOM kills, heavy allocation | `performance-memory` |\n| Writing a benchmark, claiming a speed-up, CI regression checks | `performance-benchmarks` |\n| Capacity, load, stress, soak and spike tests | `performance-load` |\n| Web vitals, bundle weight, images, hydration | `frontend-performance` |\n| Adding or fixing a cache | `backend-caching` |\n| Slow queries, N+1, reading EXPLAIN | `database-queries` |\n| Adding, changing or removing indexes | `database-indexes` |\n| Allocation strategy, data layout, cache locality | `systems-memory` |\n| Animation jank and frame cost | `motion-performance` |\n\n## Check it\n\n- Before and after come from the same command, workload and machine, with\n  several runs each, and the change is larger than the spread.\n- The profile after the change shows the hot spot shrank and nothing new\n  took its place.\n- The project's own tests pass, run with `bash`. When a command is refused\n  or cannot run (installing a profiler, tuning the CPU, a load test\n  against staging), the report says so instead of estimating.\n- Every kept change has its own measured gain; the rest were reverted.\n- The report states metric, workload, environment, method, trade and what\n  was not measured.\n\n## Avoid\n\nOptimising before measuring; optimising the code that looks slow instead\nof the code the profile shows; a speed-up from one run; means without\npercentiles; averaged percentiles; a latency without its load; a debug\nbuild or development mode measured; several changes measured as one; a\ncache added to hide a slow query; a faster result that is wrong; a\nmicro-benchmark win claimed as a product win; numbers without the workload\nand environment; estimates reported as measurements.\n","# Performance work, measured\n\nPerformance work done by default is a guess: code rewritten because it\nlooked slow, a cache put in front of everything, a loop micro-optimised\nthat takes 1% of the time, \"3x faster\" from one run on a laptop, an average\nthat hides a two-second tail, and a fix that quietly returns wrong answers.\nThis skill is the method an experienced engineer follows instead: define the\nmetric and the workload, measure a baseline, find where the time goes,\nchange one thing, compare with statistics, and report the numbers with the\nconditions they were measured under. Each step names the skill that holds\nthe detail.\n\n## 1. Define the problem as a number\n\nBefore reading any code, write down three things.\n\n- **The metric**, the one a user or an operator feels:\n\n  | Complaint | Metric |\n  |---|---|\n  | The page is slow | LCP, INP and CLS at p75 of real visits (`frontend-performance`) |\n  | The API is slow | latency p95 and p99 per endpoint, at a stated request rate |\n  | The job takes all night | wall-clock duration for a stated input size |\n  | We need more servers | throughput per instance at the latency target |\n  | It keeps getting killed | peak resident memory (`performance-memory`) |\n  | The download is huge | bundle, binary or payload size, compressed |\n  | The first request is slow | cold start, measured apart from warm requests |\n\n- **The target**: a number with its percentile and its condition. \"p95\n  under 300ms at 200 requests per second with a 50,000-order account\", not\n  \"faster\". It comes from an SLO, a budget, a product requirement or the\n  owner; if nobody has one, propose one and say it is proposed.\n- **The workload**: realistic data sizes (production row counts, the\n  largest customer, not a seed of 20 rows), realistic input shapes and\n  their distribution, the concurrency, and whether caches are warm or\n  cold. Query plans, hit rates and an algorithm's cost all change with\n  size; a toy workload optimises the wrong thing.\n\nDone means: the target is met on that workload, and the tests still pass.\n\n## 2. Measure a baseline first\n\n- Measure before changing anything, with the exact command, script or\n  query that will measure the after. Keep the raw output, not only a\n  summary, and the commit hash it ran on.\n- Write the environment down: machine or instance size (CPU model, cores,\n  memory), OS, runtime and compiler versions, build mode, configuration\n  flags, data size, and anything else running at the time.\n- Optimised builds only. A debug build, a framework's development mode\n  (React, Next.js, Django with `DEBUG`, Rails), Go's race detector (2 to\n  20x slower by its own documentation) or a sanitiser changes the numbers\n  by multiples and moves the hot spots.\n- Run the baseline three separate times. If the runs differ by as much as\n  the improvement you hope for, reduce the noise first\n  (`performance-benchmarks`).\n- Before and after on the same machine in the same session. Laptops\n  throttle on battery and when hot; shared CI runners vary between jobs.\n- Capture a profile with the baseline (`performance-profiling`): it is the\n  before half of the comparison later.\n\n## 3. Find where the time goes\n\nThe hot path is the one the measurement shows, not the one that looks slow.\n\n- Start coarse and split the total into parts. For a request: tracing\n  spans (database, external calls, serialisation, CPU, waiting for a pool).\n  For a page: the browser's Performance panel. For a command: `time`;\n  `real` far above `user + sys` means waiting (I\u002FO, network, locks,\n  sleeps), `user + sys` above `real` means several cores worked.\n- Then profile the biggest part (`performance-profiling`): a CPU profile\n  when a core is busy, an off-CPU or wall-clock view when it waits, a heap\n  profile for memory, `EXPLAIN` for a query (`database-queries`).\n- Amdahl's law sets the ceiling. A part taking a share `p` of the time,\n  made `s` times faster, makes the whole `1 \u002F ((1 - p) + p \u002F s)` times\n  faster:\n\n  | Part's share | Part made 2x faster | Part removed entirely |\n  |---|---|---|\n  | 5% | 1.03x | 1.05x |\n  | 20% | 1.11x | 1.25x |\n  | 50% | 1.33x | 2x |\n  | 80% | 1.67x | 5x |\n\n  A loop at 5% is not worth an afternoon; the part at 80% is the only\n  place a large win can come from.\n\n## 4. Change one thing, then measure again\n\n- One hypothesis, one change, the same measurement. Keep it if the number\n  moved beyond the noise, revert it if not. Two changes measured together\n  hide which one helped and whether the other hurt.\n- Cheapest first: configuration and build (release mode, production mode,\n  a pool size, a runtime flag, an index) before code, code before\n  architecture, architecture before a rewrite in another language.\n- Correctness is part of the measurement. Run the tests after every\n  change. For risky changes (a cache, concurrency, a new algorithm, a\n  denormalised column) add a test comparing old and new results on the\n  same inputs, edge cases included: empty, one item, duplicates, the\n  largest.\n- Revert what did not help. Complexity without a measured gain is a cost\n  someone pays later.\n- Keep a short log as you go (change, before, after, kept or reverted); it\n  becomes the report.\n- A change that helps one input shape and hurts another is a trade:\n  measure both and say which got slower (small versus large inputs, reads\n  versus writes, first request versus steady state).\n\n## 5. Statistics: distributions, not one number\n\n- **Repeat.** One run is an anecdote. Macro measurements: at least 10\n  runs, or a load test long enough for thousands of requests.\n  Micro-benchmarks: let the tool decide (`performance-benchmarks`).\n- **Percentiles over averages.** Report p50, p95 and p99, and the maximum\n  when samples are few. An endpoint answering in 50ms 98% of the time and\n  in 2s the other 2% has a mean of 89ms: a time no request took, hiding\n  the users who waited two seconds.\n- **Enough samples.** A p99 from 100 samples is one sample. Collect at\n  least 1,000 per p99 you report, and ten times more for p99.9.\n- **Never average percentiles.** The mean of ten instances' p95 is not the\n  fleet's p95. Merge histograms (HdrHistogram, Prometheus histograms,\n  OpenTelemetry exponential histograms) or compute from all the samples.\n- **Spread and significance.** Give the spread (interquartile range,\n  standard deviation or min to max) with the median. A difference smaller\n  than the run-to-run spread is no difference. When it is close, use a\n  statistical test: benchstat and criterion report one (hyperfine ships a\n  Welch t-test script for its JSON export); otherwise Mann-Whitney U or a\n  bootstrap confidence interval.\n- **Warm versus cold.** The first request after a deploy pays for JIT\n  compilation, empty caches, new connections and a cold disk cache. Say\n  which you measured; measure both when real users meet both.\n- **Tails multiply.** A request fanning out to 100 backends waits for the\n  slowest. If each is slow 1% of the time, 63% of those requests are slow\n  (`1 - 0.99^100`): a dependency's p99 becomes its caller's median. Fan-out\n  needs fewer calls, tight timeouts or hedged requests.\n\n## 6. Latency, throughput and saturation\n\n- **Latency** is how long one operation takes, what a user waits.\n  **Throughput** is how many complete per second, what the system carries.\n  Batching raises throughput and adds latency; more parallelism raises\n  throughput until something shared saturates.\n- **Little's law**: items in the system = arrival rate x time in the\n  system. 200 requests per second at 50ms keeps 10 in flight; at 500ms, 100\n  are in flight, and pools, threads and memory sized for 10 run out. This\n  is how one slow dependency takes a whole service down.\n- **Queueing near capacity**: in the simplest queue model, time in the\n  system is the service time divided by `(1 - utilisation)`: 2x at 50%\n  busy, 5x at 80%, 10x at 90%, 20x at 95%. Latency that is flat, then\n  climbs steeply, is a saturated resource, not slow code.\n- **The knee**: as load rises, throughput stops growing while p95 and p99\n  climb; past it, queues grow without bound and errors start. Find it with\n  a load test (`performance-load`) and plan peak traffic at 60 to 75% of\n  it.\n- A latency without its load is half a number: \"p95 120ms at 400 requests\n  per second on 8 instances\", not \"p95 120ms\".\n\n## 7. Budgets and regression guards\n\nA speed-up that nobody guards is gone within months.\n\n- Write budgets where the team sees them: endpoint latency (p95 and p99),\n  page metrics and JavaScript weight (`frontend-performance`), job\n  durations, binary or image size, memory per instance.\n- Guard each with the cheapest check that catches the regression:\n\n  | Regression | Guard in CI |\n  |---|---|\n  | A hot function got slower | benchmarks compared with the base branch (`performance-benchmarks`) |\n  | An N+1 crept in | a test asserting an endpoint's query count (Django `assertNumQueries`, Rails `assert_queries_count`, a query counter elsewhere) |\n  | A bundle or binary grew | a size limit (size-limit, a byte budget in the build) |\n  | Page metrics dropped | Lighthouse CI assertions (`frontend-performance`) |\n  | An endpoint slowed under load | a short k6 run with thresholds (`performance-load`) |\n\n- Thresholds sit above the measured noise (often 5 to 10%, more on shared\n  runners), never at zero, or the check fails at random and gets ignored.\n- In production, alert on the percentile against the SLO, not on the mean\n  (`backend-observability`).\n\n## 8. Where the big wins usually are\n\nAfter the profile points there, in rough order of how often they pay:\n\n| Area | Typical change | Detail |\n|---|---|---|\n| Algorithm and data structure | a lookup in a nested loop becomes a hash map or set; sort once, not per item; stop re-scanning a list | `code` |\n| Database | N+1 removed, a missing index added, fewer rows and columns fetched, keyset pagination | `database-queries`, `database-indexes` |\n| Repeated work | computed once per request, pure functions memoised, costly shared results cached, values precomputed on write | `backend-caching` |\n| Round trips | multi-get, bulk insert, one `IN` query instead of a loop, pipelining | `performance-backend` |\n| Loading everything | rows, lines and responses streamed instead of built in memory | `performance-memory` |\n| Independent work in series | independent I\u002FO run concurrently (bounded), CPU work spread over cores | `performance-backend` |\n| Payload size | fewer fields, pagination, compression, smaller images, less JavaScript | `frontend-performance` |\n| Work on the request path | moved to a background job | `backend-jobs` |\n| Build and runtime | release build, production mode, a current runtime, GC settings | `performance-memory` |\n\nCosts worth knowing when estimating, as orders of magnitude on current\nhardware:\n\n| Operation | Roughly |\n|---|---|\n| Main memory reference | 100ns |\n| Random 4 KB read from an NVMe SSD | 100 microseconds |\n| Round trip inside a data centre | 0.1 to 0.5ms |\n| Indexed lookup in a database, round trip included | 0.5 to 1ms |\n| Round trip across the internet | 20 to 150ms |\n| New HTTPS connection | 2 to 3 extra round trips (TCP, TLS) before the request is sent |\n\nFifty sequential queries at 1ms is 50ms whatever each query costs.\nMicro-optimisations (manual inlining, bit tricks, avoiding a call) come\nlast, and only inside a loop the profile shows is hot.\n\n## 9. Report numbers with their conditions\n\n```text\nMetric:       p95 and p99 latency of GET \u002Fapi\u002Forders?status=open\nWorkload:     \u003Ctool and script, arrival rate, duration, data size>\nEnvironment:  \u003Cinstance size, runtime versions, database size, commits before and after>\nMethod:       \u003Cruns or samples, warm or cold, warm-up excluded or not>\nBefore:       p50 \u003Cn> ms, p95 \u003Cn> ms, p99 \u003Cn> ms, errors \u003Cn>%\nAfter:        p50 \u003Cn> ms, p95 \u003Cn> ms, p99 \u003Cn> ms, errors \u003Cn>%\nChange:       \u003Cwhat changed, in one or two lines>\nTrade:        \u003Cwhat got slower or bigger, and for which inputs>\nNot measured: \u003Cwhat could not be run, and why>\n```\n\n- Absolute numbers with units plus the relative change; never \"much\n  faster\". Only numbers that were measured: no estimates presented as\n  results, no figures from a blog post as if they were yours.\n- Say what was traded: memory for speed, write cost for read speed (an\n  index), freshness for latency (a cache), simplicity for throughput.\n- Say plainly what could not be run (no staging, no permission, no\n  production-size data) and what the numbers therefore do not show.\n- Attach the raw output: benchmark tables, k6 summaries, profiles.\n\n## 10. Which skill for which job\n\n| Job | Skill |\n|---|---|\n| Where time or memory goes | `performance-profiling` |\n| A slow endpoint, service or worker | `performance-backend` |\n| Memory that grows, OOM kills, heavy allocation | `performance-memory` |\n| Writing a benchmark, claiming a speed-up, CI regression checks | `performance-benchmarks` |\n| Capacity, load, stress, soak and spike tests | `performance-load` |\n| Web vitals, bundle weight, images, hydration | `frontend-performance` |\n| Adding or fixing a cache | `backend-caching` |\n| Slow queries, N+1, reading EXPLAIN | `database-queries` |\n| Adding, changing or removing indexes | `database-indexes` |\n| Allocation strategy, data layout, cache locality | `systems-memory` |\n| Animation jank and frame cost | `motion-performance` |\n\n## Check it\n\n- Before and after come from the same command, workload and machine, with\n  several runs each, and the change is larger than the spread.\n- The profile after the change shows the hot spot shrank and nothing new\n  took its place.\n- The project's own tests pass, run with `bash`. When a command is refused\n  or cannot run (installing a profiler, tuning the CPU, a load test\n  against staging), the report says so instead of estimating.\n- Every kept change has its own measured gain; the rest were reverted.\n- The report states metric, workload, environment, method, trade and what\n  was not measured.\n\n## Avoid\n\nOptimising before measuring; optimising the code that looks slow instead\nof the code the profile shows; a speed-up from one run; means without\npercentiles; averaged percentiles; a latency without its load; a debug\nbuild or development mode measured; several changes measured as one; a\ncache added to hide a slow query; a faster result that is wrong; a\nmicro-benchmark win claimed as a product win; numbers without the workload\nand environment; estimates reported as measurements.\n",{"name":5,"description":7},"main","38293fe1b096e6bf3646c7344c38786ed688f464","crates\u002Fenowx-core\u002Fskills\u002Fperformance",21,"https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli","https:\u002F\u002Fenowx.ai","https:\u002F\u002Fgithub.com\u002Fenowdev","Pretending to be a Developer","2026-10-06 02:05:35",{"source":8,"skillName":5,"commands":51,"prompt":61,"zipAvailable":62},[52,55,58],{"tool":53,"command":54},"npx","npx skills add enowdev\u002Fenowxcli --skill performance",{"tool":56,"command":57},"bunx","bunx skills add enowdev\u002Fenowxcli --skill performance",{"tool":59,"command":60},"pnpm","pnpm dlx skills add enowdev\u002Fenowxcli --skill performance","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fperformance\u002FSKILL.md",true,[],[65,77,102,118,145,167],{"skillNo":66,"name":67,"nameZh":6,"description":68,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":69,"categories":70,"keywords":72,"publishedAt":36},"01M6D2HQYSQD9N7MTNDT4A7CBM","demo-skill","Project-scope demo skill for tests.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fworkspace\u002F.agents\u002Fskills\u002Fdemo-skill\u002FSKILL.md",[71],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},[73,74,75,76,32],"demo skill","demo","tests","project",{"skillNo":78,"name":79,"nameZh":6,"description":80,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":91,"publishedAt":36},"01M6D2HM0GCPM0TM2HPG9HHR2R","writing","Writing words people read: the specific thing instead of claims, words to drop, sentences, interface copy (buttons, labels, errors, empty states, confirmations), page copy, notifications and emails, alt text and link text, numbers and dates, words that translate well, documentation and voice. Read before writing a page's copy, an interface's text or a document.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fwriting\u002FSKILL.md",[83,86],{"categoryNo":84,"categoryName":85,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000018","写作与文案",{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000036","内容创作者","PROFESSION","适用职业",[79,92,93,94,95,96,32,97,98,99,100,101],"text","emails","empty","drop","document","page","voice","notifications","documentation","translate",{"skillNo":103,"name":104,"nameZh":6,"description":105,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":106,"categories":107,"keywords":111,"publishedAt":36},"01M6D2HG07YS49NM196Q0R3AZ8","ui","Designing or restyling an interface: direction, layout, type, colour, icons, components, states, responsive behaviour. Read before building a page, a screen or a set of components.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui\u002FSKILL.md",[108],{"categoryNo":109,"categoryName":110,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000032","设计师",[104,112,113,114,115,97,116,32,117],"icons","components","SET","responsive","layout","before building",{"skillNo":119,"name":120,"nameZh":6,"description":121,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":122,"categories":123,"keywords":130,"publishedAt":36},"01M6D2HB59HZHWG1RYZDV4SJ91","ui-themes","Light and dark themes, and colour that holds in both: tokens with a value per theme, and what each kind of content needs to stay visible (icons, SVG drawings and line art, logos, photos, screenshots, charts, code, maps, borders, shadows, focus, form controls), switching without a flash, and checking both. Read before building a second theme or a theme toggle, and before any drawing, logo or chart on a page that has two themes.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-themes\u002FSKILL.md",[124,127],{"categoryNo":125,"categoryName":126,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000015","视觉设计",{"categoryNo":128,"categoryName":129,"taxonomyType":89,"taxonomyTypeDesc":90},"01JBSEEDCAT000000000000030","开发工程师",[104,131,132,133,134,135,136,137,138,32,117,139,97,140,141,142,112,143,144],"ui themes","switching","photos","tokens","drawing","focus","maps","Art","flash","code","Charts","content","screenshots","logo",{"skillNo":146,"name":147,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":154,"publishedAt":36},"01M6D2H5R5KRAE524C8QX0T7Q0","ui-structure","Structure before styling: the blueprint written before any interface code (the screen's job, the regions its kind of page needs, their order and why, the layout skeleton in numbers, the components and their states), the anatomy and order of a homepage, a dashboard, a list, a detail page, settings, a form, sign-in, pricing, docs, an article and a checkout, and how to turn the blueprint into code (tokens, layout primitives, components, sections, page). Read first, before building or rebuilding any page or screen.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-structure\u002FSKILL.md",[151,152,153],{"categoryNo":84,"categoryName":85,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":128,"categoryName":129,"taxonomyType":89,"taxonomyTypeDesc":90},{"categoryNo":87,"categoryName":88,"taxonomyType":89,"taxonomyTypeDesc":90},[155,104,156,113,157,158,140,159,160,161,116,134,162,163,164,32,117,97,165,166],"structure","ui structure","pricing","dashboard","Blueprint","article","anatomy","styling","primitives","list","why","how",{"skillNo":168,"name":169,"nameZh":6,"description":170,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":171,"categories":172,"keywords":180,"publishedAt":36},"01M6D2H0ZZBJG77MBGPZHA6MWD","ui-stack-vue","Building interfaces in Vue 3 and Nuxt: project layout, script setup with typed defineProps, defineEmits and defineModel, attribute fallthrough, slots and scoped slots, template refs, ref, reactive and computed, watch versus watchEffect, composables and VueUse, provide and inject, Pinia, keyed v-for, transitions, Nuxt 4 (app directory, pages, layouts, useFetch and useAsyncData keys, $fetch in handlers, server routes, runtime config, useSeoMeta, NuxtImg, middleware), VeeValidate forms, Reka UI and Nuxt UI, testing, vue-tsc, and the traps. Read when the project uses Vue or Nuxt.","https:\u002F\u002Fgithub.com\u002Fenowdev\u002Fenowxcli\u002Fblob\u002Fmain\u002Fcrates\u002Fenowx-core\u002Fskills\u002Fui-stack-vue\u002FSKILL.md",[173,176,179],{"categoryNo":174,"categoryName":175,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量",{"categoryNo":177,"categoryName":178,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000009","前端开发",{"categoryNo":109,"categoryName":110,"taxonomyType":89,"taxonomyTypeDesc":90},[104,181,182,183,184,185,186,187,116,76,188,189,32,190,191,192,193,194,195,196],"vue","stack","ui stack vue","forms","pages","watch","runtime","transitions","fetch","pinia","nuxt","template","server","config","directory","testing"]