Heap And Stack 堆与栈的区别

堆与栈的区别

推荐:https://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/

栈是上下顺序存储的,且“先进后出LIFO”规则,只能删除顶部的元素,而堆是没有特定的顺序的存储,您可以删除任意元素。堆分配需要维护分配的内存和未分配的内存的完整记录,以及一些开销维护以减少碎片,找到足够大以适应请求大小的连续内存段,等等。内存可以随时释放,留出自由空间。有时,内存分配器将执行维护任务,比如通过将分配的内存到处移动来对内存进行碎片整理,或者在运行时进行垃圾收集——当内存不再处于作用域中时对其进行标识并释放它。

1. 栈用在线程中,程序执行时由线程创建有限数量的栈空间,当线程结束的时候会自动回收,属于系统级。
堆一般是由应用程序在启动时创建,由应用程序回收,属于应用级。

The stack is attached to a thread, so when the thread exits the stack is reclaimed. The heap is typically allocated at application startup by the runtime, and is reclaimed when the application (technically process) exits.

2. 栈的大小固定,通常在程序启动时已经确定了最大大小(部分语言支持动态扩容)。如果超出会出现“stack overflow”异常,经常在“递归”函数里出现。
堆是由”动态分配“的,其大小不固定,你可以在任何时间创建,再在任何时间回收(还是受限限系统虚拟内存 (ie: RAM and swap space))。

3. 每个线程可有一个堆栈,而应用程序通常只有一个堆(尽管对于不同类型的分配有多个堆并不罕见)

4. 栈的读取速度要更快。因为分配内存的机制,只是移动指针,而堆还要做查找等操作。

Which is faster – the stack or the heap? And why?

The stack is much faster than the heap. This is because of the way that memory is allocated on the stack. Allocating memory on the stack is as simple as moving the stack pointer up.

 

Variables allocated on the stack, or automatic variables, are stored directly to this memory. Access to this memory is very fast, and it’s allocation is dealt with when the program is compiled. Large chunks of memory, such as very large arrays, should not be allocated on the stack to avoid overfilling the stack memory (known as stack overflow). Stack variables only exist in the block of code in which they were declared. For example:

堆和栈在内存分配方面的不同:http://timmurphy.org/2010/08/11/the-difference-between-stack-and-heap-memory-allocation/

5. 堆和栈在用在函数变量的时候有些不同,一般动态创建的变量是存储在堆heap中,访问速度慢一些,而放在栈里的变量访问速度要快的多。

Variables allocated on the heap, or dynamic variables, have their memory allocated at run time (ie: as the program is executing). Accessing this memory is a bit slower, but the heap size is only limited by the size of virtual memory (ie: RAM and swap space). This memory remains allocated until explicitly freed by the program and, as a result, may be accessed outside of the block in which it was allocated.

如编码中的定义一个变量 int i = 20 则变量 i 存储在stack中;创建一个对象 user = new Account(); //这时user变量则存储在heap中。

堆与栈用法示例

int foo()
{
  char *pBuffer; //<--nothing allocated yet (excluding the pointer itself, which is allocated here on the stack).
  bool b = true; // Allocated on the stack.
  if(b)
  {
    //Create 500 bytes on the stack
    char buffer[500];

    //Create 500 bytes on the heap
    pBuffer = new char[500];

   }//<-- buffer is deallocated here, pBuffer is not
}//<--- oops there's a memory leak, I should have called delete[] pBuffer;

https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap

http://www.programmerinterview.com/index.php/data-structures/difference-between-stack-and-heap/

视频 https://www.youtube.com/watch?v=450maTzSIvA

https://blog.csdn.net/waidazhengzhao/article/details/76651923

Golang中的调度器

介绍(Introduction)
———————
Go 1.1最大的特色之一就是这个新的调度器,由Dmitry Vyukov贡献。新调度器让并行的Go程序获得了一个动态的性能增长,针对它我不能再做点更好的工作了,我觉得我还是为它写点什么吧。

这篇博客里面大多数东西都已经被包含在了[原始设计文档](https://docs.google.com/document/d/1TTj4T2JO42uD5ID9e89oa0sLKhJYD0Y_kqxDv3I3XMw)中了,这个文档的内容相当广泛,但是过于技术化了。

关于新调度器,你所需要知道的都在那个设计文档中,但是我这篇博客有图片,所以更加清晰易懂。

带调度器的Go runtime需要什么?(What does the Go runtime need with a scheduler?)
——————————————————————————-
但是在我们开始看新调度器之前,我们需要理解为什么需要调度器。为什么既然操作系统能为我们调度线程了,我们又创造了一个用户空间调度器? Continue reading

MySQL中的半同步复制

MySQL当前存在的三种复制模式有:异步模式、半同步模式和组复制模式。注意:MySQL复制模式没有“同步复制”这一项的,文章中只是为了读者方便理解半同步复制的概念才介绍了同步复制概念https://dev.mysql.com/doc/refman/8.0/en/replication-semisync.html

从MySQL5.5开始,MySQL以插件的形式支持半同步复制。

1. 异步复制(Asynchronous replication)

MySQL默认的复制即是异步的,主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不关心从库是否已经接收并处理,这样就会有一个问题,主如果crash掉了,此时主上已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主上的数据不完整。

异步复制是MySQL最早的也是当前使用最多的复制模式,异步复制提供了一种简单的主-从复制方法,包含一个主库(master)和备库(一个,或者多个) 之间,主库执行并提交了事务,在这之后(因此才称之为异步),这些事务才在从库上重新执行一遍(基于statement)或者变更数据内容(基于 row),主库不检测其从库上的同步情况。在服务器负载高、服务压力大的情况下主从产生延迟一直是其诟病。工作流程简图如下:

而同步复制(Fully synchronous replication,MySQL中没有此复制概念)指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端。因为需要等待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。

2. 半同步复制(Semisynchronous replication)

介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。相对于异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个延迟最少是一个TCP/IP往返的时间。所以,半同步复制最好在低延时的网络中使用。

MySQL5.5 的版本在异步同步的基础之上,以插件的形式实现了一个变种的同步方案,称之为半同步复制(semi-sync replication)。这个插件在原生的异步复制上,添加了一个同步的过程:当从库接收到了主库的变更(即事务)时,会通知主库。主库上的操作有两种:接收到这个通知以后才去commit事务接受到之后释放session。这两种方式是由主库上的具体配置决定的。当主库收不到从库的变更通知超时时,由半同步复制自动切换到异步同步,这样就极大了保证了数据的一致性(至少一个从库),但是在性能上有所下降,特别是在网络不稳定的情况下,半同步和同步之间来回切换,对正常的业务是有影响的。其工作流程简图如下:

Continue reading