Profiling CPU使用

本文内容取自于《Systems Performance: Enterprise and the Cloud》

Profiling CPU的方法是通过对CPU状态进行周期性地采样,然后进行分析。包含5个步骤:

1. Select the type of profile data to capture, and the rate.
2. Begin sampling at a timed interval.
3. Wait while the activity of interest occurs.
4. End sampling and collect sample data.
5. Process the data.

CPU采样数据基于下面两个因素:

a. User level, kernel level, or both
b. Function and offset (program-counter-based), function only, partial stack trace, or full stack trace

抓取user levelkernel level所有的函数调用栈固然可以完整地得到CPUprofile,但这样会产生太多的数据。因此通常只采样user levelkernel level部分函数调用栈就可以了,有时可能仅需要保留函数的名字。

下面是一个使用DTraceCPU采样的例子:

 # dtrace -qn 'profile-997 /arg1/ {@[execname, ufunc(arg1)] = count();} tick-10s{exit(0)}'

 top                                                 libc.so.7`0x801154fec                                             1
 top                                                 libc.so.7`0x8011e5f28                                             1
 top                                                 libc.so.7`0x8011f18a9                                             1

 

Go语言的类型转换

以下摘自The Go Programming Language

For every type T, there is a corresponding conversion operation T(x) that converts the value x to type T. A conversion from one type to another is allowed if both have the same underlying type, or if both are unnamed pointer types that point to variables of the same underlying type; these conversions change the type but not the representation of the value. If x is assignable to T, a conversion is permitted but is usually redundant.

Conversions are also allowed between numeric types, and between string and some slice types. These conversions may change the representation of the value. For instance, converting a floating-point number to an integer discards any fractional part, and converting a string to a []byte slice allocates a copy of the string data. In any case, a conversion never fails at run time.

 

Oracle笔记(7)——Oracle进程,server进程和background进程

Oracle手册上对于Oracle process的定义:

A unit of execution that runs the Oracle database code. The process execution architecture depends on the operating system. Oracle processes include server processes and background processes.

Oracle process即是运行Oracle数据库的代码,它分成server processbackground process两种。

Server process的定义:

An Oracle process that communicates with a client process and Oracle Database to fulfill user requests. The server processes are associated with a database instance, but are not part of the instance.

Server process可以看做是连接数据库client进程和数据库之间的桥梁,用来处理client的请求。虽然同Instance相关联,但不属于具体的Instance

Background process的定义:

A process that consolidates functions that would otherwise be handled by multiple Oracle programs running for each client process. The background processes asynchronously perform I/O and monitor other Oracle processes.

Background process用来做实际的I/O操作和监控其它Oracle进程。

参考资料:
Glossary

 

Oracle笔记(6)——SGA

Oracle手册上对于SGA(System Global Area)的定义:

The SGA is a read/write memory area that, along with the Oracle background processes, form a database instance. All server processes that execute on behalf of users can read information in the instance SGA. Several processes write to the SGA during database operation.

Note: The server and background processes do not reside within the SGA, but exist in a separate memory space.

Each database instance has its own SGA. Oracle Database automatically allocates memory for an SGA at instance startup and reclaims the memory at instance shutdown.

SGAOracle后台进程一起组成了数据库的Instance。每个Instance拥有自己的SGAInstance启动时会自动分配SGA,退出时会回收SGASGA包含下列组成部分:

✓ Shared pool
✓ Database buffer cache
✓ Redo log buffer
✓ Large pool
✓ Java pool
✓ Streams pool

参考资料:
Oracle 12c For Dummies
Overview of the System Global Area (SGA)

 

Go语言的函数返回多个值

以下摘自The Go Programming Language

Often, functions use these additional results to indicate some kind of error, either by returning an error as in the call to os.Open, or a bool, usually called ok. If a map lookup, type assertion, or channel receive appears in an assignment in which two results are expected, each produces an additional boolean result:
v, ok = m[key] // map lookup
v, ok = x.(T) // type assertion
v, ok = <-ch // channel receive
As with variable declarations, we can assign unwanted values to the blank identifier:
_, err = io.Copy(dst, src) // discard byte count
_, ok = x.(T)

map查找,类型断言和从channel接收数据都会返回两个值,其中一个是表示成功或失败的布尔值。同变量定义一样,不想要的值可以赋给_

 

Linux kernel 笔记 (60)——scheduling domain

NUMA系统上,由于不同CPU直接访问本地内存和远端内存的时间相差很大,所以更好地调度算法就显得很重要。Linux kernel引入了scheduling domain的概念。可以参看下面例子:

[root@localhost ~]# cd /proc/sys/kernel/sched_domain/
[root@localhost sched_domain]# ls
cpu0  cpu1  cpu2  cpu3  cpu4  cpu5  cpu6  cpu7
[root@localhost sched_domain]# ls -alt *
cpu0:
total 0
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 domain0
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 domain1
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 .
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 ..

cpu1:
total 0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain1
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 .
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 ..

cpu2:
total 0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain1
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 .
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 ..

cpu3:
total 0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain1
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 .
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 ..

cpu4:
total 0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain1
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 .
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 ..

cpu5:
total 0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain1
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 .
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 ..

cpu6:
total 0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain1
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 .
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 ..

cpu7:
total 0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain0
dr-xr-xr-x. 1 root root 0 Feb 26 20:06 domain1
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 .
dr-xr-xr-x. 1 root root 0 Feb 26 19:37 ..

/proc/sys/kernel/sched_domain/目录下每个CPU都有一个自己的目录,并且每个CPU目录下都有和自己相关的domain信息。

multi-level系统中,也拥有multi-levelscheduling domain(内核中结构体是struct sched_domain)。每个scheduling domain包含一组共享属性和调度策略的CPU;每个scheduling domain包含至少一个或多个CPU group(内核中结构体是struct sched_group),每个CPU group会被scheduling domain看做一个独立的单元。

scheduling domain的核心代码位于kernel\sched\core.c中,关于/proc/sys/kernel/sched_domain/cpu$/domain$中各个文件的含义,都可以在这里找到。

NUMA系统上,如果一个node利用率非常高,比如高于90%,而另一个node利用率可能只有60%~70%,这时可以尝试disable wakeup affinity

参考资料:
Scheduling domains
sched-domains.txt
Does domain0 in /proc/sys/kernel/sched_domain/cpu$ refer top-level domain in the system?
How to understan /proc/sys/kernel/sched_domain/cpu$/domain$/flags?

docker笔记(8)—— Container的生命周期

docker create创建一个containerdocker start则启动这个container

docker run相当于docker create加上docker start。需要注意的是,一旦执行完container需要做的工作,container就会退出:

# docker run hello-world

Hello from Docker.
......

# docker ps -a
CONTAINER ID        IMAGE               COMMAND             CREATED             STATUS                     PORTS               NAMES
62a13663511f        hello-world         "/hello"            5 seconds ago       Exited (0) 4 seconds ago                       compassionate_ptolemy

停止container可以使用下列两个命令:
docker kill:向container发送SIGKILL信号;
docker stop:先向container发送SIGTERM信号,过一段时间再发送SIGKILL信号。

彻底干掉container使用docker rm命令。移除所有已经停止的container可以使用下列命令:

$ docker rm $(docker ps -a -q)

参考资料:
Docker Cookbook

 

docker笔记(7)—— Index,registry和repository

看一下对三个词的英文解释:

An index manages user accounts, permissions, search, tagging, and all that nice stuff that’s in the public web interface.

A registry stores and serves up the actual image assets, and it delegates authentication to the index. Docker registry is a service that is storing your docker images.

Docker repository is a collection of different docker images with same name, that have different tags.

Index是管理docker的服务(包含用户账户,操作权限,等等)。Registry是存储docker image的服务。Repository则是包含同名不同tagdocker image的集合。

参考资料:
Difference between Docker registry and repository
Where are Docker images stored?

 

docker笔记(6)—— 在docker container中执行命令的脚本

下面脚本的功能是循环地在各个container中执行命令:

#!/bin/bash -x

for i in {1..2}
do
        docker exec -i hammerdb_net${i} bash <<-EOF
        su oracle
        source /tmp/ora_env
        cd /data/oracle/tablespaces/
        rm -f *.html
        ./create_awr.sh
        mv awr.html awr_${i}.html
        EOF
done

需要注意的是在dodone之间应该使用tab而不是空格。

参考资料:
Indenting bourne shell here documents
How to write a bash script which automate entering “docker container” and doing other things?
Can’t indent heredoc to match nesting’s indent

 

Haskell笔记 (19)—— Guard

guard跟在函数名和参数之后,用管道符号表示:

myCompare :: (Ord a) => a -> a -> Ordering  

myCompare a b
    | a < b = LT
    | a == b = EQ
    | otherwise = GT    

guard长得和pattern类似,pattern检查输入是否符合这个pattern,而guard则会计算布尔表达式,返回TrueFalse。如果返回值是True,则执行等号后面的函数体部分。

看另外一个例子:

Capture

The first pattern specifies that if we try to take a 0 or negative number of elements, we get an empty list. Notice that we’re using _ to match the list because we don’t really care what it is in this case. Also notice that we use a guard, but without an otherwise part. That means that if n turns out to be more than 0, the matching will fall through to the next pattern.

guard没有otherwise,如果都不匹配的话,就会执行下一个pattern

参考资料:
Guards, guards!