func showNetStat(buffer *bytes.Buffer, prev_rec *ss.StatRecord, cur_rec *ss.StatRecord) error {
	dusage, err := ss.GetNetUsage(
		prev_rec.Time, prev_rec.Net,
		cur_rec.Time, cur_rec.Net,
	)
	if err != nil {
		return err
	}

	buffer.WriteString(`,"net":`)
	dusage.WriteJsonTo(buffer)

	return nil
}
func main() {
	var cheader ss.CommonHeader
	var pheader ss.PlatformHeader

	parseArgs()

	f, err := os.Open(option.logfile)
	if err != nil {
		panic(err)
	}
	dec := gob.NewDecoder(f)

	err = dec.Decode(&cheader)
	if err == io.EOF {
		return
	}
	if err != nil {
		panic(err)
	}
	err = dec.Decode(&pheader)
	if err == io.EOF {
		return
	}
	if err != nil {
		panic(err)
	}

	var fst_record ss.StatRecord
	// read first record
	err = dec.Decode(&fst_record)
	if err == io.EOF {
		return
	} else if err != nil {
		panic(err)
	}

	// loop until last line
	var lst_records [2]ss.StatRecord
	idx := 0
	for {
		err = dec.Decode(&lst_records[idx])
		if err == io.EOF {
			idx ^= 1
			break
		} else if err != nil {
			panic(err)
		}

		idx ^= 1
	}

	lst_record := lst_records[idx]

	var cpu_usage *ss.CpuUsage = nil
	var intr_usage *ss.InterruptUsage = nil
	var disk_usage *ss.DiskUsage = nil
	var net_usage *ss.NetUsage = nil

	if fst_record.Cpu != nil && lst_record.Cpu != nil {
		cpu_usage, err = ss.GetCpuUsage(fst_record.Cpu, lst_record.Cpu)
	}

	if fst_record.Interrupt != nil && lst_record.Interrupt != nil {
		intr_usage, err = ss.GetInterruptUsage(
			fst_record.Time, fst_record.Interrupt,
			lst_record.Time, lst_record.Interrupt,
		)
	}

	if fst_record.Disk != nil && lst_record.Disk != nil {
		disk_usage, err = ss.GetDiskUsage1(
			fst_record.Time, fst_record.Disk,
			lst_record.Time, lst_record.Disk,
			option.disk_only_regex)
	}

	if fst_record.Disk != nil && lst_record.Disk != nil {
		net_usage, err = ss.GetNetUsage(
			fst_record.Time, fst_record.Net,
			lst_record.Time, lst_record.Net)
	}

	interval := lst_record.Time.Sub(fst_record.Time)

	if option.json {
		buf := bytes.NewBuffer([]byte{})

		buf.WriteString(fmt.Sprintf(`{"exectime":%.3f`, interval.Seconds()))
		if cpu_usage != nil {
			buf.WriteString(`,"cpu":`)
			cpu_usage.WriteJsonTo(buf)
		}

		if intr_usage != nil {
			buf.WriteString(`,"intr":`)
			intr_usage.WriteJsonTo(buf)
		}

		if disk_usage != nil {
			buf.WriteString(`,"disk":`)
			disk_usage.WriteJsonTo(buf)
		}

		if net_usage != nil {
			buf.WriteString(`,"net":`)
			net_usage.WriteJsonTo(buf)
		}

		buf.WriteByte('}')

		fmt.Println(buf.String())
	} else {
		if option.title == "" {
			fmt.Println("== performance summary ==")
		} else {
			fmt.Printf("== performance summary of '%s' ==\n", option.title)
		}
		fmt.Printf(`
Duration: %.3f sec

`,
			interval.Seconds())
		if cpu_usage != nil {
			fmt.Printf(`* Average CPU usage (MAX: %d %%)
  * Non-idle usage: %.2f %%
       %%usr: %.2f %%
       %%sys: %.2f %%
       %%irq: %.2f %%
      %%soft: %.2f %%
     %%other: %.2f %%
  * Idle usage: %.2f %%
    %%iowait: %.2f %%
      %%idle: %.2f %%

`,
				100*cpu_usage.NumCore,
				100.0*float64(cpu_usage.NumCore)-cpu_usage.All.Idle-cpu_usage.All.Iowait,
				cpu_usage.All.User+cpu_usage.All.Nice,
				cpu_usage.All.Sys,
				cpu_usage.All.Hardirq,
				cpu_usage.All.Softirq,
				cpu_usage.All.Steal,
				cpu_usage.All.Idle+cpu_usage.All.Iowait,
				cpu_usage.All.Iowait, cpu_usage.All.Idle)
		}

		if disk_usage != nil {
			devices := []string{}

			for device, _ := range *disk_usage {
				if device != "total" {
					devices = append(devices, device)
				}
			}
			sort.Strings(devices)
			if len(devices) > 1 {
				devices = append(devices, "total")
			}

			for _, device := range devices {
				e := (*disk_usage)[device]
				fmt.Printf(`* Average DEVICE usage: %s
        read IOPS: %.2f
       write IOPS: %.2f
  read throughput: %.2f MB/s
 write throughput: %.2f MB/s
     read latency: %.1f usec
    write latency: %.1f usec
      read amount: %.2f MB
     write amount: %.2f MB

`,
					device,
					e.RdIops, e.WrIops,
					e.RdSecps*512.0/1024.0/1024.0, e.WrSecps*512.0/1024.0/1024.0,
					e.RdLatency*1000.0, e.WrLatency*1000.0,
					float64(e.RdSectors*512)/1024.0/1024.0,
					float64(e.WrSectors*512)/1024.0/1024.0)
			}
		}
	}
}