Profiling Go Programs

转自:http://blog.golang.org/profiling-go-programs (需翻墙)

The Go Blog

Profiling Go Programs

24 June 2011

At Scala Days 2011, Robert Hundt presented a paper titled Loop Recognition in C++/Java/Go/Scala. The paper implemented a specific loop finding algorithm, such as you might use in a flow analysis pass of a compiler, in C++, Go, Java, Scala, and then used those programs to draw conclusions about typical performance concerns in these languages. The Go program presented in that paper runs quite slowly, making it an excellent opportunity to demonstrate how to use Go's profiling tools to take a slow program and make it faster.

By using Go's profiling tools to identify and correct specific bottlenecks, we can make the Go loop finding program run an order of magnitude faster and use 6x less memory.(Update: Due to recent optimizations of libstdc++ in gcc, the memory reduction is now 3.7x.) Continue reading

golang中并发实例

package main

import (
	"fmt"
	//"runtime"
	"os"
	"runtime/pprof" // 引用pprof package
	"time"
)

func main() {
	f, _ := os.Create("profile_file")
	pprof.StartCPUProfile(f)     // 开始cpu profile,结果写到文件f中
	defer pprof.StopCPUProfile() // 结束profile

	startTime := time.Now().Second()
	//runtime.GOMAXPROCS(runtime.NumCPU())

	ch := make(chan int, 100)
	quit := make(chan bool)

	go read(ch, quit)

	for i := 0; i < 2000; i++ {
		ch <- i
		fmt.Println(i)
	}

	quit <- true

	fmt.Println("\r\n====MAIN END====\r\n")
	endTime := time.Now().Second()

	fmt.Println(startTime)
	fmt.Println(endTime)
	fmt.Println("用时:", endTime-startTime, "秒")
}

func read(ch chan int, quit chan bool) {
	for {
		select {
		case value := <-ch:
			fmt.Print("----", value, "----")
		case <-quit:
			break
		}

	}
}

 

在Golang中使用json

由于要开发一个小型的web应用,而web应用大部分都会使用json作为数据传输的格式,所以有了这篇文章。

包引用

import (
    "encoding/json"
    "github.com/bitly/go-simplejson" // for json get
)

用于存放数据的结构体

type MyData struct {
    Name   string    `json:"item"`
    Other  float32   `json:"amount"`
}

这里需要注意的就是后面单引号中的内容。

`json:"item"`

这个的作用,就是Name字段在从结构体实例编码到JSON数据格式的时候,使用item作为名字。算是一种重命名的方式吧。 Continue reading

golang的json操作

package main
 
import (
    "encoding/json"
    "fmt"
    "os"
)
 
type ConfigStruct struct {
    Host              string   `json:"host"`
    Port              int      `json:"port"`
    AnalyticsFile     string   `json:"analytics_file"`
    StaticFileVersion int      `json:"static_file_version"`
    StaticDir         string   `json:"static_dir"`
    TemplatesDir      string   `json:"templates_dir"`
    SerTcpSocketHost  string   `json:"serTcpSocketHost"`
    SerTcpSocketPort  int      `json:"serTcpSocketPort"`
    Fruits            []string `json:"fruits"`
}
 
type Other struct {
    SerTcpSocketHost string   `json:"serTcpSocketHost"`
    SerTcpSocketPort int      `json:"serTcpSocketPort"`
    Fruits           []string `json:"fruits"`
}
 
func main() { 
    jsonStr := `{"host": "http://localhost:9090","port": 9090,"analytics_file": "","static_file_version": 1,"static_dir": "E:/Project/goTest/src/","templates_dir": "E:/Project/goTest/src/templates/","serTcpSocketHost": ":12340","serTcpSocketPort": 12340,"fruits": ["apple", "peach"]}`
 
    //json str 转map
    var dat map[string]interface{}
    if err := json.Unmarshal([]byte(jsonStr), &dat); err == nil {
        fmt.Println("==============json str 转map=======================")
        fmt.Println(dat)
        fmt.Println(dat["host"])
    }
 
    //json str 转struct
    var config ConfigStruct
    if err := json.Unmarshal([]byte(jsonStr), &config); err == nil {
        fmt.Println("================json str 转struct==")
        fmt.Println(config)
        fmt.Println(config.Host)
    }
 
    //json str 转struct(部份字段)
    var part Other
    if err := json.Unmarshal([]byte(jsonStr), &part); err == nil {
        fmt.Println("================json str 转struct==")
        fmt.Println(part)
        fmt.Println(part.SerTcpSocketPort)
    }
 
    //struct 到json str
    if b, err := json.Marshal(config); err == nil {
        fmt.Println("================struct 到json str==")
        fmt.Println(string(b))
    }
 
    //map 到json str
    fmt.Println("================map 到json str=====================")
    enc := json.NewEncoder(os.Stdout)
    enc.Encode(dat)
 
    //array 到 json str
    arr := []string{"hello", "apple", "python", "golang", "base", "peach", "pear"}
    lang, err := json.Marshal(arr)
    if err == nil {
        fmt.Println("================array 到 json str==")
        fmt.Println(string(lang))
    }
 
    //json 到 []string
    var wo []string
    if err := json.Unmarshal(lang, &wo); err == nil {
        fmt.Println("================json 到 []string==")
        fmt.Println(wo)
    }
}

参考第三方json库 simplejson 的用法:http://blog.haohtml.com/archives/16851

转自:http://www.cnblogs.com/go-ios/p/3906251.html

golang中的md5的用法

代码

package main

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
)

func main() {
	// md5 加密的第一种方法
	srcData := []byte("iyannik0215")
	cipherText1 := md5.Sum(srcData)
	fmt.Printf("md5 encrypto is \"iyannik0215\": %x \n", cipherText1)

	// md5 加密的第二种方法
	hash := md5.New()
	hash.Write(srcData)
	cipherText2 := hash.Sum(nil)
	hexText := make([]byte, 32)
	hex.Encode(hexText, cipherText2)
	fmt.Println("md5 encrypto is \"iyannik0215\":", string(hexText))
}
# 执行结果
md5 encrypto is "iyannik0215": b6b20c73e6bc53bc691a6bb559cf9ca9
md5 encrypto is "iyannik0215": b6b20c73e6bc53bc691a6bb559cf9ca9

不同

解释一下两种加密方式的不一样之处.
第一种加密方法:
第一种加密方法所调用的函数

//Source file src/crypto/md5/md5.go
19	// The size of an MD5 checksum in bytes.
20	const Size = 16

130	// Sum returns the MD5 checksum of the data.
131	func Sum(data []byte) [Size]byte {
132		var d digest
133		d.Reset()
134		d.Write(data)
135		return d.checkSum()
136	}

func Sum(data []byte) [Size]byte
其 [Size]byte 是固定死的.所以说第一种方法返回的是 16长度的数组(无法转string类型,需使用第二种加密方法)
第二种加密方法:

//Source file src/crypto/md5/md5.go
50	// New returns a new hash.Hash computing the MD5 checksum.
51	func New() hash.Hash {
52		d := new(digest)
53		d.Reset()
54		return d
55	}
// 这里只放了函数签名部分, 关于函数具体内容这里就不详细复制了.
51	func New() hash.Hash {}
61	func (d *digest) Write(p []byte) (nn int, err error) {}
90	func (d0 *digest) Sum(in []byte) []byte {}

这里使用 func New() hash.Hash {} 函数进行生成对象.
使用 func (d *digest) Write(p []byte) (nn int, err error) {} 方法进行写入要加密的数据.
使用 func (d0 *digest) Sum(in []byte) []byte {} 方法进行数据的加密 看其返回值.
[]byte 可见使用第二种方式加密返回的是 []byte 类型的切片.

转:http://openskill.cn/article/206?utm_source=tuicool&utm_medium=referral

koa中生成器函数generator执行顺序详解

ES6的generator http://book.apebook.org/minghe/koa-action/co/start.html

 	
function* gen() {
  var a = yield 'start';
  console.log(a);
  var b = yield 'end';
  console.log(b);
  return 'over';
}
var it = gen();
console.log(it.next()); // {value: 'start', done: false}
console.log(it.next(22)); // 22 {value: 'end', done: false}
console.log(it.next(333)); // 333 {value: 'over', done: true}

带有 * 的函数声明表示是一个 generator 函数,当执行 gen() 时,函数体内的代码并没有执行,而是返回了一个 generator 对象。

generator 函数通常和 yield 结合使用,函数执行到每个 yield 时都会暂停并返回 yield 的右值。下次调用 next 时,函数会从 yield 的下一个语句继续执行。等到整个函数执行完,next 方法返回的 done 字段会变成 true,并且将函数返回值作为 value 字段。

第一次执行 next() 时,走到 yield 'start' 后暂停并返回 yield 的右值 'start'。注意,此时var a = 这个赋值语句其实还没有执行。

第二次执行 next(22) 时,从 yield 'start' 下一个语句执行。于是执行 var a = 这个赋值语句,而表达式 yield 'start' 的值就等于传递给 next 函数的参数值 22,所以,a 被赋值为 22。然后继续往下执行到 yield 'end' 后暂停并返回 yield 的右值 'end'

第三次执行 next(333) 时,从 yield 'end' 下一个语句执行。此时执行 var b = 这个赋值语句,表达式 yield 'end' 的值等于传递给 next 函数的参数 333b 被赋值为 333。继续往下执行到 return 语句,将 return 语句的返回值作为 value 返回,因为函数已经执行完毕,done 字段标记为 true

可以看到 generator 就是一种迭代机制,就像一只很懒的青蛙,戳一下(调用 next)动一下。
出处:http://taobaofed.org/blog/2016/03/18/error-handling-in-koa/

2039474406-56efe8fb3a850_articlex

给一个正在运行的Docker容器动态添加Volume(转)

之前有人问我Docker容器启动之后还能否再挂载卷,考虑mnt命名空间的工作原理,我一开始认为这很难实现。不过现在我认为是它实现的。

简单来说,要想将磁盘卷挂载到正在运行的容器上,我们需要:

  • 使用nsenter将包含这个磁盘卷的整个文件系统mount到临时挂载点上;
  • 从我们想当作磁盘卷使用的特定文件夹中创建绑定挂载(bind mount)到这个磁盘卷的位置;
  • umount第一步创建的临时挂载点。

Continue reading

node出现“dyld: bad external relocation length”的解决办法

mac下有时候在执行 npm的过程中,我们强制中止了操作或者一些命令出现问题会提示“dyld: bad external relocation length”这个错误,这个时候只要将未下载完的文件删除即可,我这里使用 n 4.4.3下载的时候,网络出现异常,提示这个错误,只要删除 /usr/local/n/versions/node/4.4.3 这个目录即可。

如果还是不行的话,可以试着执行一下

brew doctor

命令,根据提示操作就可以了。

我遇到的情况是使用node版本控制n安装新版本号的时候,好像安装包下载的不完整,但提示安装成功了,在最后提示这个错误。试了好多方法卸载重装也不行,最后根据 brew doctor 的提示,执行了

brew link --overwrite node

彻底解决了。

nodejs中package.json文件说明

推荐:http://jingpin.jikexueyuan.com/article/34254.html

package.json 中包含各种所需模块以及项目的配置信息(名称、版本、许可证等)meta 信息。

package.json文件可以通过npm init 来创建

包含可配置项

  • name 名称
  • 应用描述 description
  • 版本号 version
  • 应用的配置项 config
  • 作者 author
  • 资源仓库地址 respository
  • 授权方式 licenses
  • 目录 directories
  • 应用入口文件 main
  • 命令行文件 bin
  • 项目应用运行依赖模块 dependencies
  • 项目应用开发环境依赖 devDependencies
  • 运行引擎 engines
  • 脚本 script

简单模式

Continue reading