d 用于观察基本NFS指标的Dtrace代码段 - io延迟,大小,计数

nfs-high-level-detail.d
dtrace -qn '
  char m[string];
  BEGIN {
    m["rfs3_read"]  = 0x52;
    m["rfs3_write"] = 0x57;
    start = timestamp;
  }
  ::rfs3_read:op-read-start {
    self->t = timestamp; self->arg2r = args[2];  self->a = args[0]->ci_remote;
    @qiosz[m[probefunc], args[0]->ci_remote] = quantize(args[2]->count);
    @iops_by_host[m[probefunc], args[0]->ci_remote] = count();
    @iops_aggr[m[probefunc]] = count();
  }
  ::rfs3_write:op-write-start {
    self->t = timestamp; self->arg2w = args[2]; self->a = args[0]->ci_remote;
    @qiosz[m[probefunc], args[0]->ci_remote] = quantize(args[2]->count);
    @iops_by_host[m[probefunc], args[0]->ci_remote] = count();
    @iops_aggr[m[probefunc]] = count();
  }
  ::rfs3_read:op-read-done /self->t/ {
    this->delta = (timestamp - self->t) / 1000;
    this->b = self->arg2r->count;
    @q[m[probefunc], self->a] = quantize(this->delta);
    
    @av[m[probefunc], self->a] = avg(this->delta);
    self->a = 0; self->s = 0; self->arg2r = 0;
  }
  ::rfs3_write:op-write-done /self->t/ {
    this->delta = (timestamp - self->t) / 1000;
    this->b = self->arg2w->data.data_len;
    @q[m[probefunc], self->a] = quantize(this->delta);
    
    @av[m[probefunc], self->a]  = avg(this->delta);
    self->a = 0; self->s = 0; self->arg2w = 0;
  }
  END {
    this->elapsed_sec = (timestamp - start) / 1000000000;
    normalize(@iops_by_host, this->elapsed_sec);
    normalize(@iops_aggr, this->elapsed_sec);
    printa("\t   %c - IO size(b)  client: %s avg: %@d(b)%@d\n", @av, @qiosz);
    printa("\t   %c - latency(μS) client: %s avg: %@d(μS)%@d\n", @av, @q);
    printa("\t   %c - IOPS(#/sec) client: %s avg: %@d\n", @iops_by_host);
    printa("\t   %c - IOPS(#/sec) client: ALL avg: %@d\n", @iops_aggr);
  }'

d 字体在css中很棒

fontawesomr
ul li a:before{
    font-family:'FontAwesome';
    display:inline-block;
    vertical-align:top;
    padding:0 5px;
    content:'\f08e';
    font-size:30px;
    color:#000;
  -webkit-font-smothing:antialiazed;
}

li a[href*="facebook.com"]::before{
    content:'\f09a';
}

li a[href*="twitter.com"]::before{
    content:'\f09b';  // search for unicode 
}



























d Dtrace在内核中隐藏了SMB功能

smb-one-liners.d
# Measure latency in oplock-related functions
dtrace -qn '
  ::smb*oplock*:entry {
    self->in = timestamp
  }
  ::smb*oplock*:return /self->in/ {
    @[probefunc] = quantize(timestamp - self->in);
    self->in = 0;
  }'

# Measure how often timeouts happen in smb_oplock_wait_ack
dtrace -qn '
    long all, timedout;
  BEGIN {
      started = timestamp;
  }
  ::smb_oplock_wait_ack:entry {
    self->in_wait_ack = timestamp;
    all++;
  }
  /* Hit a timeout, bump count, only bump here once, because
   * this is a while() loop. Otherwise our total count may be smaller
   * than the timedout count.
   */ 
  ::smb_oplock_timedout:entry /self->in_wait_ack/ {
    @q["timeout"] = quantize(timestamp - self->in_wait_ack);
    timedout++;
    self->in_wait_ack = 0;
  }
  ::smb_oplock_wait_ack:return /self->in_wait_ack/ {
    @q["no timeout"] = quantize(timestamp - self->in_wait_ack);
    self->in_wait_ack = 0;
  }
  END {
    this->delta = timestamp - started;
    printf("runtime: %d seconds | %%timeout: %d\n",
        this->delta/1000000000, all > 0 ? (100*timedout)/all : 0);
  }'

d Dtrace在un_lun结构中捕获errstats kstat的信息片段

read-errstats-sd.d
dtrace -qn '
  ::sd_start_cmds:entry {
    v = args[0]->un_errstats->ks_data;
    vv = (struct sd_errstats *)v;
    @ = max(vv->sd_modeparmschanged.value.ui32);
  }'

d REM JS

REM自适应布局的JS

untitled
//designWidth:设计稿的实际宽度值,需要根据实际设置
//maxWidth:制作稿的最大宽度值,需要根据实际设置
//这段js的最后面有两个参数记得要设置,一个为设计稿实际宽度,一个为制作稿最大宽度,例如设计稿为750,最大宽度为750,则为(750,750)
;(function(designWidth, maxWidth) {
  var doc = document,
  win = window,
  docEl = doc.documentElement,
  remStyle = document.createElement("style"),
  tid;

  function refreshRem() {
    var width = docEl.getBoundingClientRect().width;
    maxWidth = maxWidth || 540;
    width>maxWidth && (width=maxWidth);
    var rem = width * 100 / designWidth;
    remStyle.innerHTML = 'html{font-size:' + rem + 'px;}';
  }

  if (docEl.firstElementChild) {
    docEl.firstElementChild.appendChild(remStyle);
  } else {
    var wrap = doc.createElement("div");
    wrap.appendChild(remStyle);
    doc.write(wrap.innerHTML);
    wrap = null;
  }
  //要等 wiewport 设置好后才能执行 refreshRem,不然 refreshRem 会执行2次;
  refreshRem();

  win.addEventListener("resize", function() {
    clearTimeout(tid); //防止执行两次
    tid = setTimeout(refreshRem, 300);
  }, false);

  win.addEventListener("pageshow", function(e) {
    if (e.persisted) { // 浏览器后退的时候重新计算
      clearTimeout(tid);
      tid = setTimeout(refreshRem, 300);
    }
  }, false);

  if (doc.readyState === "complete") {
    doc.body.style.fontSize = "16px";
  } else {
    doc.addEventListener("DOMContentLoaded", function(e) {
      doc.body.style.fontSize = "16px";
    }, false);
  }
})(750, 750);

d 给出正在运行的进程的pid报告IOCTL延迟

ioctl-for-given-pid.d
#!/usr/sbin/dtrace -qCs
/* stolen from /usr/include/sys/scsi/impl/uscsi.h */
#define USCSIIOC        (0x04 << 8)
#define USCSICMD        (USCSIIOC|201)  /* user scsi command */

pid$target::ioctl:entry {
  self->p = 0;
  self->t = timestamp;
  self->i = arg1;
}
pid$target::ioctl:return /self->t/ {
  @[probefunc,
    self->i == USCSICMD ? "USCSICMD" : "other"] =
      quantize(timestamp - self->t);
  self->fd = 0 ; self->t = 0 ;
}

d 给出正在运行的进程的pid报告IOCTL延迟

ioctl-for-given-pid.d
#!/usr/sbin/dtrace -qCs
/* stolen from /usr/include/sys/scsi/impl/uscsi.h */
#define USCSIIOC        (0x04 << 8)
#define USCSICMD        (USCSIIOC|201)  /* user scsi command */

pid$target::ioctl:entry {
  self->t = timestamp;
  self->i = arg1;
}
pid$target::ioctl:return /self->t/ {
  @[probefunc,
    self->i == USCSICMD ? "USCSICMD" : "other"] =
      quantize(timestamp - self->t);
  self->fd = 0 ; self->t = 0 ;
}

d 使用dtrace创建移动平均线的示例

因为我们没有真正的for循环,所以我们必须使用dtrace更加聪明。这种方法虽然难看,似乎有效,但我们可以确认它相对于使用avg()聚合是合理的。

dtrace-moving-avg.d
dtrace -qn '
  inline const int BUFFER = 1000;
  int x[BUFFER]; int ct, s; int n;
  tick-1msec {
    n = rand(); n = n > 0 ? n : -n;
    @av = avg(n);
    s += n/BUFFER;
    s -= x[ct % BUFFER]/BUFFER;
    x[ct % BUFFER] = n;
    ct += ct == 1000 ? -1000 : 1; /* count is also a ring */
  }
  tick-1sec {
    printf("moving avg=%d ", s);
    printa("agg. avg=%@d\n", @av);
    printf("%d\n", ct);
  }'

d Dtrace片段用于收集有关NFSv4 IO的基本详细信息

主要用于理智检查合成工具声称他们正在做什么。

nfsv4-sanity-check.d
dtrace -qn '
long lastoff[char *];
long nextoff[char *];
long lastdist[char *];
long bytesW;
int first[char *];

nfsv4:::op-write-start /!first[args[1]->noi_curpath]/ {
  first[args[1]->noi_curpath]++;
  lastoff[args[1]->noi_curpath] = args[2]->offset / 1024;
  bytesW += args[2]->data_len;
  /* We predict next offset, assuming that size of IO is constant, which 
   * is something we expect if IO is sequential with fix length chunks.
   */
   nextoff[args[1]->noi_curpath] =
    (args[2]->offset / 1024) + (args[2]->data_len / 1024);
}
nfsv4:::op-write-start
/ lastoff[args[1]->noi_curpath] != (args[2]->offset / 1024) / {
  this->p = args[1]->noi_curpath;
  this->cur = args[2]->offset / 1024;
  this->iosz = args[2]->data_len / 1024;
  bytesW += args[2]->data_len;

  @qoff[this->iosz] = quantize(lastoff[this->p]);
  this->dist = this->cur > lastoff[this->p] ?
    this->cur - lastoff[this->p] :
    lastoff[this->p] - this->cur;
  
  /* If our current offset is greater than previous offset, we are moving
   * in the forward direction, and if it is actually lower than previous
   * offset, we are moving in reverse direction. Direction changes are
   * indicative of random IO. 
   */
  this->is_fw = this->cur > lastoff[this->p] ? 1 : 0;

  /* nextoff[this->p] was computed previously, by adding size of last
   * io to offset at that point. If our current position in the file
   * equals our predicted position, stored in nextoff[this->p], we are
   * doing fixed size sequential IO.
   */
  this->is_seq = this->cur == nextoff[this->p];
  @seqcnt[this->is_seq ? "SEQUENTIAL" : "RANDOM" ] = count();
  @tot[this->is_seq ? "SEQUENTIAL" : "RANDOM" ]    = sum(this->iosz);

  this->dir_label = this->is_fw ? "Forward [ => ]" : "Reverse [ <= ]";
  @qdist[this->dir_label] = quantize(this->dist);
  
  lastoff[this->p] = (this->cur) - lastoff[this->p];
  /* We predict next offset, assuming that size of IO is constant, which 
   * is something we expect if IO is sequential with fix length chunks.
   */
  nextoff[this->p] = this->cur + this->iosz;
}
tick-1sec /bytesW/ {
  this->b = bytesW;
  bytesW = 0;
  @avKBps   = avg(this->b >> 10);
  @minKBps  = min(this->b >> 10);
  @maxKBps  = max(this->b >> 10);
}
END {
  printa("           Seek Distance with IO Size: %d(KB) %@d\n", @qoff);
  printa("           %s %@d\n", @qdist);
  printf("-/- Basic Statistics -/-\n");
  printa("Throughput [Avg]: %8@d(KB) | [Min]: %8@d(KB) | [Max]: %8@d(KB)\n",
    @avKBps, @minKBps, @maxKBps);
  printa("%s IOs count: %@d totaling %@d(KB)\n", @seqcnt, @tot);
}'

d Dtrace脚本,用于从sdopen获取有关EIO故障排除的有用信息

添加此脚本是为了窥视sdopen以确定哪些EIO在预计不在那里时会从通话中返回。

sdopen-label-readiness-check.d
dtrace -qn '
  ::sdopen:entry {self->x = args[0]}
  ::ddi_get_soft_state:return /self->x/ {
    self->un = (struct sd_lun *)args[1];
  }
  ::sd_ready_and_valid:entry /self->un == args[0]->ssc_un/ {
    self->rav = 1;
  }
  ::sd_ready_and_valid:return /self->rav/ {
    self->rav = 0;
    self->isvalid = args[1];
  }
  ::cmlb_partinfo:entry /self->x/ {
      self->nblks = args[2];
      self->part = args[1];
    }
  ::cmlb_partinfo:return /self->nblks/ {
    @nblks[self->un, self->part, self->isvalid, *self->nblks] = count();
    self->nblks = 0;
    self->x = 0;
    self->part = 0;
    self->un = 0;
    self->isvalid = 0;
  }
  END {
    printa("un: %p partition: 0x%-3x isvalid: %d nblks: %-12d samples: %@d\n", @nblks);
  }'