Ubuntu上玩转graphviz绘图工具

http://blog.csdn.net/tao_627/article/details/26128001

简介

关于Graphviz: Graphviz(英文:Graph Visualization Software的缩写)是一个由AT&T实验室启动的开源工具包,用于绘制DOT语言脚本描述的图形。它也提供了供其它软件使用的库。Graphviz是一个自由软件,其授权为Eclipse Public License。其Mac版本曾经获得2004年的苹果设计奖。

Graphviz是大名鼎鼎的贝尔实验室的几位牛人开发的一个画图工具。它的理念和一般的“所见即所得”的画图工具不一样,是“所想即所得”。
Graphviz提供了dot语言来编写绘图脚本。dot的语言专门用来定义关系。我们必须先在某个文件中写上代码,最后调用命令行生成。没有找到可边写边改的集成环境。
关于dot的具体语法参看官方文档,这里就不多说。这里仅用来入门。

http://www.graphviz.org/

另外也有专门渲染DOT脚本的浏览器xdo,直接在窗口渲染,不需要生成图像文件,强烈推荐。

很多图都比较适合用DOT来定义,比如流程图,组织关系图,类图,状态转换图等等。

在刚接触DOT不到3天的时间里,我就分别在代码性能优化,协议栈状态机定义两件事情用到了DOT,感觉非常方便。

性能优化:gprof可以对一个程序运行时进行profiling,生成报告,包括函数调用关系,每个函数被调用的次数,花费的时间。但这个报告是文本的,不够直观。可以通过一个gprof2dot.py脚本,把gprof的输出翻译成一个DOT文件,然后再用Graphviz转成图片或者直接用xdot来查看。

安装graphviz     
sudo apt-get install graphviz graphviz-doc
这样会安装dot语言的执行文件,执行文件路径在
/usr/bin/dot
绘图方法
先根据业务需要编写dot文件,参见下面的示例部分,然后编译运行。输出格式可以根据自己的需要来灵活选择
例如test.dot, 产生图片:
dot -Tpng test.dot -o test.png
dot -Tsvg test.dot -o test.svg
dot test.dot -Tpdf -o test.pdf

典型示例(更多例子可以参见官方文档)

1.Fancy Graph

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. digraph G {   
  2.     edge[fontname="FangSong"];  
  3.     node[peripheries=2fontname="FangSong"];  
  4.     size="16, 16";  
  5.     main[shape="box"];  
  6.     main[label="从这里开始"]  
  7.     main->parse[weight=8]  
  8.     parse->execute;  
  9.     main->init[style=dotted];                                                                                                                                               
  10.     main->cleanup;  
  11.     execute->{make_string; printf;}  
  12.     edge[color=red];  
  13.     init->make_string[label="1000次的感动"];  
  14.     main->printf[label="make a \n string"];  
  15.           
  16.     node[shape=box,style=filled,color=".7 .3 1.0"];  
  17.     execute->compare;  
  18. }         
效果图


2.Polygon Graph

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. digraph G{  
  2.     size = "4, 4"  
  3.     a->b->c;  
  4.     b->d;  
  5.           
  6.     a[shape=polygonsides=5peripheries=3color=lightbluestyle=filled];  
  7.     c[shape=polygonsides=4skew=0.4, label="hello world"];  
  8.     d[shape=invtriangle];                                                                                                                                                   
  9.     e[shape=polygonside=4distortion=.7];  
  10.     }     


效果图


3.list Graph

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. digraph G{  
  2.     node[shape=recordheight=.1];  
  3.     node0[label="<f0> |<f1> G|<f2> "];  
  4.     node1[label="<f0> |<f1> E|<f2> "];  
  5.     node2[label="<f0> |<f1> B|<f2> "];  
  6.     node3[label="<f0> |<f1> F|<f2> "];  
  7.     node4[label="<f0> |<f1> R|<f2> "];  
  8.     node5[label="<f0> |<f1> H|<f2> "];  
  9.     node6[label="<f0> |<f1> Y|<f2> "];  
  10.     node7[label="<f0> |<f1> A|<f2> "];  
  11.     node8[label="<f0> |<f1> C|<f2> "];                                                                                                                                      
  12.           
  13.     "node0":f2->"node4":f1;  
  14.     "node0":f0->"node1":f1;  
  15.     "node1":f0->"node2":f1;  
  16.     "node1":f2->"node3":f1;  
  17.     "node2":f2->"node8":f1;  
  18.     "node2":f0->"node7":f1;  
  19.     "node4":f2->"node6":f1;  
  20.     "node4":f0->"node5":f1;  
  21. }         



4.hash table Graph

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. digraph G {   
  2.     nodesep=.05;  
  3.     rankdir=LR;  
  4.           
  5.     node[shape=recordwidth=.1, height=.1];  
  6.     node0[label="<f0> |<f1> |<f2> |<f3> |<f4> |<f5> |<f6> |"height=2.5]  
  7.     node[width=1.5];  
  8.     node1[label="{<n> n14 | 719 |<p>}"];  
  9.     node2[label="{<n> a1 | 719 |<p>}"];  
  10.     node3[label="{<n> i9 | 512 |<p>}"];  
  11.     node4[label="{<n> e5 | 632 |<p>}"];  
  12.     node5[label="{<n> t20 | 959 |<p>}"];  
  13.     node6[label="{<n> o15 | 794 |<p>}"];  
  14.     node7[label="{<n> s19 | 659 |<p>}"];  
  15.           
  16.     node0:f0->node1:n;  
  17.     node0:f1->node2:n;  
  18.     node0:f2->node3:n;  
  19.     node0:f5->node4:n;  
  20.     node0:f6->node5:n;  
  21.     node2:p->node6:n;  
  22.     node4:p->node7:n;                                                                                                                                                       
  23. }       


5.Process Graph

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. digraph G {   
  2.     subgraph cluster0 {  
  3.         node[style=filledcolor=white];  
  4.         style=filled;  
  5.         color=lightgrey;  
  6.         a0->a1->a2->a3;  
  7.         label="process #1";  
  8.     }     
  9.           
  10.     subgraph cluster1 {  
  11.         node[style=filled];  
  12.         color=blue;  
  13.         b0->b1->b2->b3;  
  14.         label="process #2";  
  15.     }     
  16.           
  17.     start->a0;  
  18.     start->b0;  
  19.     a1->b3;  
  20.     b2->a3;  
  21.     a3->end;  
  22.     b3->end;  
  23.           
  24.     start[shape=Mdiamond];  
  25.     end[shape=Msquare];                                                                                                                                                     
  26. }         


6.directed Graph

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. digraph G {   
  2.     {a b c} -> {d e f g}                                                                                                                                                    
  3. }   


7.化学分子式

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. graph s{  
  2.     C_0 -- H_0;  
  3.     C_0 -- H_1;  
  4.     C_0 -- H_2;  
  5.     C_0 -- C_1;  
  6.     C_1 -- H_3;  
  7.     C_1 -- H_4;  
  8.     C_1 -- H_5;  
  9. }  

8.函数调用关系图

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. digraph s {  
  2.     node [shape=ellipse, style=filled, color="#40e0d0"];  
  3.     edge [color="#606060", penwidth=3];  
  4.     main [color=green];  
  5.     main -> init[color=blue, label="hello, I'm \llable of edge"];  
  6.     main -> mainloop;  
  7.     main -> exit;  
  8.     init -> a_init;  
  9.     init -> b_init;  
  10.     init -> c_init;  
  11.     mainloop -> select;  
  12. }  

这个是有向图(directional graph), 脚本的第一个词需要换成"digraph"。常用的属性有color, style, shape, penwidth, label等。label中 \r, \l, \n 都表示换行,但对齐方式分别是 右对齐,左对齐,居中


9.ATS中插件collapsed_connection的流程图,一个更复杂的例子

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. digraph collapsed_connection {    
  2.   accept -> TS_HTTP_POST_REMAP_HOOK;  
  3.   TS_HTTP_POST_REMAP_HOOK -> "check request method (and header)";  
  4.                                   
  5.   "check request method (and header)" -> "get CacheUrl hash_key using MurmurHash3" [label = "GET request (required_header present)"];  
  6.   "check request method (and header)" -> "pass request" [label = "others"];  
  7.   "get CacheUrl hash_key using MurmurHash3" -> "check hash_key from hashTable";  
  8.   "check hash_key from hashTable" -> "lock URL in hashTable" [label = "not found"];  
  9.   "check hash_key from hashTable" -> "pass request" [label = "found, but marked pass"];  
  10.   "check hash_key from hashTable" -> "check hash_key from hashTable" [label = "locked or unable to get mutex, wait insert_lock_retry_time"];  
  11.   "lock URL in hashTable" -> TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK;  
  12.   TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK -> "remove URL from hashTable(1)" [label = "hit_fresh or skipped"];  
  13.   TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK -> "request origin server" [label = "miss or stale"];  
  14.   "request origin server" -> TS_HTTP_READ_RESPONSE_HDR_HOOK;  
  15.   TS_HTTP_READ_RESPONSE_HDR_HOOK -> "remove URL from hashTable(1)" [label = "not 200/OK response"];  
  16.   TS_HTTP_READ_RESPONSE_HDR_HOOK -> "check read_while_writer config";  
  17.   "check read_while_writer config" -> "remove URL from hashTable(1)" [label = "enabled"];  
  18.   "check read_while_writer config" -> TS_HTTP_TXN_CLOSE_HOOK [label = "disabled"];  
  19.   TS_HTTP_READ_RESPONSE_HDR_HOOK -> "mark pass in hashTable" [label = "non-cacheable"];  
  20.   "remove URL from hashTable(1)" -> TS_HTTP_TXN_CLOSE_HOOK;  
  21.   "mark pass in hashTable" -> TS_HTTP_TXN_CLOSE_HOOK;  
  22.   "pass request" -> TS_HTTP_TXN_CLOSE_HOOK;  
  23.   TS_HTTP_TXN_CLOSE_HOOK -> "remove URL from hashTable(2)";  
  24.   TS_HTTP_TXN_CLOSE_HOOK -> "check keep_pass_record_time" [label = "non-cacheable"];  
  25.   "check keep_pass_record_time" -> "add into KeepPassList" [label = "> 0"];  
  26.   "check keep_pass_record_time" -> "remove URL from hashTable(2)" [label = "= 0"];  
  27.   "add into KeepPassList" -> "transaction close";  
  28.   "remove URL from hashTable(2)" -> "transaction close";  
  29.   "transaction close" -> accept;                                                                                                                                           
  30.                                   
  31.   TS_HTTP_POST_REMAP_HOOK [shape = box];  
  32.   TS_HTTP_CACHE_LOOKUP_COMPLETE_HOOK[shape = box];  
  33.   TS_HTTP_READ_RESPONSE_HDR_HOOK [shape = box];  
  34.   TS_HTTP_TXN_CLOSE_HOOK [shape = box];  
  35.                                   
  36.   "check request method (and header)" [shape = diamond];  
  37.   "check hash_key from hashTable" [shape = diamond];  
  38.   "check read_while_writer config" [shape = diamond];  
  39.   "check keep_pass_record_time" [shape = diamond];  
  40. }   



注意事项

1.中文乱码

graphviz默认情况下对中文支持不好,如果代码中有中文,则必须使用UTF-8的格式保存文件,并且在代码中指定字体。

进一步深究可以查看官方文档

http://www.graphviz.org/Documentation.PHP

下面给出几个颇具震撼力的效果图,来自官网文档




  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值