http://www2.ic.uff.br/~michael/kr1999/6-multimedia/6_06-scheduling_and_policing.htm
https://www.alibabacloud.com/blog/detailed-explanation-of-guava-ratelimiters-throttling-mechanism_594820
https://www.quora.com/What-is-the-difference-between-token-bucket-and-leaky-bucket-algorithms
What is the difference between token bucket and leaky bucket algorithms?
Samples: 192K of event 'cpu-clock', 4000 Hz, Event count (approx.): 48187750000
Percent│ ◆
│ /root/.debug/.build-id/80/6c9856a2fdbd570dd869f2b216392efaece1b3/elf: 文件格式 elf64-x86-64 ▒
│ ▒
│ ▒
│ Disassembly of section .text: ▒
│ ▒
│ 000000000040052d <main>: ▒
│ main(): ▒
│ #include <stdio.h> ▒
│ int main(void) ▒
│ { ▒
│ push %rbp ;堆栈基指针 将寄存器rbp的值推入堆栈,现在rsp的值是堆栈新顶部的内存地址 ▒
│ mov %rsp,%rbp ;堆栈顶指针 将堆栈指针rsp的值复制到基指针rbp -> rbp和rsp现在都指向堆栈的顶部 ▒
│ sub $0x10,%rsp ▒
│ unsigned i = 10; ▒
│ movl $0xa,-0x4(%rbp) ;movb(8位)、movw(16位)、movl(32位)、movq(64位) ▒
│ unsigned ii = i - 100; ▒
│ mov -0x4(%rbp),%eax ;累加寄存器 ▒
│ sub $0x64,%eax ▒
│ mov %eax,-0x8(%rbp) ▒
│ int iii = -90; ▒
│ movl $0xffffffa6,-0xc(%rbp) ▒
│ printf("%d,%d,%d", i, ii, iii); ▒
│ mov -0xc(%rbp),%ecx ;计数寄存器 ▒
│ mov -0x8(%rbp),%edx ;数据寄存器 ▒
│ mov -0x4(%rbp),%eax ▒
│ mov %eax,%esi ;变址寄存器 ▒
│ mov $0x400610,%edi ▒
│ mov $0x0,%eax ▒
│ → callq printf@plt ▒
│ while (1 < 11) ▒
│ { ▒
│ printf("%d", ii); ▒
28.37 │39: mov -0x8(%rbp),%eax ▒
9.28 │ mov %eax,%esi ▒
0.18 │ mov $0x400619,%edi ▒
│ mov $0x0,%eax ▒
17.86 │ → callq printf@plt ▒
│ } ▒
44.31 │ ↑ jmp 39 ▒
▒
Samples: 62K of event 'cpu-clock', 4000 Hz, Event count (approx.): 15607500000
f /home/hdp/workbench/perfUcan/a.out [Percent: local period]
Percent│ {
10.54 │ push %rbp
5.12 │ mov %rsp,%rbp
0.31 │ sub $0x20,%rsp
│ int i = 6;
7.13 │ movl $0x6,-0x4(%rbp)
│ int j = 10;
23.57 │ movl $0xa,-0x8(%rbp)
│ unsigned k = 10;
9.46 │ movl $0xa,-0xc(%rbp)
│ int ii = -6;
4.03 │ movl $0xfffffffa,-0x10(%rbp)
│ int jj = -10;
3.10 │ movl $0xfffffff6,-0x14(%rbp)
│ int n = -110;
5.43 │ movl $0xffffff92,-0x18(%rbp)
│ printf("hi");
3.26 │ mov $0x400630,%edi
0.16 │ mov $0x0,%eax
0.78 │ → callq printf@plt
│ return 0;
13.80 │ mov $0x0,%eax
│ }
1.09 │ leaveq
12.25 │ ← retq
https://zhuanlan.zhihu.com/p/55896356
函数的第一行涉及rbp和rsp;这些是专用寄存器。
rbp是指向当前栈桢底部的基指针,rsp是指向当前栈桢顶部的堆栈指针。
(译者注:在很多翻译过来的书上,有些地方将Stack翻译为栈桢,有的地方叫堆栈,
只要知道这里的堆栈是指Stack,Heap没关系就好)
rbp = memory address of the base of the prev stack frame
rsp = memory address of the top of the stack
指针寄存器
SP(stack pointer)
BP(base pointer)
堆栈的内存地址越来越低,即向地址小的地方增长。
基指针或帧指针。它指向当前运行的函数的栈桢中的一个固定位置,并为访问函数参数和本地变量提供一个稳定的参考点(基)
{
MOV 指令将源操作数复制到目的操作数。作为数据传送(data transfer)指令,它几乎用在所有程序中。在它的基本格式中,第一个操作数是目的操作数,第二个操作数是源操作数:
MOV destination,source
其中,目的操作数的内容会发生改变,而源操作数不会改变。这种数据从右到左的移动与 C++ 或 Java 中的赋值语句相似:
dest = source;
在几乎所有的汇编语言指令中,左边的操作数是目标操作数,而右边的操作数是源操作数。只要按照如下原则,MOV 指令使用操作数是非常灵活的。
两个操作数必须是同样的大小。
两个操作数不能同时为内存操作数。
指令指针寄存器(IP、EIP 或 RIP)不能作为目标操作数。
}
https://www.oschina.net/translate/the-art-of-picking-intel-registers?lang=chs&p=1
EAX - 累加器寄存器
EBX - 基础寄存器
ECX - 计数器寄存器
EDX - 数据寄存器
ESI - 源指针
EDI - 目的地指针
EBP - 基本指针
ESP - 堆栈指针
EAX - Accumulator Register
EBX - Base Register
ECX - Counter Register
EDX - Data Register
ESI - Source Index
EDI - Destination Index
EBP - Base Pointer
ESP - Stack Pointer
在CPU中,有八个通用寄存器
ax (add,代表相加,累加的意思)累加寄存器
bx (base,代表基地址,存放地址的寄存器) 基址寄存器
cx (count,个数,代表统计的意思)计数寄存器
dx (data,数据) 数据寄存器
SI (source) 源寄存器,存放源地址的内容的寄存器
DI (Dest) 目标寄存器,从源寄存器中memcpy到目标寄存器中
BP (base Point) 堆栈,理解为栈底指针,每次在栈中移动数据,出栈进栈,都会更新.记录的是当前的栈底
SP () 堆栈栈顶指针.
16位汇编第一讲简介
https://www.cnblogs.com/iBinary/p/7446164.html
32位汇编第一讲x86和8086的区别,以及OllyDbg调试器的使用
https://www.cnblogs.com/iBinary/p/7508144.html
一丶32位(x86也称为80386)与8086(16位)汇编的区别
1.寄存器的改变
AX 变为 EAX 可以这样想,16位通用寄存器前边都加个E开头
例如:
EAX EBX ECX EDX ESI EDI ESP EBP ;八个寄存器
EIP EFLAGES ;特殊寄存器
CS ES SS DS GS FS ;其中GS FS是新增加的寄存器,这些段寄存器,并不是4个字节(32位的)还是以前16位的
注意在32位下没有分段的概念的,因为寻址能力是 0- FFFFFFFF ,在当时的inter认为当初的4G已经很厉害了,那是后最好的内存才1G,放到现在看
我们感觉4G不够用了,但也是近几年才开始用的8G
有分区的概念,比如我们16位汇编中,给代码分段的时候,顺便分了一下区,分区是为了更好的管理代码的编写
https://sourceware.org/gdb/current/onlinedocs/gdb/Memory.html
u10进制 x16
(gdb) x/16ub 0x400650
0x400650: 104 105 0 0 1 27 3 59
0x400658: 56 0 0 0 6 0 0 0
(gdb) x/16xb 0x400650
0x400650: 0x68 0x69 0x00 0x00 0x01 0x1b 0x03 0x3b
0x400658: 0x38 0x00 0x00 0x00 0x06 0x00 0x00 0x00
[hdp@cmd ~]$ cat /proc/version
Linux version 3.10.0-1062.4.1.el7.x86_64 (mockbuild@kbuilder.bsys.centos.org) (gcc version 4.8.5 20150623 (Red Hat 4.8.5-39) (GCC) ) #1 SMP Fri Oct 18 17:15:30 UTC 2019
[hdp@cmd ~]$ cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 79
model name : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz
stepping : 1
microcode : 0xffffffff
cpu MHz : 2095.146
cache size : 20480 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 0
initial apicid : 0
fpu : yes
fpu_exception : yes
cpuid level : 20
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ibrs ibpb stibp fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt spec_ctrl intel_stibp arch_capabilities
bogomips : 4190.29
clflush size : 64
cache_alignment : 64
address sizes : 44 bits physical, 48 bits virtual
power management:
processor : 1
vendor_id : GenuineIntel
cpu family : 6
model : 79
model name : Intel(R) Xeon(R) CPU E5-2620 v4 @ 2.10GHz
stepping : 1
microcode : 0xffffffff
cpu MHz : 2095.146
cache size : 20480 KB
physical id : 0
siblings : 2
core id : 0
cpu cores : 1
apicid : 1
initial apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 20
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss ht syscall nx pdpe1gb rdtscp lm constant_tsc rep_good nopl xtopology eagerfpu pni pclmulqdq ssse3 fma cx16 pcid sse4_1 sse4_2 movbe popcnt aes xsave avx f16c rdrand hypervisor lahf_lm abm 3dnowprefetch invpcid_single ibrs ibpb stibp fsgsbase bmi1 hle avx2 smep bmi2 erms invpcid rtm rdseed adx smap xsaveopt spec_ctrl intel_stibp arch_capabilities
bogomips : 4190.29
clflush size : 64
cache_alignment : 64
address sizes : 44 bits physical, 48 bits virtual
power management:
[hdp@cmd ~]$
https://linuxtools-rst.readthedocs.io/zh_CN/latest/tool/readelf.html
拥有的条件
static PyObject *
rlock_is_owned(rlockobject *self, PyObject *Py_UNUSED(ignored))
{
unsigned long tid = PyThread_get_thread_ident();
if (self->rlock_count > 0 && self->rlock_owner == tid) {
Py_RETURN_TRUE;
}
Py_RETURN_FALSE;
}
创建
static PyObject *
rlock_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
rlockobject *self;
self = (rlockobject *) type->tp_alloc(type, 0);
if (self != NULL) {
self->in_weakreflist = NULL;
self->rlock_owner = 0;
self->rlock_count = 0;
self->rlock_lock = PyThread_allocate_lock();
if (self->rlock_lock == NULL) {
Py_DECREF(self);
PyErr_SetString(ThreadError, "can't allocate lock");
return NULL;
}
}
return (PyObject *) self;
}
static PyObject *
lock_PyThread_acquire_lock(lockobject *self, PyObject *args, PyObject *kwds)
{
_PyTime_t timeout;
PyLockStatus r;
if (lock_acquire_parse_args(args, kwds, &timeout) < 0)
return NULL;
r = acquire_timed(self->lock_lock, timeout);
if (r == PY_LOCK_INTR) {
return NULL;
}
if (r == PY_LOCK_ACQUIRED)
self->locked = 1;
return PyBool_FromLong(r == PY_LOCK_ACQUIRED);
}
如果多线程的场景下,没有在一个线程内的 锁的获取与释放的要求,那么 Rlock的作用 就是否和Lock一样?
单线程的情况下,lock有的功能点,Rlock也有,反之不成立;
多线程的情况下, 如果有在同一线程内的锁的释放或获取的需求,则用Rlock;
否则,用Lock,因为Rlock的运行逻辑多于Lock,会有更多的资源消耗 性能开销。