// 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. EventQueue.invokeLater(new Runnable())

    public class EventQueueextends ObjectEventQueue 是一个与平台无关的类,它将来自于底层同位体类和受信任的应用程序类的事件列入队列. 它封装了异步事件指派机 ...

  2. SpringBoot的第一个例子

    1. 安装springboot的开发IDE,IntelliJ IDEA 2016.3.1这个工具,在IDE的官网上可以下载最新版本.https://www.jetbrains.com/idea/#ch ...

  3. 《深入理解JAVA虚拟机》笔记1

    java程序运行时的内存空间,按照虚拟机规范有下面几项: )程序计数器 指示下条命令执行地址.当然是线程私有,不然线程怎么能并行的起来. 不重要,占内存很小,忽略不计. )方法区 这个名字很让我迷惑. ...

  4. JSP指令与动作

    Jsp基本指令和动作 (2011-08-18 16:25:13) 转载▼ 标签: 杂谈 分类: java JSP基本指令 jsp命令指令用来设置与整个jsp页面相关的属性,它并不直接产生任何可见的输出 ...

  5. Day18 Django的深入使用

    在向某一个数据库中插入表的时候,应该在项目下面的models里边写入: class book(models,Model): #book代指的是表名 id=models.AutoField(primar ...

  6. 简单剖析Node中的事件监听机制(一)

    使用js的class类简单的实现一个事件监听机制,不同于浏览器中的时间绑定与监听,类似于node中的时间监听,并且会在接下来的文章中去根据自己的理解去写一下Event模块中的原理. Node.js使用 ...

  7. Windows下Markdown软件的选择

    从开始Java学习这个系列的同时,我也开始改用Markdown而不是无比蛋疼的博客园默认编辑器来进行博客管理.但是Windows下想找一个比较好的Markdown编辑器蛮困难的,可以说专门的Markd ...

  8. 前端leader找我谈心:我是如何从刚毕业的前端菜鸟一步步成长为前端架构师的?

    谈谈学习 我做前端已经有五年的时间了,从大学刚毕业的时候,我是一个完全什么都不懂的小白.虽然我大学里学的是软件工程专业,但是因为在大学里荒废学业,每天只知道打游戏,基本上到大学毕业之前我是什么都不会的 ...

  9. 洛谷 P3177 树上染色 解题报告

    P3177 [HAOI2015]树上染色 题目描述 有一棵点数为\(N\)的树,树边有边权.给你一个在\(0\) ~ \(N\)之内的正整数\(K\),你要在这棵树中选择\(K\)个点,将其染成黑色, ...

  10. 【python3】如何建立爬虫代理ip池

    一.为什么需要建立爬虫代理ip池 在众多的网站防爬措施中,有一种是根据ip的访问频率进行限制的,在某段时间内,当某个ip的访问量达到一定的阀值时,该ip会被拉黑.在一段时间内被禁止访问. 这种时候,可 ...