sparkline这个单词,我第一次看的时候,也不知道这什么意思啊,以前根本没听过啊,但是这真真实实的出现在了redis的代码中了,刚刚开始以为这也是属于普通的队列嘛,就把他分在了struct包里了。好来分析完了,与原本我所想的差太大了。sparkline英文中的意思
sparkline这个单词,我第一次看的时候,也不知道这什么意思啊,以前根本没听过啊,但是这真真实实的出现在了redis的代码中了,刚刚开始以为这也是属于普通的队列嘛,就把他分在了struct包里了。好来分析完了,与原本我所想的差太大了。sparkline英文中的意思“微线图”,这么说吧,类似于折线图,由一个一个信息点构成。所以看到这个意思,你或许就明白了sparkline.c是干什么用的了吧,就是画图用的。我们看看这个画图的内部结构是什么,画图需要的元素是哪些:
/* sparkline.h -- ASCII Sparklines header file * * --------------------------------------------------------------------------- * * Copyright(C) 2011-2014 Salvatore Sanfilippo <antirez@gmail.com> * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #ifndef __SPARKLINE_H #define __SPARKLINE_H /* sparkline是一类信息体积小和数据密度高的图表。目前它被用作一些测量, *相关的变化的信息呈现的方式,如平均温度,股市交投活跃。sparkline常常以一组多条的形式出现在柱状图,折线图当中。 *可以理解为一个图线信息 */ /* A sequence is represented of many "samples" */ /* 可以理解为图像上的一个信息点,有文字,有值的大小 */ struct sample { double value; char *label; }; /* 图线信息结构体,包括n个元素点,可以据此描述出图,绘图的可不是直接按点和值直接绘制的 */ struct sequence { //当前元素点个数 int length; //总共的文字个数,有些点没有label描述,为NULL int labels; //元素点列表 struct sample *samples; //元素中的最大值,最小值 double min, max; }; /* 定义了一些渲染图时候一些属性操作设置 */ #define SPARKLINE_NO_FLAGS 0 #define SPARKLINE_FILL 1 /* Fill the area under the curve. */ #define SPARKLINE_LOG_SCALE 2 /* Use logarithmic scale. */ struct sequence *createSparklineSequence(void); //创建图线序列结构体 void sparklineSequenceAddSample(struct sequence *seq, double value, char *label); //在图线序列中添加一个信息点 void freeSparklineSequence(struct sequence *seq); //释放图线序列 sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags); //渲染图线序列为一个图,其实就是得到一个字符串组成的图 sds sparklineRender(sds output, struct sequence *seq, int columns, int rows, int flags); //方法同上,只是少可一个偏移量 #endif /* __SPARKLINE_H */
/* sparkline.c -- ASCII Sparklines * This code is modified from http://github.com/antirez/aspark and adapted * in order to return SDS strings instead of outputting directly to * the terminal. * * ---------------------------------------------------------------------------
aspark is a C program to display ASCII Sparklines. It is completely useless in 2011.
$ ./aspark 1,2,3,4,10,7,6,5 `-_ __-` `
$ ./aspark 1,2,3,4,5,6,7,8,9,10,10,8,5,3,1 --rows 4 _-``_ _` -` ` _-` `_
$ ./aspark 1,2,3,4,5,6,7,8,9,10,10,8,5,3,1 --rows 4 --fill _o##_ _#||||| o#|||||||# _o#||||||||||#_
/* Render part of a sequence, so that render_sequence() call call this function * with differnent parts in order to create the full output without overflowing * the current terminal columns. */ /* 渲染出这个图线信息 */ sds sparklineRenderRange(sds output, struct sequence *seq, int rows, int offset, int len, int flags) { int j; double relmax = seq->max - seq->min; int steps = charset_len*rows; int row = 0; char *chars = zmalloc(len); int loop = 1; int opt_fill = flags & SPARKLINE_FILL; int opt_log = flags & SPARKLINE_LOG_SCALE; if (opt_log) { relmax = log(relmax+1); } else if (relmax == 0) { relmax = 1; } while(loop) { loop = 0; memset(chars,' ',len); for (j = 0; j < len; j++) { struct sample *s = &seq->samples[j+offset]; //value派上用处了 double relval = s->value - seq->min; int step; if (opt_log) relval = log(relval+1); //最后会算出相关的step step = (int) (relval*steps)/relmax; if (step < 0) step = 0; if (step >= steps) step = steps-1; if (row < rows) { /* Print the character needed to create the sparkline */ /* step控制输出的字符是哪一个 */ int charidx = step-((rows-row-1)*charset_len); loop = 1; if (charidx >= 0 && charidx < charset_len) { chars[j] = opt_fill ? charset_fill[charidx] : charset[charidx]; } else if(opt_fill && charidx >= charset_len) { //用"|"填充内容,更加可视化 chars[j] = '|'; } } else { /* Labels spacing */ if (seq->labels && row-rows < label_margin_top) { loop = 1; break; } /* Print the label if needed. */ if (s->label) { int label_len = strlen(s->label); int label_char = row - rows - label_margin_top; if (label_len > label_char) { loop = 1; chars[j] = s->label[label_char]; } } } } if (loop) { row++; output = sdscatlen(output,chars,len); output = sdscatlen(output,"\n",1); } } zfree(chars); return output; }