西维蜀黍

【Golang】性能调优 - 分析阻塞操作

排查因调用同步原语(synchronization primitives)导致阻塞操作

使用前需要先调用 runtime.SetMutexProfileFraction。

在程序中,除了锁的争用会导致阻塞之外,很多逻辑都会导致阻塞。

  ...


【Golang】性能调优 - 分析互斥锁使用

查看因持有互斥锁(mutexes)导致阻塞的情况(堆栈)

使用前需要先调用 runtime.SetBlockProfileRate。

$ go tool pprof http://localhost:6060/debug/pprof/mutex
Fetching profile over HTTP from http://localhost:6060/debug/pprof/mutex
Saved profile in /Users/weishi/pprof/pprof.contentions.delay.002.pb.gz
Type: delay
Time: Aug 15, 2020 at 1:54pm (+08)
No samples were found with the default sample value type.
Try "sample_index" command to analyze different sample values.
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top
Showing nodes accounting for 0, 0% of 0 total
      flat  flat%   sum%        cum   cum%
  ...


【Golang】性能调优 - 分析 goroutine 使用

排查 goroutine 泄露

由于 Golang 自带内存回收,所以一般不会发生内存泄露。但凡事都有例外,在 golang 中, goroutine 本身是可能泄露的,或者叫 goroutine 失控,进而导致内存泄露。

  ...


【Golang】性能调优 - 性能诊断

Diagnostics solutions can be categorized into the following groups:

  • Profiling: Profiling tools analyze the complexity and costs of a Go program such as its memory usage and frequently called functions to identify the expensive sections of a Go program.
  • Tracing: Tracing is a way to instrument code to analyze latency throughout the lifecycle of a call or user request. Traces provide an overview of how much latency each component contributes to the overall latency in a system. Traces can span multiple Go processes.
  • Debugging: Debugging allows us to pause a Go program and examine its execution. Program state and flow can be verified with debugging.
  • Runtime statistics and events: Collection and analysis of runtime stats and events provides a high-level overview of the health of Go programs. Spikes/dips of metrics helps us to identify changes in throughput, utilization, and performance.
  ...


【Golang】性能调优 - 分析测试用例

安装 PProf

$ go get -u github.com/google/pprof

编写测试用例

新建 data/d_test.go,文件内容:

package data

import "testing"

const url = "https://github.com/EDDYCJY"

func TestAdd(t *testing.T) {
    s := Add(url)
    if s == "" {
        t.Errorf("Test.Add error!")
    }
}

func BenchmarkAdd(b *testing.B) {
    for i := 0; i < b.N; i++ {
        Add(url)
    }
}
  ...


【Golang】性能调优 - 分析耗时函数

Demo 0

$ go tool pprof http://localhost:6060/debug/pprof/profile\?seconds\=60

Fetching profile over HTTP from http://localhost:6060/debug/pprof/profile?seconds=60
Saved profile in /Users/weishi/pprof/pprof.samples.cpu.001.pb.gz
Type: cpu
Time: Aug 15, 2020 at 1:17pm (+08)
Duration: 1mins, Total samples = 2.95s ( 4.92%)
Entering interactive mode (type "help" for commands, "o" for options)
(pprof) top10
Showing nodes accounting for 2810ms, 95.25% of 2950ms total
Dropped 11 nodes (cum <= 14.75ms)
Showing top 10 nodes out of 50
      flat  flat%   sum%        cum   cum%
    1610ms 54.58% 54.58%     1760ms 59.66%  syscall.syscall
     330ms 11.19% 65.76%      330ms 11.19%  runtime.nanotime
     210ms  7.12% 72.88%      210ms  7.12%  runtime.usleep
     160ms  5.42% 78.31%      310ms 10.51%  runtime.notetsleep
     150ms  5.08% 83.39%      150ms  5.08%  runtime.exitsyscallfast
     150ms  5.08% 88.47%      150ms  5.08%  runtime.pthread_cond_timedwait_relative_np
     100ms  3.39% 91.86%      100ms  3.39%  runtime.memmove
      40ms  1.36% 93.22%       40ms  1.36%  runtime.pthread_cond_signal
      30ms  1.02% 94.24%       60ms  2.03%  runtime.findObject
      30ms  1.02% 95.25%       30ms  1.02%  runtime.spanOf
(pprof)

执行该命令后,需等待 60 秒(可调整 seconds 的值),pprof 会进行 CPU Profiling。结束后将默认进入 pprof 的交互式命令模式,可以对分析的结果进行查看或导出。

  ...


【MySQL】索引命中

like 关键字和索引命中

Example

Table Schema

mysql> show create table task2.core_user;
+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Table     | Create Table                                                                                                                                                                                                                                                                                                                                                                                                                                        |
+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| core_user | CREATE TABLE `core_user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  ...
  PRIMARY KEY (`id`),
  UNIQUE KEY `core_user_name_2b52f76e_uniq` (`name`)
) ENGINE=InnoDB AUTO_INCREMENT=101 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci |
+-----------+-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

可以看到,对 id 和 name 都有索引。

  ...


【Git】Duplicate a Git Repo

Before you can duplicate a repository and push to your new copy, or mirror, of the repository, you must create the new repository on GitHub. In these examples, exampleuser/new-repository or exampleuser/mirrored are the mirrors.

Mirroring a repository

  1. Open Terminal.

  2. Create a bare clone of the repository.

    $ git clone --bare https://github.com/exampleuser/old-repository.git
    
  3. Mirror-push to the new repository.

    $ cd old-repository.git
    $ git push --mirror https://github.com/exampleuser/new-repository.git
    
  4. Remove the temporary local repository you created earlier.

    $ cd ..
    $ rm -rf old-repository.git
    
  ...


【Golang】同步机制 - WaitGroup

Usage

To wait for multiple goroutines to finish, we can use a wait group.

This is the function we’ll run in every goroutine. Note that a WaitGroup must be passed to functions by pointer.

On return, notify the WaitGroup that we’re done.

package main

import (
    "fmt"
    "sync"
    "time"
)

func worker(id int, wg *sync.WaitGroup) {

    defer wg.Done()

    fmt.Printf("Worker %d starting\n", id)

    time.Sleep(time.Second)
    fmt.Printf("Worker %d done\n", id)
}

func main() {

    var wg sync.WaitGroup

    for i := 1; i <= 5; i++ {
        wg.Add(1)
        // Launch several goroutines and increment the WaitGroup counter for each.
        go worker(i, &wg)
    }
		
    // Block until the WaitGroup counter goes back to 0; all the workers notified they’re done.
    wg.Wait()
}
  ...


【Linux】命令 - rename

Installation

$ brew install rename
  ...