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)不能作为目标操作数。

}



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位汇编第一讲简介

32位汇编第一讲x86和8086的区别,以及OllyDbg调试器的使用

一丶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,会有更多的资源消耗 性能开销。