// Package profile provides a simple way to manage runtime/pprof
// profiling of your Go application.
package profile

import (
    "io/ioutil"
    "log"
    "os"
    "os/signal"
    "path/filepath"
    "runtime"
    "runtime/pprof"
    "sync/atomic"
)

const (
    cpuMode = iota
    memMode
    blockMode
    traceMode
)

// Profile represents an active profiling session.
type Profile struct {
    // quiet suppresses informational messages during profiling.
    quiet bool

    // noShutdownHook controls whether the profiling package should
    // hook SIGINT to write profiles cleanly.
    noShutdownHook bool

    // mode holds the type of profiling that will be made
    mode int

    // path holds the base path where various profiling files are  written.
    // If blank, the base path will be generated by ioutil.TempDir.
    path string

    // memProfileRate holds the rate for the memory profile.
    memProfileRate int

    // closer holds a cleanup function that run after each profile
    closer func()

    // stopped records if a call to profile.Stop has been made
    stopped uint32
}

// NoShutdownHook controls whether the profiling package should
// hook SIGINT to write profiles cleanly.
// Programs with more sophisticated signal handling should set
// this to true and ensure the Stop() function returned from Start()
// is called during shutdown.
func NoShutdownHook(p *Profile) { p.noShutdownHook = true }

// Quiet suppresses informational messages during profiling.
func Quiet(p *Profile) { p.quiet = true }

// CPUProfile enables cpu profiling.
// It disables any previous profiling settings.
func CPUProfile(p *Profile) { p.mode = cpuMode }

// DefaultMemProfileRate is the default memory profiling rate.
// See also http://golang.org/pkg/runtime/#pkg-variables
const DefaultMemProfileRate = 4096

// MemProfile enables memory profiling.
// It disables any previous profiling settings.
func MemProfile(p *Profile) {
    p.memProfileRate = DefaultMemProfileRate
    p.mode = memMode
}

// MemProfileRate enables memory profiling at the preferred rate.
// It disables any previous profiling settings.
func MemProfileRate(rate int) func(*Profile) {
    return func(p *Profile) {
        p.memProfileRate = rate
        p.mode = memMode
    }
}

// BlockProfile enables block (contention) profiling.
// It disables any previous profiling settings.
func BlockProfile(p *Profile) { p.mode = blockMode }

// Trace profile controls if execution tracing will be enabled. It disables any previous profiling settings.
func TraceProfile(p *Profile) { p.mode = traceMode }

// ProfilePath controls the base path where various profiling
// files are written. If blank, the base path will be generated
// by ioutil.TempDir.
func ProfilePath(path string) func(*Profile) {
    return func(p *Profile) {
        p.path = path
    }
}

// Stop stops the profile and flushes any unwritten data.
func (p *Profile) Stop() {
    if !atomic.CompareAndSwapUint32(&p.stopped, 0, 1) {
        // someone has already called close
        return
    }
    p.closer()
    atomic.StoreUint32(&started, 0)
}

// started is non zero if a profile is running.
var started uint32

// Start starts a new profiling session.
// The caller should call the Stop method on the value returned
// to cleanly stop profiling.
func Start(options ...func(*Profile)) interface {
    Stop()
} {
    if !atomic.CompareAndSwapUint32(&started, 0, 1) {
        log.Fatal("profile: Start() already called")
    }

    var prof Profile
    for _, option := range options {
        option(&prof)
    }

    path, err := func() (string, error) {
        if p := prof.path; p != "" {
            return p, os.MkdirAll(p, 0777)
        }
        return ioutil.TempDir("", "profile")
    }()

    if err != nil {
        log.Fatalf("profile: could not create initial output directory: %v", err)
    }

    logf := func(format string, args ...interface{}) {
        if !prof.quiet {
            log.Printf(format, args...)
        }
    }

    switch prof.mode {
    case cpuMode:
        fn := filepath.Join(path, "cpu.pprof")
        f, err := os.Create(fn)
        if err != nil {
            log.Fatalf("profile: could not create cpu profile %q: %v", fn, err)
        }
        logf("profile: cpu profiling enabled, %s", fn)
        pprof.StartCPUProfile(f)
        prof.closer = func() {
            pprof.StopCPUProfile()
            f.Close()
            logf("profile: cpu profiling disabled, %s", fn)
        }

    case memMode:
        fn := filepath.Join(path, "mem.pprof")
        f, err := os.Create(fn)
        if err != nil {
            log.Fatalf("profile: could not create memory profile %q: %v", fn, err)
        }
        old := runtime.MemProfileRate
        runtime.MemProfileRate = prof.memProfileRate
        logf("profile: memory profiling enabled (rate %d), %s", runtime.MemProfileRate, fn)
        prof.closer = func() {
            pprof.Lookup("heap").WriteTo(f, 0)
            f.Close()
            runtime.MemProfileRate = old
            logf("profile: memory profiling disabled, %s", fn)
        }

    case blockMode:
        fn := filepath.Join(path, "block.pprof")
        f, err := os.Create(fn)
        if err != nil {
            log.Fatalf("profile: could not create block profile %q: %v", fn, err)
        }
        runtime.SetBlockProfileRate(1)
        logf("profile: block profiling enabled, %s", fn)
        prof.closer = func() {
            pprof.Lookup("block").WriteTo(f, 0)
            f.Close()
            runtime.SetBlockProfileRate(0)
            logf("profile: block profiling disabled, %s", fn)
        }

    case traceMode:
        fn := filepath.Join(path, "trace.out")
        f, err := os.Create(fn)
        if err != nil {
            log.Fatalf("profile: could not create trace output file %q: %v", fn, err)
        }
        if err := startTrace(f); err != nil {
            log.Fatalf("profile: could not start trace: %v", err)
        }
        logf("profile: trace enabled, %s", fn)
        prof.closer = func() {
            stopTrace()
            logf("profile: trace disabled, %s", fn)
        }
    }

    if !prof.noShutdownHook {
        go func() {
            c := make(chan os.Signal, 1)
            signal.Notify(c, os.Interrupt)
            <-c

            log.Println("profile: caught interrupt, stopping profiles")
            prof.Stop()

            os.Exit(0)
        }()
    }

    return &prof
}

profile.go的更多相关文章

  1. CoreCRM 开发实录 —— Profile

    再简单的功能,也需要一坨代码的支持.Profile 的编辑功能主要就是修改个人的信息.比如用户名.头像.性别.电话--虽然只是一个编辑界面,但添加下来,涉及了6个文件的修改和7个新创建的文件.各种生成 ...

  2. Xamarin+Prism开发详解一:PCL跨平台类库与Profile的关系

    在[Xamarin+Prism小试牛刀:定制跨平台Outlook邮箱应用]中提到过以下错误,不知道大伙还记得不: 无法安装程序包"Microsoft.Identity.Client 1.0. ...

  3. source /etc/profile报错-bash: id:command is not found

    由于误操作导致 source /etc/profile 报错 -bash: id:command is not found 此时,linux下很多命令到不能能用,包括vi ls 等... 可以使用 e ...

  4. 【译】Spring 4 @Profile注解示例

    前言 译文链接:http://websystique.com/spring/spring-profile-example/ 本文将探索Spring中的@Profile注解,可以实现不同环境(开发.测试 ...

  5. Linix登录报"/etc/profile: line 11: syntax error near unexpected token `$'{\r''"

    同事反馈他在一测试服务器(CentOS Linux release 7.2.1511)上修改了/etc/profile文件后,使用source命令不能生效,让我帮忙看看,结果使用SecureCRT一登 ...

  6. Spring profile配置应用

    spring配置文件中可以配置多套不同环境配置,如下: <beans xml.....>     <beans profile="dev">     < ...

  7. 项目实现不同环境不同配置文件-maven profile

    最近接触的项目都是在很多地方都落地的项目,需要支持不同的环境使用不同的配置文件.一直以来都以为是人工的去写不同的配置文件,手动的去修改运用的配置文件.感觉自己还是太low呀.maven的使用的还停留在 ...

  8. 修改/etc/profile和/etc/environment导致图形界面无法登陆的问题

    在使用ubuntu开发时,往往要修改PATH变量,有时会通过修改/etc/profile和/etc/environment来修改默认的PATH变量,但是一旦出错,很容易造成无法登陆进入图形界面的问题. ...

  9. RF Firefox Profile

    默认情况下,robot framework是启动不带任何配置信息的firefox,如果需要启动带有profile的话,增加一个参数即可,如 Open Browser https://aws-qa5.i ...

  10. Linux知识:/root/.bashrc与/etc/profile的异同

    Linux知识:/root/.bashrc与/etc/profile的异同 要搞清bashrc与profile的区别,首先要弄明白什么是交互式shell和非交互式shell,什么是login shel ...

随机推荐

  1. 云技术:弹性计算ECS

    云计算(Cloud Computing)被业界看作继大型计算机.个人计算机.互联网之后的第四次IT产业革命,正日益成为未来互联网与移动技术相结合的一种新兴计算模式.云计算提供了IT基础设施和平台服务的 ...

  2. jQuery结合lhgdialog弹出窗口,关闭时出现没有权限错误

    背景: 最近的项目,使用JQuery+lhgdialog窗口组件方式模拟弹窗,在关闭lhgdialog窗口时,出现以下错误: >jQuery没有权限 >调试时 w.readyState没有 ...

  3. 点击劫持漏洞之理解 python打造一个挖掘点击劫持漏洞的脚本

    前言: 放假了,上个星期刚刚学习完点击劫持漏洞.没来的及写笔记,今天放学总结了一下 并写了一个检测点击劫持的脚本.点击劫持脚本说一下哈.= =原本是打算把网站源码 中的js也爬出来将一些防御的代码匹配 ...

  4. Pascal's Triangle(杨辉三角)

    Given numRows, generate the first numRows of Pascal's triangle. For example, given numRows = 5,Retur ...

  5. JS核心笔记

    一.说明 JS权威指南文字用红色标出: JS高级程序设计用橙色标出; 自己加上的文字用粉红色标出: 其(一)-(九)为JS权指南,(十)为JS高级程序设计 二.记法结构 2.1字符集 Javascri ...

  6. Android Data Binding使用笔记

    说在前面:先来三个文档,官网文档:https://developer.Android.com/topic/libraries/data-binding/index.html 官网文档的汉化版:http ...

  7. 文本分类学习(六) AdaBoost和SVM

    直接从特征提取,跳到了BoostSVM,是因为自己一直在写程序,分析垃圾文本,和思考文本分类用于识别垃圾文本的短处.自己学习文本分类就是为了识别垃圾文本. 中间的博客待自己研究透彻后再补上吧. 因为获 ...

  8. JS跨域:1.解决方案之-SpringMVC拦截器

    一 拦截器代码 package com.wiimedia.controller; import java.util.List; import javax.servlet.http.HttpServle ...

  9. HTML学习笔记5:修饰符和特殊标签

    ①修饰符:     作用:修饰显示的方式,并不改变网页的结构,需要修饰的内容写在修饰标签内     常用文字和段落修饰符: 文字斜体:<i></i>  或  <em> ...

  10. Quartz学习--二 Hello Quartz! 和源码分析

    Quartz学习--二  Hello Quartz! 和源码分析 三.  Hello Quartz! 我会跟着 第一章 6.2 的图来 进行同步代码编写 简单入门示例: 创建一个新的java普通工程 ...