From ec95f91c139107762a7eadc1d23a1fb0a8ccee2d Mon Sep 17 00:00:00 2001 From: kennytm Date: Thu, 14 Nov 2019 16:21:06 +0800 Subject: [PATCH] util/profile: remove github.com/lonng/pprof replacement (#13318) --- go.mod | 2 - go.sum | 23 +--- util/profile/flamegraph.go | 182 +++++++++++++++++++++++++++++++ util/profile/flamegraph_test.go | 96 ++++++++++++++++ util/profile/profile.go | 92 ++-------------- util/profile/testdata/test.pprof | Bin 0 -> 1206 bytes 6 files changed, 288 insertions(+), 107 deletions(-) create mode 100644 util/profile/flamegraph.go create mode 100644 util/profile/flamegraph_test.go create mode 100644 util/profile/testdata/test.pprof diff --git a/go.mod b/go.mod index 2c6e01937af95..d855de8222b7a 100644 --- a/go.mod +++ b/go.mod @@ -74,6 +74,4 @@ require ( sourcegraph.com/sourcegraph/appdash-data v0.0.0-20151005221446-73f23eafcf67 ) -replace github.com/google/pprof => github.com/lonng/pprof v0.0.0-20191012154247-04dfd648ce8d - go 1.13 diff --git a/go.sum b/go.sum index a7caa403be467..36adf1bde2c8c 100644 --- a/go.sum +++ b/go.sum @@ -5,7 +5,6 @@ github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f h1:5ZfJxyXo8KyX8 github.com/StackExchange/wmi v0.0.0-20180725035823-b12b22c5341f/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= -github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= @@ -14,9 +13,7 @@ github.com/blacktear23/go-proxyprotocol v0.0.0-20180807104634-af7a81e8dd0d h1:rQ github.com/blacktear23/go-proxyprotocol v0.0.0-20180807104634-af7a81e8dd0d/go.mod h1:VKt7CNAQxpFpSDz3sXyj9hY/GbVsQCr0sB3w59nE7lU= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20171208011716-f6d7a1f6fbf3/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= -github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= -github.com/client9/misspell v0.3.4 h1:ta993UF76GwbvJcIo3Y68y/M3WxlpEHPWIGDkJYwzJI= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa h1:OaNxuTZr7kxeODyLWsRMC+OD03aFUH+mW6r2d+MWa5Y= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= @@ -52,7 +49,6 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= @@ -87,6 +83,8 @@ github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/pprof v0.0.0-20190930153522-6ce02741cba3 h1:3CYI9xg87xNAD+es02gZxbX/ky4KQeoFBsNOzuoAQZg= +github.com/google/pprof v0.0.0-20190930153522-6ce02741cba3/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/shlex v0.0.0-20181106134648-c34317bd91bf/go.mod h1:RpwtwJQFrIEPstU94h88MWPXP2ektJZ8cZ0YntAmXiE= github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -111,15 +109,11 @@ github.com/grpc-ecosystem/grpc-gateway v1.9.5 h1:UImYN5qQ8tuGpGE16ZmjvcTtTw24zw1 github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6 h1:UDMh68UUwekSh5iP2OMhRRZJiiBccgV7axzUG8vi56c= -github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= -github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jeremywohl/flatten v0.0.0-20190921043622-d936035e55cf h1:Ut4tTtPNmInWiEWJRernsWm688R0RN6PFO8sZhwI0sk= github.com/jeremywohl/flatten v0.0.0-20190921043622-d936035e55cf/go.mod h1:4AmD/VxjWcI5SRB0n6szE2A6s2fsNHDLO0nAlMHgfLQ= github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= -github.com/json-iterator/go v1.1.6 h1:MrUvLMLTMxbqFJ9kzlvat/rYZqZnW3u4wkLzWTaFwKs= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.7 h1:KfgG9LzI+pYjr4xvmz/5H4FXjokeP+rlHLhv3iH62Fo= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= @@ -139,8 +133,6 @@ github.com/kr/pty v1.0.0/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/lonng/pprof v0.0.0-20191012154247-04dfd648ce8d h1:6Ike9EBxOFsCMMih14rQJmb7WPWdgRu4C0OLl6oRHwE= -github.com/lonng/pprof v0.0.0-20191012154247-04dfd648ce8d/go.mod h1:0vjxLpmyJvBwQbIQuxhHxmogQFpJvB9doVHvxFFfyoY= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= @@ -173,7 +165,6 @@ github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKw github.com/opentracing/opentracing-go v1.0.2 h1:3jA2P6O1F9UOrWVpwrIo17pu01KWvNWg4X946/Y5Zwg= github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/pelletier/go-toml v1.3.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= -github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8 h1:USx2/E1bX46VG32FIw034Au6seQ2fY9NEILmNh/UlQg= github.com/pingcap/check v0.0.0-20190102082844-67f458068fc8/go.mod h1:B1+S9LNcuMyLH/4HMTViQOJevkGiik3wW2AN9zb2fNQ= github.com/pingcap/check v0.0.0-20191107115940-caf2b9e6ccf4 h1:iRtOAQ6FXkY/BGvst3CDfTva4nTqh6CL8WXvanLdbu0= github.com/pingcap/check v0.0.0-20191107115940-caf2b9e6ccf4/go.mod h1:PYMCGwN0JHjoqGr3HrZoD+b8Tgx8bKnArhSq8YVzUMc= @@ -213,7 +204,6 @@ github.com/prometheus/client_golang v1.0.0 h1:vrDKnkGzuGvhNAL56c7DBz29ZL+KxnoR0x github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/prometheus/client_model v0.0.0-20170216185247-6f3806018612/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20171117100541-99fa1f4be8e5/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= -github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910 h1:idejC8f05m9MGOsuEi1ATq9shN03HrxNkD/luQvxCv8= github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE= github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= @@ -221,7 +211,6 @@ github.com/prometheus/common v0.0.0-20180518154759-7600349dcfe1/go.mod h1:daVV7q github.com/prometheus/common v0.4.1 h1:K0MGApIoQvMw27RTdJkPbr3JZ7DNbtxQNyi5STVM6Kw= github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= github.com/prometheus/procfs v0.0.0-20180612222113-7d6f385de8be/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= -github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d h1:GoAlyOgbOEIFdaDqxJVlbOQ1DtGmZWs/Qau0hIlk+WQ= github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= github.com/prometheus/procfs v0.0.2 h1:6LJUbpNm42llc4HRCuvApCSWB/WfhuNo9K98Q9sNGfs= github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= @@ -229,7 +218,6 @@ github.com/remyoudompheng/bigfft v0.0.0-20190512091148-babf20351dd7 h1:FUL3b97ZY github.com/remyoudompheng/bigfft v0.0.0-20190512091148-babf20351dd7/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44 h1:tB9NOR21++IjLyVx3/PCPhWMwqGNCMQEH96A6dMZ/gc= github.com/sergi/go-diff v1.0.1-0.20180205163309-da645544ed44/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v2.18.10+incompatible h1:cy84jW6EVRPa5g9HAHrlbxMSIjBhDSX0OFYyMYminYs= github.com/shirou/gopsutil v2.18.10+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= @@ -244,14 +232,12 @@ github.com/soheilhy/cmux v0.1.4 h1:0HKaf1o97UwFjHH9o5XsHUOF+tqmdA7KEzXLpiyaw0E= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72 h1:qLC7fQah7D6K1B0ujays3HV9gkFtllcxhzImRR7ArPQ= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= -github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8= github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/pflag v1.0.1 h1:aCvUg6QPl3ibpQUxyLkrEkCHtPqYJL4x9AuhqVqFis4= github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -270,9 +256,7 @@ github.com/uber/jaeger-client-go v2.15.0+incompatible h1:NP3qsSqNxh8VYr956ur1N/1 github.com/uber/jaeger-client-go v2.15.0+incompatible/go.mod h1:WVhlPFC8FDjOFMMWRy2pZqQJSXxYSwNYOkTr/Z6d3Kk= github.com/uber/jaeger-lib v1.5.0 h1:OHbgr8l656Ub3Fw5k9SWnBfIEwvoHQ+W2y+Aa9D1Uyo= github.com/uber/jaeger-lib v1.5.0/go.mod h1:ComeNDZlWwrWnDv8aPp0Ba6+uUTzImX/AauajbLI56U= -github.com/ugorji/go v1.1.2 h1:JON3E2/GPW2iDNGoSAusl1KDf5TRQ8k8q7Tp097pZGs= github.com/ugorji/go v1.1.2/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= -github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43 h1:BasDe+IErOQKrMVXab7UayvSlIpiyGwRvuX3EKYY7UA= github.com/ugorji/go/codec v0.0.0-20190204201341-e444a5086c43/go.mod h1:iT03XoTwV7xq/+UGwKO3UbC1nNNlopQiY61beSdrtOA= github.com/unrolled/render v0.0.0-20171102162132-65450fb6b2d3/go.mod h1:tu82oB5W2ykJRVioYsB+IQKcft7ryBr7w12qMBUPyXg= github.com/unrolled/render v0.0.0-20180914162206-b9786414de4d h1:ggUgChAeyge4NZ4QUw6lhHsVymzwSDJOZcE0s2X8S20= @@ -344,8 +328,6 @@ golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190909082730-f460065e899a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191010194322-b09406accb47 h1:/XfQ9z7ib8eEJX2hdgFTZJ/ntt0swNk5oYBziWeTCvY= -golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c h1:S/FtSvpNLtFBgjTqcKsRpsa6aVsI6iztaz1bQd9BJwE= golang.org/x/sys v0.0.0-20191029155521-f43be2a4598c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -362,7 +344,6 @@ golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3 golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5 h1:hKsoRgsbwY1NafxrwTs+k64bikrLBkAgPir1TNCj3Zs= golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191107010934-f79515f33823 h1:akkRBeitX2EZP59KdtKw310CI4WGPCNPyrLbE7WZA8Y= golang.org/x/tools v0.0.0-20191107010934-f79515f33823/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= diff --git a/util/profile/flamegraph.go b/util/profile/flamegraph.go new file mode 100644 index 0000000000000..f43b61572699d --- /dev/null +++ b/util/profile/flamegraph.go @@ -0,0 +1,182 @@ +// Copyright 2019 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package profile + +import ( + "fmt" + "math" + "sort" + + "github.com/google/pprof/profile" + "github.com/pingcap/tidb/types" + "github.com/pingcap/tidb/util/texttree" +) + +type flamegraphNode struct { + cumValue int64 + children map[uint64]*flamegraphNode +} + +func newFlamegraphNode() *flamegraphNode { + return &flamegraphNode{ + cumValue: 0, + children: make(map[uint64]*flamegraphNode), + } +} + +// add the value from a sample into the flamegraph DAG. +// This method should only be called on the root node. +func (n *flamegraphNode) add(sample *profile.Sample) { + // FIXME: we take the last sample value by default, but some profiles have multiple samples. + // - allocs: alloc_objects, alloc_space, inuse_objects, inuse_space + // - block: contentions, delay + // - cpu: samples, cpu + // - heap: alloc_objects, alloc_space, inuse_objects, inuse_space + // - mutex: contentions, delay + + value := sample.Value[len(sample.Value)-1] + if value == 0 { + return + } + + locs := sample.Location + + for { + n.cumValue += value + if len(locs) == 0 { + return + } + + // The previous implementation in TiDB identify nodes using location ID, + // but `go tool pprof` identify nodes using function ID. Should we follow? + loc := locs[len(locs)-1].ID + child, ok := n.children[loc] + if !ok { + child = newFlamegraphNode() + n.children[loc] = child + } + locs = locs[:len(locs)-1] + n = child + } +} + +type flamegraphNodeWithLocation struct { + *flamegraphNode + locID uint64 +} + +// sortedChildren returns a list of children of this node, sorted by each +// child's cumulative value. +func (n *flamegraphNode) sortedChildren() []flamegraphNodeWithLocation { + children := make([]flamegraphNodeWithLocation, 0, len(n.children)) + for locID, child := range n.children { + children = append(children, flamegraphNodeWithLocation{ + flamegraphNode: child, + locID: locID, + }) + } + sort.Slice(children, func(i, j int) bool { + a, b := children[i], children[j] + if a.cumValue != b.cumValue { + return a.cumValue > b.cumValue + } + return a.locID < b.locID + }) + + return children +} + +type flamegraphCollector struct { + rows [][]types.Datum + locations map[uint64]*profile.Location + total int64 + rootChild int +} + +func newFlamegraphCollector(p *profile.Profile) *flamegraphCollector { + locations := make(map[uint64]*profile.Location, len(p.Location)) + for _, loc := range p.Location { + locations[loc.ID] = loc + } + return &flamegraphCollector{locations: locations} +} + +func (c *flamegraphCollector) locationName(locID uint64) (funcName, fileLine string) { + loc := c.locations[locID] + if len(loc.Line) == 0 { + return "", "" + } + line := loc.Line[0] + funcName = line.Function.Name + fileLine = fmt.Sprintf("%s:%d", line.Function.Filename, line.Line) + return +} + +func (c *flamegraphCollector) collectChild( + node flamegraphNodeWithLocation, + depth int64, + indent string, + parentCumValue int64, + isLastChild bool, +) { + funcName, fileLine := c.locationName(node.locID) + c.rows = append(c.rows, types.MakeDatums( + texttree.PrettyIdentifier(funcName, indent, isLastChild), + percentage(node.cumValue, c.total), + percentage(node.cumValue, parentCumValue), + c.rootChild, + depth, + fileLine, + )) + + if len(node.children) == 0 { + return + } + + indent4Child := texttree.Indent4Child(indent, isLastChild) + children := node.sortedChildren() + for i, child := range children { + c.collectChild(child, depth+1, indent4Child, node.cumValue, i == len(children)-1) + } +} + +func (c *flamegraphCollector) collect(root *flamegraphNode) { + c.rows = append(c.rows, types.MakeDatums("root", "100%", "100%", 0, 0, "root")) + if len(root.children) == 0 { + return + } + + c.total = root.cumValue + indent4Child := texttree.Indent4Child("", false) + children := root.sortedChildren() + for i, child := range children { + c.rootChild = i + 1 + c.collectChild(child, 1, indent4Child, root.cumValue, i == len(children)-1) + } +} + +func percentage(value, total int64) string { + var ratio float64 + if total != 0 { + ratio = math.Abs(float64(value)/float64(total)) * 100 + } + switch { + case ratio >= 99.95 && ratio <= 100.05: + return "100%" + case ratio >= 1.0: + return fmt.Sprintf("%.2f%%", ratio) + default: + return fmt.Sprintf("%.2g%%", ratio) + } +} diff --git a/util/profile/flamegraph_test.go b/util/profile/flamegraph_test.go new file mode 100644 index 0000000000000..b73572f5f9fe2 --- /dev/null +++ b/util/profile/flamegraph_test.go @@ -0,0 +1,96 @@ +// Copyright 2019 PingCAP, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// See the License for the specific language governing permissions and +// limitations under the License. + +package profile + +import ( + "os" + "testing" + + . "github.com/pingcap/check" + "github.com/pingcap/tidb/types" +) + +type profileInternalSuite struct{} + +var _ = Suite(&profileInternalSuite{}) + +func TestT(t *testing.T) { + TestingT(t) +} + +func (s *profileInternalSuite) TestProfileToDatum(c *C) { + file, err := os.Open("testdata/test.pprof") + c.Assert(err, IsNil) + defer file.Close() + + data, err := (&Collector{}).profileReaderToDatums(file) + c.Assert(err, IsNil) + + datums := [][]types.Datum{ + types.MakeDatums(`root`, "100%", "100%", 0, 0, `root`), + types.MakeDatums(`├─runtime.main`, "87.50%", "87.50%", 1, 1, `c:/go/src/runtime/proc.go:203`), + types.MakeDatums(`│ └─main.main`, "87.50%", "100%", 1, 2, `Z:/main.go:46`), + types.MakeDatums(`│ ├─main.collatz`, "68.75%", "78.57%", 1, 3, `Z:/main.go:22`), + types.MakeDatums(`│ │ └─crypto/cipher.(*ctr).XORKeyStream`, "68.75%", "100%", 1, 4, `c:/go/src/crypto/cipher/ctr.go:84`), + types.MakeDatums(`│ │ ├─crypto/cipher.(*ctr).refill`, "62.50%", "90.91%", 1, 5, `c:/go/src/crypto/cipher/ctr.go:60`), + types.MakeDatums(`│ │ │ ├─crypto/aes.(*aesCipherAsm).Encrypt`, "56.25%", "90.00%", 1, 6, `c:/go/src/crypto/aes/cipher_asm.go:68`), + types.MakeDatums(`│ │ │ │ ├─crypto/aes.encryptBlockAsm`, "12.50%", "22.22%", 1, 7, `c:/go/src/crypto/aes/asm_amd64.s:49`), + types.MakeDatums(`│ │ │ │ ├─crypto/aes.encryptBlockAsm`, "6.25%", "11.11%", 1, 7, `c:/go/src/crypto/aes/asm_amd64.s:45`), + types.MakeDatums(`│ │ │ │ ├─crypto/aes.encryptBlockAsm`, "6.25%", "11.11%", 1, 7, `c:/go/src/crypto/aes/asm_amd64.s:39`), + types.MakeDatums(`│ │ │ │ ├─crypto/aes.encryptBlockAsm`, "6.25%", "11.11%", 1, 7, `c:/go/src/crypto/aes/asm_amd64.s:37`), + types.MakeDatums(`│ │ │ │ ├─crypto/aes.encryptBlockAsm`, "6.25%", "11.11%", 1, 7, `c:/go/src/crypto/aes/asm_amd64.s:43`), + types.MakeDatums(`│ │ │ │ ├─crypto/aes.encryptBlockAsm`, "6.25%", "11.11%", 1, 7, `c:/go/src/crypto/aes/asm_amd64.s:41`), + types.MakeDatums(`│ │ │ │ ├─crypto/aes.encryptBlockAsm`, "6.25%", "11.11%", 1, 7, `c:/go/src/crypto/aes/asm_amd64.s:51`), + types.MakeDatums(`│ │ │ │ └─crypto/aes.encryptBlockAsm`, "6.25%", "11.11%", 1, 7, `c:/go/src/crypto/aes/asm_amd64.s:11`), + types.MakeDatums(`│ │ │ └─crypto/aes.(*aesCipherAsm).Encrypt`, "6.25%", "10.00%", 1, 6, `c:/go/src/crypto/aes/cipher_asm.go:58`), + types.MakeDatums(`│ │ └─crypto/cipher.(*ctr).refill`, "6.25%", "9.09%", 1, 5, `c:/go/src/crypto/cipher/ctr.go:60`), + types.MakeDatums(`│ ├─main.collatz`, "12.50%", "14.29%", 1, 3, `Z:/main.go:30`), + types.MakeDatums(`│ │ └─main.collatz`, "12.50%", "100%", 1, 4, `Z:/main.go:22`), + types.MakeDatums(`│ │ └─crypto/cipher.(*ctr).XORKeyStream`, "12.50%", "100%", 1, 5, `c:/go/src/crypto/cipher/ctr.go:84`), + types.MakeDatums(`│ │ └─crypto/cipher.(*ctr).refill`, "12.50%", "100%", 1, 6, `c:/go/src/crypto/cipher/ctr.go:60`), + types.MakeDatums(`│ │ ├─crypto/aes.(*aesCipherAsm).Encrypt`, "6.25%", "50.00%", 1, 7, `c:/go/src/crypto/aes/cipher_asm.go:68`), + types.MakeDatums(`│ │ │ └─crypto/aes.encryptBlockAsm`, "6.25%", "100%", 1, 8, `c:/go/src/crypto/aes/asm_amd64.s:45`), + types.MakeDatums(`│ │ └─crypto/aes.(*aesCipherAsm).Encrypt`, "6.25%", "50.00%", 1, 7, `c:/go/src/crypto/aes/cipher_asm.go:65`), + types.MakeDatums(`│ │ └─crypto/internal/subtle.InexactOverlap`, "6.25%", "100%", 1, 8, `c:/go/src/crypto/internal/subtle/aliasing.go:33`), + types.MakeDatums(`│ │ └─crypto/internal/subtle.AnyOverlap`, "6.25%", "100%", 1, 9, `c:/go/src/crypto/internal/subtle/aliasing.go:20`), + types.MakeDatums(`│ └─main.collatz`, "6.25%", "7.14%", 1, 3, `Z:/main.go:20`), + types.MakeDatums(`│ └─runtime.memmove`, "6.25%", "100%", 1, 4, `c:/go/src/runtime/memmove_amd64.s:362`), + types.MakeDatums(`├─runtime.mstart`, "6.25%", "6.25%", 2, 1, `c:/go/src/runtime/proc.go:1146`), + types.MakeDatums(`│ └─runtime.systemstack`, "6.25%", "100%", 2, 2, `c:/go/src/runtime/asm_amd64.s:370`), + types.MakeDatums(`│ └─runtime.bgscavenge.func2`, "6.25%", "100%", 2, 3, `c:/go/src/runtime/mgcscavenge.go:315`), + types.MakeDatums(`│ └─runtime.(*mheap).scavengeLocked`, "6.25%", "100%", 2, 4, `c:/go/src/runtime/mheap.go:1446`), + types.MakeDatums(`│ └─runtime.(*mspan).scavenge`, "6.25%", "100%", 2, 5, `c:/go/src/runtime/mheap.go:589`), + types.MakeDatums(`│ └─runtime.sysUnused`, "6.25%", "100%", 2, 6, `c:/go/src/runtime/mem_windows.go:33`), + types.MakeDatums(`│ └─runtime.stdcall3`, "6.25%", "100%", 2, 7, `c:/go/src/runtime/os_windows.go:837`), + types.MakeDatums(`└─runtime.morestack`, "6.25%", "6.25%", 3, 1, `c:/go/src/runtime/asm_amd64.s:449`), + types.MakeDatums(` └─runtime.newstack`, "6.25%", "100%", 3, 2, `c:/go/src/runtime/stack.go:1038`), + types.MakeDatums(` └─runtime.gopreempt_m`, "6.25%", "100%", 3, 3, `c:/go/src/runtime/proc.go:2653`), + types.MakeDatums(` └─runtime.goschedImpl`, "6.25%", "100%", 3, 4, `c:/go/src/runtime/proc.go:2625`), + types.MakeDatums(` └─runtime.schedule`, "6.25%", "100%", 3, 5, `c:/go/src/runtime/proc.go:2524`), + types.MakeDatums(` └─runtime.findrunnable`, "6.25%", "100%", 3, 6, `c:/go/src/runtime/proc.go:2170`), + } + + for i, row := range data { + comment := Commentf("row %2d", i) + rowStr, err := types.DatumsToString(row, true) + c.Assert(err, IsNil, comment) + expectStr, err := types.DatumsToString(datums[i], true) + c.Assert(err, IsNil, comment) + + comment = Commentf("row %2d, actual (%s), expected (%s)", i, rowStr, expectStr) + equal, err := types.EqualDatums(nil, row, datums[i]) + c.Assert(err, IsNil, comment) + c.Assert(equal, IsTrue, comment) + } +} diff --git a/util/profile/profile.go b/util/profile/profile.go index 7286e1f070cad..d3b61c9c218d9 100644 --- a/util/profile/profile.go +++ b/util/profile/profile.go @@ -15,17 +15,13 @@ package profile import ( "bytes" - "fmt" "io" "runtime/pprof" "strconv" "strings" "time" - "github.com/google/pprof/graph" - "github.com/google/pprof/measurement" "github.com/google/pprof/profile" - "github.com/google/pprof/report" "github.com/pingcap/errors" "github.com/pingcap/tidb/types" "github.com/pingcap/tidb/util/texttree" @@ -35,39 +31,7 @@ import ( var CPUProfileInterval = 30 * time.Second // Collector is used to collect the profile results -type Collector struct { - Rows [][]types.Datum -} - -type perfNode struct { - Name string - Location string - Cum int64 - CumFormat string - Percent string - Children []*perfNode -} - -func (c *Collector) collect(node *perfNode, depth int64, indent string, rootChild int, parentCur int64, isLastChild bool) { - row := types.MakeDatums( - texttree.PrettyIdentifier(node.Name, indent, isLastChild), - node.Percent, - strings.TrimSpace(measurement.Percentage(node.Cum, parentCur)), - rootChild, - depth, - node.Location, - ) - c.Rows = append(c.Rows, row) - - indent4Child := texttree.Indent4Child(indent, isLastChild) - for i, child := range node.Children { - rc := rootChild - if depth == 0 { - rc = i + 1 - } - c.collect(child, depth+1, indent4Child, rc, node.Cum, i == len(node.Children)-1) - } -} +type Collector struct{} func (c *Collector) profileReaderToDatums(f io.Reader) ([][]types.Datum, error) { p, err := profile.Parse(f) @@ -78,59 +42,19 @@ func (c *Collector) profileReaderToDatums(f io.Reader) ([][]types.Datum, error) } func (c *Collector) profileToDatums(p *profile.Profile) ([][]types.Datum, error) { - err := p.Aggregate(true, true, true, true, true) + err := p.CheckValid() if err != nil { return nil, err } - rpt := report.NewDefault(p, report.Options{ - OutputFormat: report.Dot, - CallTree: true, - }) - g, config := report.GetDOT(rpt) - var nodes []*perfNode - nroots := 0 - rootValue := int64(0) - nodeArr := []string{} - nodeMap := map[*graph.Node]*perfNode{} - // Make all nodes and the map, collect the roots. - for _, n := range g.Nodes { - v := n.CumValue() - node := &perfNode{ - Name: n.Info.Name, - Location: fmt.Sprintf("%s:%d", n.Info.File, n.Info.Lineno), - Cum: v, - CumFormat: config.FormatValue(v), - Percent: strings.TrimSpace(measurement.Percentage(v, config.Total)), - } - nodes = append(nodes, node) - if len(n.In) == 0 { - nodes[nroots], nodes[len(nodes)-1] = nodes[len(nodes)-1], nodes[nroots] - nroots++ - rootValue += v - } - nodeMap[n] = node - // Get all node names into an array. - nodeArr = append(nodeArr, n.Info.Name) - } - // Populate the child links. - for _, n := range g.Nodes { - node := nodeMap[n] - for child := range n.Out { - node.Children = append(node.Children, nodeMap[child]) - } - } - rootNode := &perfNode{ - Name: "root", - Location: "root", - Cum: rootValue, - CumFormat: config.FormatValue(rootValue), - Percent: strings.TrimSpace(measurement.Percentage(rootValue, config.Total)), - Children: nodes[0:nroots], + root := newFlamegraphNode() + for _, sample := range p.Sample { + root.add(sample) } - c.collect(rootNode, 0, "", 0, config.Total, len(rootNode.Children) == 0) - return c.Rows, nil + col := newFlamegraphCollector(p) + col.collect(root) + return col.rows, nil } // cpuProfileGraph returns the CPU profile flamegraph which is organized by tree form diff --git a/util/profile/testdata/test.pprof b/util/profile/testdata/test.pprof new file mode 100644 index 0000000000000000000000000000000000000000..118d3f3faecf2eee890d4cd0e0719c68e1973731 GIT binary patch literal 1206 zcmV;n1WEfJiwFP!00004|7?>8;VNS_Y znWXUcUjn7z8G%wzz=A+&ymI&x?n=X$KxrsqQ7KWGWbnr$5t;#s$|Q@Yj*37ARH4m4 z8OutE0wH+&_u~ngCRzAi5-bZc$_i8~AOW8%PozXLmCj^I72;4EMX6Gml zLL>oF!I%GjjrW*?Z!)6C9MrI;)TvCW_|msW`Gw`7B~Tt3*ignOkQ!dT{tCAh;D?l8 z1sKP11u2j^9>4G^XGJ()5UdCjI3ZXAuUvVHvl3hkkE8@mY$}r!$QWLD=Okxk_$Op# zn8GP#ngSWeYhS+3nGCmx$SK1N&L}W)eU)mh-WVIFGC{l^&%H~`9qmOHhjUNh`fZUA z;1-C40JAu&00q*-i)Y^8#VYViO|S|ms0cQRXFn9I3YY4FRiT9~!KU!-PX(*NuOX`e zMJm`dp1*X0=d8n<;Q)1*!#U+n3S0xk&D!iynFzzRs!YJ4KOS)~;|6)F>oS4W<8 zwH%AmG+Mbi{O+t+N(l-u`f}#Nb8V)G^nj$@p=EvDa!uxIX~XH;ftEDfzE-ex+wqy< z*d1SM8s5MSoVLzATGg%2{r9Q9Muj1C zFD&WIf4Ju!VBU&vEvk>&0&3J)-X@D7gsZx5sa;2#6jCROstZd-;4P{i+ut)yZDvb? z(A+ixkDFWDnxEVA)Z=XMbl@@F(u$VevsJ?}O+9!~%kN!oi$K@Wa^esF(TZN*4tf>~ zza}=SM)9`mIR^L0Q9!krWjSk1Yi-p=Xn0Z(d;Fkd=%%?#o84-1{MAD}yW<@4d6~-4 zGVq_Z`#$SvBR3L3UTD-b5yjPoCChhpdr|cbeT~^&rZu+~v<@)c<+Wx{(-;sk_?U8$(7*`af}7H+#C@v%9>;{Pr4kx6NMAjbP6j U^Gx0SF8~1l|KH)aVpRwL08q0{