[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M698Z2GWDYSWWESR8FYDTB1P":3,"skill-same:01M698Z2GWDYSWWESR8FYDTB1P":71},{"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":18,"publishedAt":42,"linkOnly":43,"markdownContent":44,"markdownBody":45,"frontMatter":46,"refName":47,"commitSha":48,"skillDirectory":49,"forksCount":50,"repositoryHtmlUrl":51,"repositoryHomepageUrl":52,"ownerHtmlUrl":53,"ownerBlogUrl":54,"ownerDescription":55,"updatedAt":56,"install":57,"resources":70},"01M698Z2GWDYSWWESR8FYDTB1P","gvisor-performance",null,"Use when modifying gVisor in ways with potential performance implications; as a kernel, gVisor's performance matters almost as much as its security. Load imperatively when editing this performance-sensitive code:\n\n  * Syscall hot path: `pkg\u002Fsentry\u002Fkernel` (`task_run.go`, `task_syscall.go`),\n    `pkg\u002Fsentry\u002Fsyscalls\u002Flinux`, and app-memory copy layers\n    (`pkg\u002Fusermem`, `pkg\u002Fsafemem`, `pkg\u002Fsafecopy`, `pkg\u002Fmarshal`).\n  * Platform: `pkg\u002Fsentry\u002Fplatform`, `pkg\u002Fring0`.\n  * Sandbox startup: `runsc\u002Fboot`, `runsc\u002Fcontainer`, `runsc\u002Fsandbox`.\n  * Serialization and checkpoint\u002Frestore: `pkg\u002Fstate`, `pkg\u002Fsentry\u002Fstate`.\n  * Netstack: `pkg\u002Ftcpip`.\n  * File I\u002FO: `pkg\u002Fsentry\u002Fvfs`, `pkg\u002Fsentry\u002Ffsimpl`.\n  * Memory management: `pkg\u002Fsentry\u002Fmm`, `pkg\u002Fsentry\u002Fpgalloc`.\n  * Gofer IPC: `pkg\u002Flisafs`, `runsc\u002Ffsgofer`.\n  * Go `init()` functions, which run on every binary startup.\n\nAlso load for any change with potential performance impact, even outside these paths.","google\u002Fgvisor","google","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F1342004?v=4","01M698VYEFDM0VJBZDYYJ2T83S","Google","01M698YX0KM1V8AAGJQZXZD6T7",20002,"Apache-2.0","https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgvisor\u002Fblob\u002Fmaster\u002F.agents\u002Fskills\u002Fgvisor-performance\u002FSKILL.md",[],[19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41],"performance","gvisor","gvisor performance","impact","sentry","as","mm","path","marshal","security","paths","run","change","code","when","init","memory","which","app","linux","kernel","go","sandbox","2026-11-10 10:12:30",false,"---\nname: gvisor-performance\ndescription: >\n  Use when modifying gVisor in ways with potential performance implications;\n  as a kernel, gVisor's performance matters almost as much as its security.\n  Load imperatively when editing this performance-sensitive code:\n\n    * Syscall hot path: `pkg\u002Fsentry\u002Fkernel` (`task_run.go`, `task_syscall.go`),\n      `pkg\u002Fsentry\u002Fsyscalls\u002Flinux`, and app-memory copy layers\n      (`pkg\u002Fusermem`, `pkg\u002Fsafemem`, `pkg\u002Fsafecopy`, `pkg\u002Fmarshal`).\n    * Platform: `pkg\u002Fsentry\u002Fplatform`, `pkg\u002Fring0`.\n    * Sandbox startup: `runsc\u002Fboot`, `runsc\u002Fcontainer`, `runsc\u002Fsandbox`.\n    * Serialization and checkpoint\u002Frestore: `pkg\u002Fstate`, `pkg\u002Fsentry\u002Fstate`.\n    * Netstack: `pkg\u002Ftcpip`.\n    * File I\u002FO: `pkg\u002Fsentry\u002Fvfs`, `pkg\u002Fsentry\u002Ffsimpl`.\n    * Memory management: `pkg\u002Fsentry\u002Fmm`, `pkg\u002Fsentry\u002Fpgalloc`.\n    * Gofer IPC: `pkg\u002Flisafs`, `runsc\u002Ffsgofer`.\n    * Go `init()` functions, which run on every binary startup.\n\n  Also load for any change with potential performance impact,\n  even outside these paths.\n---\n\n## gVisor performance sensitivity\n\nAs a kernel, gVisor performance matters almost as much as security. As such, any\nchange that may impact performance is required to come with benchmark\nmeasurements to measure its benefit and to avoid regressions, and must be\ncareful to avoid introducing performance regressions.\n\nIn particular, consider these tips when making changes in this area:\n\n-   **Heap allocations**: Avoid heap allocations where possible, and annotate\n    functions that must not allocate with `\u002F\u002F +checkescape` so that the\n    `checkescape` analyzer enforces this. In netstack, use the pooled\n    reference-counted buffers in `pkg\u002Fbuffer` instead of allocating and copying\n    packet data.\n-   **Gofer round-trips**: Each gofer RPC is a round trip to another process.\n    Avoid adding RPCs to frequent file system operations; use the Sentry's\n    cached file system state, or combined RPCs such as `WalkStat`.\n-   **Pre-sized data structures**: When you need to use a heap-allocated\n    dynamically-sized data structure such as a slice or a map, pre-allocate the\n    expected capacity it will need. When no perfect proxy exists but an upper\n    bound exists that isn't likely to be pathologically high, use that. When\n    there is truly no way to know but that tracking historical patterns could be\n    effective, do so. Do not assume Go's default sizing is the correct option.\n    When possible, reuse already-allocated slices rather than allocating new\n    ones within the same context.\n-   **Never use `init()` functions**: `init` functions are almost never a good\n    idea. They add silent startup cost to every binary invocation, even when\n    unneeded. Instead, add a package-level `Init` function that actual package\n    users have to call by the time it is clear it will be necessary, or\n    initialize the package on first-use if doing so is cheap and doesn't have\n    synchronization issues. If neither of these options is adequate, create an\n    `Init` function and manually call it in `main` in all the binaries that will\n    for sure use it.\n    -   Similarly, also avoid allocating large data structures at the package\n        level. Prefer a `sync.Once` that allocates it on first access, unless\n        doing so comes with performance\u002Fsynchronization overhead due to frequent\n        access.\n    -   Never, ever put system calls in `init` functions.\n-   **Saved state**: Checkpoint latency and byte size grow the more kernel state\n    is saved. Don't save state that can be rebuilt cheaply on restore; tag it\n    `state:\"nosave\"` instead and rebuild it in `afterLoad`.\n-   **Go compiler annotations**: You may use `go:nosplit` where appropriate.\n    Functions that are short enough should aim to fit under Go's inlining budget\n    if they are performance-sensitive and if doing so comes at no more than a\n    small readability cost.\n\n## Benchmarking methodology\n\nFor performance-impacting changes, or changes that may *potentially* impact\nperformance, benchmark figures are required in the PR description.\n\nSelect the subset of benchmarks in `\u002F\u002Ftest\u002Fbenchmarks` and\n`\u002F\u002Ftest\u002Fkubernetes\u002Fbenchmarks` that cover the aspects of performance that may be\nimpacted by the change. If not already covered, also come up with new benchmarks\nthat demonstrate the effect the change at hand has more clearly than the\nexisting benchmarks do. For example, if benchmarking Gofer startup performance,\nrun `\u002F\u002Ftest\u002Fbenchmarks\u002Fbase:startup_test` and\n`\u002F\u002Ftest\u002Fkubernetes\u002Fbenchmarks:startup_test`, as well as some one-off Gofer-only\nbenchmarks you may design on your own.\n\nNOTE: You **must** select at least one already-existing benchmark.\nPerformance-impacting changes that only come with change-specific benchmarks may\nhide broader performance implications. Thus, you must select at least one broad\nbenchmark as well, even if the benchmark data shows no difference.\n\nIn general, selecting broad benchmarks should be done on a category basis; do\nnot cherrypick benchmarks. For example, if you are modifying networking code,\nthen you should include **all** networking benchmarks (`iperf`, `nginx`,\n`redis`, etc.) and run them at **all** relevant variants (e.g. all concurrency\nlevels of `nginx`). If the resulting benchmark dump is too long, you may\nsummarize it, but do not elide it completely, as this may be perceived as an\nattempt to cherrypick benchmarks.\n\nBenchmark data must be presented as the raw output of\n[Go's `benchstat` tool](https:\u002F\u002Fpkg.go.dev\u002Fgolang.org\u002Fx\u002Fperf\u002Fcmd\u002Fbenchstat).\nThis output contains the following critical pieces of information:\n\n-   Which benchmarks were run\n-   The median reading before vs after the change\n-   The standard deviation of the readings (both before and after the change)\n-   The percentage change between the \"before\" vs \"after\" readings\n-   How many times they were run (both before and after the change)\n-   The statistical significance of the results (the `p` value, resulting from\n    the Mann-Whitney U-test)\n\nAs a rule of thumb, you should run benchmarks until `n≥24` on each side or\n`p\u003C0.01`, whichever happens first. Signs to push `n` further include a standard\ndeviation larger than 5% on microbenchmarks. Seeing `~` (indicating no\nstatistically-significant change) is normal and expected for benchmark metrics\nwhere we expect no improvement nor regressions, and should therefore be included\nas well for completeness. If possible, benchmark on a relatively quiet machine\nto avoid benchmark noise.\n\nYou may create throwaway VMs to the extent permitted by your environment,\nalthough note that virtualization comes with its own overhead which can distort\nresults and, in the case of gVisor's KVM platform, do not reflect real-world\nbare-metal performance.\n\nIf none of the existing benchmarks cover the aspect of performance your change\nimpacts, you should add a benchmark that does.\n\nAfter providing the `benchstat` table, the PR description should also explain\nany surprising\u002Fnon-obvious result.\n\n## Help gVisor performance not regress\n\n### Add new benchmarks\n\nIf a performance change improves an area of gVisor that isn't already\nwell-captured by the existing set of benchmarks, and that you had to write a\none-off benchmark to show the effect of a performance change, then chances are\nthat this means gVisor needs a new benchmark added to its permanent set in order\nto ensure this aspect of gVisor performance does not regress into the future. If\nthis is the case, you should submit a separate PR **before** the performance\nchange that adds this benchmark to the permanent set. Permanent benchmarks\nshould be broad and generally-useful, not overly-specific to one particular\ncase.\n\nFor example, a benchmark measuring number of allocations in a specific tiny\ncodepath is **not** appropriate, but a benchmark measuring number of allocations\nand GC load in gVisor while a specific workload runs in the sandbox is.\n\n### Add `+checkescape` annotations\n\nIf your change reduces the number of allocations inside a certain codepath to\nzero, then you should add the `+checkescape` annotation to ensure this does not\nregress.\n","## gVisor performance sensitivity\n\nAs a kernel, gVisor performance matters almost as much as security. As such, any\nchange that may impact performance is required to come with benchmark\nmeasurements to measure its benefit and to avoid regressions, and must be\ncareful to avoid introducing performance regressions.\n\nIn particular, consider these tips when making changes in this area:\n\n-   **Heap allocations**: Avoid heap allocations where possible, and annotate\n    functions that must not allocate with `\u002F\u002F +checkescape` so that the\n    `checkescape` analyzer enforces this. In netstack, use the pooled\n    reference-counted buffers in `pkg\u002Fbuffer` instead of allocating and copying\n    packet data.\n-   **Gofer round-trips**: Each gofer RPC is a round trip to another process.\n    Avoid adding RPCs to frequent file system operations; use the Sentry's\n    cached file system state, or combined RPCs such as `WalkStat`.\n-   **Pre-sized data structures**: When you need to use a heap-allocated\n    dynamically-sized data structure such as a slice or a map, pre-allocate the\n    expected capacity it will need. When no perfect proxy exists but an upper\n    bound exists that isn't likely to be pathologically high, use that. When\n    there is truly no way to know but that tracking historical patterns could be\n    effective, do so. Do not assume Go's default sizing is the correct option.\n    When possible, reuse already-allocated slices rather than allocating new\n    ones within the same context.\n-   **Never use `init()` functions**: `init` functions are almost never a good\n    idea. They add silent startup cost to every binary invocation, even when\n    unneeded. Instead, add a package-level `Init` function that actual package\n    users have to call by the time it is clear it will be necessary, or\n    initialize the package on first-use if doing so is cheap and doesn't have\n    synchronization issues. If neither of these options is adequate, create an\n    `Init` function and manually call it in `main` in all the binaries that will\n    for sure use it.\n    -   Similarly, also avoid allocating large data structures at the package\n        level. Prefer a `sync.Once` that allocates it on first access, unless\n        doing so comes with performance\u002Fsynchronization overhead due to frequent\n        access.\n    -   Never, ever put system calls in `init` functions.\n-   **Saved state**: Checkpoint latency and byte size grow the more kernel state\n    is saved. Don't save state that can be rebuilt cheaply on restore; tag it\n    `state:\"nosave\"` instead and rebuild it in `afterLoad`.\n-   **Go compiler annotations**: You may use `go:nosplit` where appropriate.\n    Functions that are short enough should aim to fit under Go's inlining budget\n    if they are performance-sensitive and if doing so comes at no more than a\n    small readability cost.\n\n## Benchmarking methodology\n\nFor performance-impacting changes, or changes that may *potentially* impact\nperformance, benchmark figures are required in the PR description.\n\nSelect the subset of benchmarks in `\u002F\u002Ftest\u002Fbenchmarks` and\n`\u002F\u002Ftest\u002Fkubernetes\u002Fbenchmarks` that cover the aspects of performance that may be\nimpacted by the change. If not already covered, also come up with new benchmarks\nthat demonstrate the effect the change at hand has more clearly than the\nexisting benchmarks do. For example, if benchmarking Gofer startup performance,\nrun `\u002F\u002Ftest\u002Fbenchmarks\u002Fbase:startup_test` and\n`\u002F\u002Ftest\u002Fkubernetes\u002Fbenchmarks:startup_test`, as well as some one-off Gofer-only\nbenchmarks you may design on your own.\n\nNOTE: You **must** select at least one already-existing benchmark.\nPerformance-impacting changes that only come with change-specific benchmarks may\nhide broader performance implications. Thus, you must select at least one broad\nbenchmark as well, even if the benchmark data shows no difference.\n\nIn general, selecting broad benchmarks should be done on a category basis; do\nnot cherrypick benchmarks. For example, if you are modifying networking code,\nthen you should include **all** networking benchmarks (`iperf`, `nginx`,\n`redis`, etc.) and run them at **all** relevant variants (e.g. all concurrency\nlevels of `nginx`). If the resulting benchmark dump is too long, you may\nsummarize it, but do not elide it completely, as this may be perceived as an\nattempt to cherrypick benchmarks.\n\nBenchmark data must be presented as the raw output of\n[Go's `benchstat` tool](https:\u002F\u002Fpkg.go.dev\u002Fgolang.org\u002Fx\u002Fperf\u002Fcmd\u002Fbenchstat).\nThis output contains the following critical pieces of information:\n\n-   Which benchmarks were run\n-   The median reading before vs after the change\n-   The standard deviation of the readings (both before and after the change)\n-   The percentage change between the \"before\" vs \"after\" readings\n-   How many times they were run (both before and after the change)\n-   The statistical significance of the results (the `p` value, resulting from\n    the Mann-Whitney U-test)\n\nAs a rule of thumb, you should run benchmarks until `n≥24` on each side or\n`p\u003C0.01`, whichever happens first. Signs to push `n` further include a standard\ndeviation larger than 5% on microbenchmarks. Seeing `~` (indicating no\nstatistically-significant change) is normal and expected for benchmark metrics\nwhere we expect no improvement nor regressions, and should therefore be included\nas well for completeness. If possible, benchmark on a relatively quiet machine\nto avoid benchmark noise.\n\nYou may create throwaway VMs to the extent permitted by your environment,\nalthough note that virtualization comes with its own overhead which can distort\nresults and, in the case of gVisor's KVM platform, do not reflect real-world\nbare-metal performance.\n\nIf none of the existing benchmarks cover the aspect of performance your change\nimpacts, you should add a benchmark that does.\n\nAfter providing the `benchstat` table, the PR description should also explain\nany surprising\u002Fnon-obvious result.\n\n## Help gVisor performance not regress\n\n### Add new benchmarks\n\nIf a performance change improves an area of gVisor that isn't already\nwell-captured by the existing set of benchmarks, and that you had to write a\none-off benchmark to show the effect of a performance change, then chances are\nthat this means gVisor needs a new benchmark added to its permanent set in order\nto ensure this aspect of gVisor performance does not regress into the future. If\nthis is the case, you should submit a separate PR **before** the performance\nchange that adds this benchmark to the permanent set. Permanent benchmarks\nshould be broad and generally-useful, not overly-specific to one particular\ncase.\n\nFor example, a benchmark measuring number of allocations in a specific tiny\ncodepath is **not** appropriate, but a benchmark measuring number of allocations\nand GC load in gVisor while a specific workload runs in the sandbox is.\n\n### Add `+checkescape` annotations\n\nIf your change reduces the number of allocations inside a certain codepath to\nzero, then you should add the `+checkescape` annotation to ensure this does not\nregress.\n",{"name":5,"description":7},"master","dbcce494395f0f40564701651b76de5a96d70c8f",".agents\u002Fskills\u002Fgvisor-performance",2078,"https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgvisor","https:\u002F\u002Fgvisor.dev","https:\u002F\u002Fgithub.com\u002Fgoogle","https:\u002F\u002Fopensource.google\u002F","Google ❤️ Open Source","2026-11-15 02:45:30",{"source":8,"skillName":5,"commands":58,"prompt":68,"zipAvailable":69},[59,62,65],{"tool":60,"command":61},"npx","npx skills add google\u002Fgvisor --skill gvisor-performance",{"tool":63,"command":64},"bunx","bunx skills add google\u002Fgvisor --skill gvisor-performance",{"tool":66,"command":67},"pnpm","pnpm dlx skills add google\u002Fgvisor --skill gvisor-performance","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgvisor\u002Fblob\u002Fmaster\u002F.agents\u002Fskills\u002Fgvisor-performance\u002FSKILL.md",true,[],[72,93],{"skillNo":73,"name":74,"nameZh":6,"description":75,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":76,"categories":77,"keywords":78,"publishedAt":42},"01M698Z47JBA4W1XC0A96WXB8K","update-gvisor-maintainers","Update the gVisor maintainer roster in governance\u002Fmaintainers.yaml or the specialization areas in governance\u002Fareas.yaml, and regenerate the files derived from them (MAINTAINERS.md and CODEOWNERS). Use when a maintainer goes on hiatus, returns from hiatus, is added, steps down to emeritus, changes employer or specialization, or when MAINTAINERS.md \u002F CODEOWNERS are out of sync.","https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgvisor\u002Fblob\u002Fmaster\u002F.agents\u002Fskills\u002Fupdate-gvisor-maintainers\u002FSKILL.md",[],[79,80,20,81,82,83,84,85,86,87,33,88,89,90,91,92],"update","maintainers","update gvisor maintainers","returns","goes","sync","yaml","governance","changes","use","files","codeowners","roster","down",{"skillNo":94,"name":95,"nameZh":6,"description":96,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":97,"categories":98,"keywords":99,"publishedAt":42},"01M698Z06KDHZGY585SB25C56E","gvisor-kernel-development","Use when modifying gVisor application kernel behavior: adding a new system call, adding new flags to an existing system call, editing the syscall tests in `\u002F\u002Ftest\u002Fsyscalls`.","https:\u002F\u002Fgithub.com\u002Fgoogle\u002Fgvisor\u002Fblob\u002Fmaster\u002F.agents\u002Fskills\u002Fgvisor-kernel-development\u002FSKILL.md",[],[100,20,39,101,102,103,104,105,106,107,33,108,88,109,110],"development","gvisor kernel development","system","editing","application","flags","behavior","test","Existing","call","tests"]