From a8f996c605c181e5adae0de24b235d463825beab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ludovic=20Court=C3=A8s?= Date: Sun, 21 Jun 2015 23:25:19 +0200 Subject: [PATCH] size: Add '--map-file' option. * guix/scripts/size.scm (profile->page-map): New procedures. (show-help, %options): Add --map-file. (guix-size): Honor it. * doc/guix.texi (Invoking guix size): Document it. * doc/images/coreutils-size-map.png: New file. * doc.am (dist_infoimage_DATA): Add it. --- doc.am | 4 ++- doc/guix.texi | 15 ++++++++- doc/images/coreutils-size-map.png | Bin 0 -> 6755 bytes guix/scripts/size.scm | 51 +++++++++++++++++++++++++++++- 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 doc/images/coreutils-size-map.png diff --git a/doc.am b/doc.am index ee896c189b8ec39b8cf85bf12db034054231b0b2..9d72b11caa211d742cdf19d4086c06375bb0b192 100644 --- a/doc.am +++ b/doc.am @@ -40,7 +40,9 @@ doc/os-config-%.texi: gnu/system/examples/%.tmpl cp "$<" "$@" infoimagedir = $(infodir)/images -dist_infoimage_DATA = doc/images/bootstrap-graph.png +dist_infoimage_DATA = \ + doc/images/bootstrap-graph.png \ + doc/images/coreutils-size-map.png # Try hard to obtain an image size and aspect that's reasonable for inclusion # in an Info or PDF document. diff --git a/doc/guix.texi b/doc/guix.texi index a669464feb43de634d3861d6a4b02b492160bb56..f9c9f2ab938a8e5a3392d0747372c7a655586301 100644 --- a/doc/guix.texi +++ b/doc/guix.texi @@ -4038,10 +4038,23 @@ reports information based on information about the available substitutes (@pxref{Substitutes}). This allows it to profile disk usage of store items that are not even on disk, only available remotely. -A single option is available: +The available options are: @table @option +@item --map-file=@var{file} +Write to @var{file} a graphical map of disk usage as a PNG file. + +For the example above, the map looks like this: + +@image{images/coreutils-size-map,5in,, map of Coreutils disk usage +produced by @command{guix size}} + +This option requires that +@uref{http://wingolog.org/software/guile-charting/, Guile-Charting} be +installed and visible in Guile's module search path. When that is not +the case, @command{guix size} fails as it tries to load it. + @item --system=@var{system} @itemx -s @var{system} Consider packages for @var{system}---e.g., @code{x86_64-linux}. diff --git a/doc/images/coreutils-size-map.png b/doc/images/coreutils-size-map.png new file mode 100644 index 0000000000000000000000000000000000000000..21d73a84587fec3ee66c4b78f14f9a8192f0ea62 GIT binary patch literal 6755 zcmeAS@N?(olHy`uVBq!ia0y~yVA5bXvE+iBL|cR!3Hq1$&z5uJaeGCi?9j-=Km>C!v9K0S9bBl&1wy|~oD;c! z{^vVB_n)Wz5^{R+pRsMKptCJQ!@`eueC~JE*XaMN<(EIH`Nws)7*{_V?` z58qD_-oe@+d5MvSzpnV%zo#jV?(Xb=AD7IJ^a=iOYQvr6%BZzw-y`BYA}sDkMU<@C zy*qmO<+WX1|6Yr`_RHB?{eQcCJ$w6x^_F+juWkJE=i9e$cakd)Y9F>x|D=ClxVd;Pww)YPx?r>DiOU-xXzitn4MIPWtZIP>5k zlZ2ia>%L7IAEurTU+?C!zO%P))0QncIXNL(Q(Go@=H<1zE{}`dvtq%A?)1BNUi=GM zIi=39wClJ0G+pi)|2IvYD*As@tLyS&A`B809M9%5X9-=0?8X30L!bffH(?T zIa_%pr%o!d7dO4Kn1Ml}BH#Z{yMs2uGYo-WH(i|;WgR@Hkb$A$<^hmFGX%h%x3_voay4 z65A(l{#jc;|Fh%d(m%4#i~Q#Q`c>6vJ+52BdwVx-+&J4j zUv7`}v**vBKYe<4ce%crnwo`0#17BpmlY37Gn~14b^UDR{vG+hAO5^K@p19>aABuD z^?MPYj(6T(zh}dbzn#bL?{eh$X|(fP;i@-x-!HfJnOHkB$erV7blBhf#qZkc-b@R6 zyZN=ayr29-&YBC{{H}rWbw3`yxVTtWR`&C!PaKNYWp5v z=jF_*{dzTgj`!5*)2k~hHAT9XEK&LPtGROSlqpLBH1_P>s~@||g=6KKHD5k|-n?bY z6aBD0dHZ)ypQfg!K7IdQfAYzm93}<>d+mRxulkuzniQby7IZDyUBD^lShRrCi_Xi} z5>*tRJTE@GdGWF6-bv>=AhVlI&NWl8N6nH8llyESAugv$o!S zdwYI*YO1P=ihxtuyE`-I%vp0a>t!m-@A_UhVR7;F^z`p%&F`C-nH8XqZ`f zd}qz+CEfG$S4GZyH-~7VqB|`M2HP)|n%7_w}U#Q36gPUfu1!b6Y0- z-rB$J@7k|>S57b68xr~T{@FQp6Z1_mFlt&MJ(aOTVzW_CUc zOUvBb+j=h-e|&WG`nuTc?CjaL)!SCD*8chRxpw%v7*1~P$)}&L4qJPvdhv%31v_K* zRegPRdb+-_la{vj;zf&ebah{bopU!$O--$Zr!npeI2jK7dGqUN`tkGn zd%it1c7MEzQ}Ottyq20b-i z{h5l=*GK+r&$g&N)+_u=`a_b4T<4SUa!yXpodpjM%`{FA3J(4`x4NoIFK*9|bJp*V z96L5ieg66j-qSKKFH22N-@bjjyj6+E``#I0{{H?>9ox5WcUxTf<%QtgQ~Rd4Esoq( zvNCEdA209I7#FZZMercxygldUA(`dz z9x6iN;n#26xbfphh2K#veSLmz?$s+-cJ}nxRD4Lt&er}dCgPfVYm26`^5L^*b*-&` zw~EL8_;_4iSy@>>cGs1wSC3ZCp5tE|6&>x~D|NJ|@%|Azr4Q1F#XT4wto+=+=h&ky zyZYMi_60xnzBl{BnS7Dy-f}fRm(Tv5Z?|c7!pQ7)|IPk$RqV;(u{|rYi8HNK2Fa00Bj9(;mbWw=b@51=R+uL#gjk&^QHqy%{(hBI>ZeVdjqSJ&0e{q*Ey(8?)xaq;o;0s;xi$-)8x z4$n7y{JlZF@}c#&@K|xDP z%Rh7PIR8LP&C#R;hYjcy5l;$2j z_THIeAZ_C+P^pwjr@b2BaC3lmHShhs1^-;T=wbg5B(CVv~mYRWB*RNh(8M12ACZnldq2b}rU%#&Y{LHsb{#lT&uCCV9Ra>`Sy|DM!hDV9vvVM!C z9C2ZAtM=ae?cW|8Y@RYjByHaH)%N`20V1i1 ziGm^`BErIl|8Hpv3=Uo#qV@gl?d|pd>wcZMwl@0lqeoxL&Yd}P=ER8rt*N1*pE9KxVJ{hii@WwCr_R*VZp@=kNWw&&p^)jeBj^fj4$0! zo;>ll`QnOe)!t;%{PvonQ>^^{Q2)+zSNw4I{n<7%6E4x>)0C?n3W0J zPvT%mh&Xxr^lYnAE!(;CY^%fG3qD?cs!`MC@99M8D__itslOB zJd_w39=0vg(AHkPVui-D>MwJYYiDTv4*bHQ7_~NR`Q@!!x1LNfdiLYA{{EVmmsFSe zmzSIG_P7w4{w4Cw@1k=_ZeL$6pTBF@u1l7-K`XBWJX{!mS=;)YXo=O`@AvE9KYCR3 ze4=m&4?xy&ssEk#8|OG`>bL`5wvEjjmA>`Il&7D*Isaq9xunJRN<}3le;zdRzxdbL*;&#f{e0`f z@`IJjOG32v^Vc7kqx|*jS8j2=E!(zz`|!b{_*u_^d^T-41_N()KAD1|q96^C{lD+N z-}n2S^gq>S@+@J$yli9rlwG^~wKODF9b{mbp|%D* z4A2~1;le$`aS|`Xfy+q+-2Lx7e=#)Mo%7FpT=L^PC(Bk&laKAUvLAplkMN9RmbR=$ z29ip-TMhj$7S^Q%-MX=s*-2rAuf^eB+{>JE*{;WYR9IZBt*NQl5)u~n>*vqNs3<9| zwa5GAzkm9)Y15`p-@i{knc`;lv0dwqBtyas1Cw53D=RA{C8eUGqN=@D7ObhTIGJfR z_uaq0zr)wZl@=Cqa&ss5aWC2O@nyu$+?EL)9UY?DVOzFr;aETU3)@ys6G^F62TBWGam78y$%X1mUOA-0w)eUky>GNV%`_a^)IDw z-nyk1wPnSwU9<8YrSInK>6(B0+hKnDGqX&)*A-YXduHdnS+Ff`_6_H!;`?Ypq%HxLkU@d9mvTxTI_vuQ#t>1~T^RpP!$-y}cJNUi|vis~L=|QCbM6`J$hi ze>|S^BE04JO2z{=Q>IR3Wo51Xa?yRx7K5~H&*h<^b@JS~y!?Fok{1(}FIO*~F!!FY zkWkUXL#@W?=awv6_R6+({;p&9ROguGN?rc{zx~85jmP=33fG6ygr=NbgU;p^TnKL}x+}=JuJv}`k8X|us zgrbXzKCKE}-PF`HXYSn1n>L-8Tq*==6g=%Uzc<4mv1$GK_Y;-fTV}T$=V3@lTeNsF zry?UGs9)dR{c%z-;+#_``d0EsjPbY@$qpEmy;GxlOk~8F8<; z+~dauKWr~wy7Z)I=Zr?HGuQoGcPle6eCgb%Emx=G9~d~Xy}f`uw)6a&rywng+9z*rZf3TwU}#WG(a4|tPf6|XEPL%w$v1!0vV2Kg z-79=rSWeE*e$(7()5HV?7k;18*4EZ3tS(j0eUXD_o_tWrt1BxXJ$kfk*|Hx$D%7@d zFdX1{!FyXrUq5{H)ieEnA}7k9US@vp>;yXzIX|8L$&-aEH{A+Y8RE13(xo7F_I74= zz5tP{moFdIUov&-)VjL5Y15{a1iQK(T@$%^&DyoKwYA#X+Ap*7Zfr<=a$;i3gzW3< ze*XTgEz_Hb`2K@wxf2L>2q_V|; zT%)6vP-jl?P)srU!Pq9Qt{iy~SMnRd1@X$opg0w;x}5bED1KvuB@p zx-N_tcH-jZK79DF{~U{hmJ|Q}oPZbrc=Gb)%(-*dUd`f{vpL~%;9_XIfKl?X9_Mzx zty{OgEU~guKYQ}z%P%i4zkU05e%&w4yY6a}@9wLeZ6D=VAXCj##qR&OUF7J|qZd_U zl_nY-W@9h_jo_UL@%(>&zUa@5Ic<;betC5}I9E?kPgGR2M5jM$ZC`iy=8YRYJv=UC zn3QZkaNxkBM~`}?&EMVJeEh;vyWej%-?g0I-ch=Tl2O62ZmVWy1@bH;ZiFST@ zyShI+7B5!*9OzqBRaH>|Vh0;sTNnHK-Me%D7254mA0BG;DUfNluXy(5#fywzjl93U zwDZgR&A0pe^ZESk+qa)TapJ`3)5f37*%%Uj{g^-H^T+g~Q>IMm>gwVYRtpIUQBhZa v{Z_doSVf$Hp<%{^7zVQDP~fAW|HQxK&Yxd7amqvn1_lOCS3j3^P6output-path drv output))))))) + +;;; +;;; Charts. +;;; + +;; Autoload Guile-Charting. +;; XXX: Use this hack instead of #:autoload to avoid compilation errors. +;; See . +(module-autoload! (current-module) + '(charting) '(make-page-map)) + +(define (profile->page-map profiles file) + "Write a 'page map' chart of PROFILES, a list of objects, to FILE, +the name of a PNG file." + (define (strip name) + (string-drop name (+ (string-length (%store-prefix)) 28))) + + (define data + (fold2 (lambda (profile result offset) + (match profile + (($ name self) + (let ((self (inexact->exact + (round (/ self (expt 2. 10)))))) + (values `((,(strip name) ,offset . ,self) + ,@result) + (+ offset self)))))) + '() + 0 + (sort profiles + (match-lambda* + ((($ _ _ total1) ($ _ _ total2)) + (> total1 total2)))))) + + ;; TRANSLATORS: This is the title of a graph, meaning that the graph + ;; represents a profile of the store (the "store" being the place where + ;; packages are stored.) + (make-page-map (_ "store profile") (pk data) + #:write-to-png file)) + ;;; ;;; Options. @@ -191,6 +230,8 @@ as \"guile:debug\" or \"gcc-4.8\" and return its store file name." (define (show-help) (display (_ "Usage: guix size [OPTION]... PACKAGE Report the size of PACKAGE and its dependencies.\n")) + (display (_ " + -m, --map-file=FILE write to FILE a graphical map of disk usage")) (display (_ " -s, --system=SYSTEM consider packages for SYSTEM--e.g., \"i686-linux\"")) (newline) @@ -207,6 +248,9 @@ Report the size of PACKAGE and its dependencies.\n")) (lambda (opt name arg result) (alist-cons 'system arg (alist-delete 'system result eq?)))) + (option '(#\m "map-file") #t #f + (lambda (opt name arg result) + (alist-cons 'map-file arg result))) (option '(#\h "help") #f #f (lambda args (show-help) @@ -230,6 +274,7 @@ Report the size of PACKAGE and its dependencies.\n")) (('argument . file) file) (_ #f)) opts)) + (map-file (assoc-ref opts 'map-file)) (system (assoc-ref opts 'system))) (match files (() @@ -239,7 +284,11 @@ Report the size of PACKAGE and its dependencies.\n")) (run-with-store store (mlet* %store-monad ((item (ensure-store-item file)) (profile (store-profile item))) - (display-profile* profile)) + (if map-file + (begin + (profile->page-map profile map-file) + (return #t)) + (display-profile* profile))) #:system system))) ((files ...) (leave (_ "too many arguments\n")))))))