PageSourceSearch

https://www.parca.dev/docs/assets/js/ccb8fd1f.0ce2c7d9.js

js parca.dev collected 2026-10-03 21:33:45 UTC 8,144 bytes, 1 lines download raw bytes

1"use strict";(globalThis.webpackChunkparca_dev=globalThis.webpackChunkparca_dev||[]).push([[4224],{5680(e,n,a){a.d(n,{xA:()=>c,yg:()=>m});var t=a(6540);function r(e,n,a){return n in e?Object.defineProperty(e,n,{value:a,enumerable:!0,configurable:!0,writable:!0}):e[n]=a,e}function o(e,n){var a=Object.keys(e);if(Object.getOwnPropertySymbols){var t=Object.getOwnPropertySymbols(e);n&&(t=t.filter(function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable})),a.push.apply(a,t)}return a}function l(e){for(var n=1;n<arguments.length;n++){var a=null!=arguments[n]?arguments[n]:{};n%2?o(Object(a),!0).forEach(function(n){r(e,n,a[n])}):Object.getOwnPropertyDescriptors?Object.defineProperties(e,Object.getOwnPropertyDescriptors(a)):o(Object(a)).forEach(function(n){Object.defineProperty(e,n,Object.getOwnPropertyDescriptor(a,n))})}return e}function p(e,n){if(null==e)return{};var a,t,r=function(e,n){if(null==e)return{};var a,t,r={},o=Object.keys(e);for(t=0;t<o.length;t++)a=o[t],n.indexOf(a)>=0||(r[a]=e[a]);return r}(e,n);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(t=0;t<o.length;t++)a=o[t],n.indexOf(a)>=0||Object.prototype.propertyIsEnumerable.call(e,a)&&(r[a]=e[a])}return r}var i=t.createContext({}),s=function(e){var n=t.useContext(i),a=n;return e&&(a="function"==typeof e?e(n):l(l({},n),e)),a},c=function(e){var n=s(e.components);return t.createElement(i.Provider,{value:n},e.children)},u={inlineCode:"code",wrapper:function(e){var n=e.children;return t.createElement(t.Fragment,{},n)}},g=t.forwardRef(function(e,n){var a=e.components,r=e.mdxType,o=e.originalType,i=e.parentName,c=p(e,["components","mdxType","originalType","parentName"]),g=s(a),m=r,d=g["".concat(i,".").concat(m)]||g[m]||u[m]||o;return a?t.createElement(d,l(l({ref:n},c),{},{components:a})):t.createElement(d,l({ref:n},c))});function m(e,n){var a=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var o=a.length,l=new Array(o);l[0]=g;var p={};for(var i in n)hasOwnProperty.call(n,i)&&(p[i]=n[i]);p.originalType=e,p.mdxType="string"==typeof e?e:r,l[1]=p;for(var s=2;s<o;s++)l[s]=a[s];return t.createElement.apply(null,l)}return t.createElement.apply(null,a)}g.displayName="MDXCreateElement"},4660(e,n,a){a.r(n),a.d(n,{assets:()=>i,contentTitle:()=>l,default:()=>u,frontMatter:()=>o,metadata:()=>p,toc:()=>s});var t=a(8168),r=(a(6540),a(5680));const o={},l="Profiling Rust Memory Usage with Jemalloc",p={unversionedId:"rust-jemalloc-support",id:"rust-jemalloc-support",title:"Profiling Rust Memory Usage with Jemalloc",description:"Our jemalloc integration makes it possible to profile heap usage of",source:"@site/docs/rust-jemalloc-support.md",sourceDirName:".",slug:"/rust-jemalloc-support",permalink:"/docs/rust-jemalloc-support",draft:!1,editUrl:"https://github.com/parca-dev/parca.dev/edit/main/docs/rust-jemalloc-support.md",tags:[],version:"current",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Java Support",permalink:"/docs/java-support"},next:{title:"Security",permalink:"/docs/parca-agent-security"}},i={},s=[{value:"Using jemalloc and rust-jemalloc-pprof",id:"using-jemalloc-and-rust-jemalloc-pprof",level:2},{value:"Exposing pprof profiles with http:",id:"exposing-pprof-profiles-with-http",level:2},{value:"Uploading symbols with <code>parca-debuginfo</code> (only if not using",id:"uploading-symbols-with-parca-debuginfo-only-if-not-using",level:2},{value:"Scraping with Parca",id:"scraping-with-parca",level:2}],c={toc:s};function u({components:e,...n}){return(0,r.yg)("wrapper",(0,t.A)({},c,n,{components:e,mdxType:"MDXLayout"}),(0,r.yg)("h1",{id:"profiling-rust-memory-usage-with-jemalloc"},"Profiling Rust Memory Usage with Jemalloc"),(0,r.yg)("p",null,"Our jemalloc integration makes it possible to profile heap usage of\nRust programs, as long as you are willing to use the jemalloc\nallocator."),(0,r.yg)("h1",{id:"setup-instructions"},"Setup Instructions"),(0,r.yg)("h2",{id:"using-jemalloc-and-rust-jemalloc-pprof"},"Using jemalloc and rust-jemalloc-pprof"),(0,r.yg)("p",null,"Add the\n",(0,r.yg)("a",{parentName:"p",href:"https://crates.io/crates/jemalloc-pprof"},"jemalloc_pprof"),"\nand ",(0,r.yg)("a",{parentName:"p",href:"https://crates.io/crates/tikv-jemallocator"},"tikv-jemallocator"),"\npackages to your project. Make sure the latter has the ",(0,r.yg)("inlineCode",{parentName:"p"},"profiling")," and\n",(0,r.yg)("inlineCode",{parentName:"p"},"unprefixed_malloc_on_supported_platforms")," features:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-bash"},"cargo add jemalloc_pprof\ncargo add tikv-jemallocator --features profiling,unprefixed_malloc_on_supported_platforms\n")),(0,r.yg)("p",null,"Then, in y
1our program's ",(0,r.yg)("inlineCode",{parentName:"p"},"main.rs")," set your global allocator to\njemalloc and configure it with the special ",(0,r.yg)("inlineCode",{parentName:"p"},"malloc_conf")," symbol:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-rust"},'#[global_allocator]\nstatic ALLOC: tikv_jemallocator::Jemalloc = tikv_jemallocator::Jemalloc;\n\n#[unsafe(export_name = "malloc_conf")]\n#[allow(non_upper_case_globals)]\npub static malloc_conf: &[u8] = b"prof:true,prof_active:true,lg_prof_sample:19\\0";\n')),(0,r.yg)("h2",{id:"exposing-pprof-profiles-with-http"},"Exposing pprof profiles with http:"),(0,r.yg)("p",null,"Call the ",(0,r.yg)("inlineCode",{parentName:"p"},"dump_pprof")," method to dump profiles to memory. We\nrecommending exposing an HTTP interface for these profiles that can be\nscraped by Parca."),(0,r.yg)("p",null,"Here is how to do so using Axum:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-rust"},'async fn handle_get_heap() -> Result<impl IntoResponse, (StatusCode, String)> {\n    let mut prof_ctl = jemalloc_pprof::PROF_CTL\n        .as_ref()\n        .ok_or((\n            StatusCode::INTERNAL_SERVER_ERROR,\n            "Profiling not available".to_string(),\n        ))?\n        .lock()\n        .await;\n\n    let pprof = prof_ctl\n        .dump_pprof()\n        .map_err(|err| (StatusCode::INTERNAL_SERVER_ERROR, err.to_string()))?;\n\n    Ok(pprof)\n}\n\nfn main() {\n    let app = Router::new().route("/debug/pprof/heap", get(handle_get_heap));\n\n    let rt = Runtime::new().unwrap();\n\n    rt.spawn(async {\n        let listener = tokio::net::TcpListener::bind("127.0.0.1:3000")\n            .await\n            .expect("Failed to bind to port 3000");\n        axum::serve(listener, app).await.expect("Server failed");\n    });\n}\n\n')),(0,r.yg)("h2",{id:"uploading-symbols-with-parca-debuginfo-only-if-not-using"},"Uploading symbols with ",(0,r.yg)("inlineCode",{parentName:"h2"},"parca-debuginfo")," (only if not using"),(0,r.yg)("p",null,(0,r.yg)("inlineCode",{parentName:"p"},"parca-agent"),")."),(0,r.yg)("p",null,"If you are already using ",(0,r.yg)("inlineCode",{parentName:"p"},"parca-agent"),", all relevant symbols will be\nfound and uploaded to the backend automatically. Otherwise, you will\nneed to manually upload them using the ",(0,r.yg)("inlineCode",{parentName:"p"},"parca-debuginfo")," CLI. For example,\nassuming Parca is running on localhost:"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-bash"},"parca-debuginfo upload --store-address=localhost:7070 --insecure path/to/your/binary\n")),(0,r.yg)("h2",{id:"scraping-with-parca"},"Scraping with Parca"),(0,r.yg)("p",null,"In order to continually scrape the endpoint, add a stanza like the\nfollowing to your ",(0,r.yg)("inlineCode",{parentName:"p"},"parca.yaml"),", assuming (as in the example above) the\nprofiles are being served via HTTP on ",(0,r.yg)("inlineCode",{parentName:"p"},"127.0.0.1:3000"),":"),(0,r.yg)("pre",null,(0,r.yg)("code",{parentName:"pre",className:"language-yaml"},'scrape_configs:\n  - job_name: "rjemp"\n    scrape_interval: "10s"\n    static_configs:\n      - targets: [ \'127.0.0.1:3000\' ]\n    profiling_config:\n      pprof_config:\n        heap:\n          enabled: true\n          path: /debug/pprof/heap\n')),(0,r.yg)("p",null,"This should cause profiles to appear in the Parca UI."))}u.isMDXComponent=!0}}]);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.