月度归档:2021年03月

堆和栈的速度

今天被问到一个问题,堆和栈的速度比较。

当时我并没有仔细了解过堆栈的速度比较,之前也没看过相关的博客技术,所以并不知道标准答案,但我还是猜想出来了。

堆和栈最后都是在物理内存DDRM上的,对于上层的应用来说,由于页表的机制,是看不到物理内存的,而且无论是堆还是栈,都是被打散分布在DDRAM上的,所以,从物理上来说,堆和栈应该没有差异。但是既然有堆和栈的速度比较,那肯定是有差异的,那么差异不来自于物理的DDRM,那就只可能来自于Cache,一定是栈的cache的命中率比较高,导致了这样一个速度的差异。

以上内容是面试的时候推导出来的,面试后我又查了相关的知识,发现确实有这样的原因。

  • On the stack, temporal allocation locality (allocations made close together in time) implies spatial locality (storage that is close together in space). In turn, when temporal allocation locality implies temporal access locality (objects allocated together are accessed together), the sequential stack storage tends to perform better with respect to CPU caches and operating system paging systems.

  • Memory density on the stack tends to be higher than on the heap because of the reference type overhead (discussed later in this chapter). Higher memory density often leads to better performance, e.g., because more objects fit in the CPU cache.

  • Thread stacks tend to be fairly small – the default maximum stack size on Windows is 1MB, and most threads tend to actually use only a few stack pages. On modern systems, the stacks of all application threads can fit into the CPU cache, making typical stack object access extremely fast. (Entire heaps, on the other hand, rarely fit into CPU caches.)
    《Pro .NET Performance》

总体上来说:

  1. 栈内存的分配具有空间上的局部性(分配时间的局部性),而我们知道cache设计的基础理论就是程序的局部性,因此这是利于cache的
  2. 栈的内存密度比堆更高,这是利于cache的
  3. 线程栈往往比较小,可以完全cache到缓冲里面
  4. 此外,申请堆内存需要malloc,需要经历一些内存空间的寻找,还可能会引发系统调用,而栈内存是自动分配的,在内存的分配速度上,栈就比堆快

ESP32+Arduino的smartconfig配网方式,以及配套APP

主要原理采用了WIFI UDP发送广播的方式
由于Arduino提供的驱动包实在太方便了,这里直接用了,可以去看一下库源码,源码的继承关系还是比较多了,一个WIFI类继承了多个不同的父类,其中ESP8266WiFiSTAClass类提供了在STA模式下的各种方法,这里面就有

        bool beginWPSConfig(void);
        bool beginSmartConfig();
        bool stopSmartConfig();
        bool smartConfigDone();四个方法,WPS需要路由器支持,其他三个方法看名字就知道用途
demo代码如下:
 
char ssid[30] = STASSID;
char password[30] = STAPSK;
//以下函数在setup中调用
void smartConfig()
{
  WiFi.mode(WIFI_STA);//切换到STA模式
  Serial.println(“\r\nWait for Smartconfig\r\n”);
  WiFi.beginSmartConfig();//开始smartconfig
  while (1)
  {
    Serial.print(“Waiting …\r\n”);
    if (WiFi.smartConfigDone())
    {
      Serial.println(“SmartConfig Success!!!”);
      Serial.printf(“SSID:%s\r\n”, WiFi.SSID().c_str());
      Serial.printf(“PSW:%s\r\n”, WiFi.psk().c_str());
      memset(ssid,0,sizeof(ssid));
      memset(password,0,sizeof(password));
      sprintf(ssid,”%s”,WiFi.SSID().c_str());
      sprintf(password,”%s”,WiFi.psk().c_str());        //设置WIFI账号和密码
      WiFi.setAutoConnect(true);                        //设置自动连接
      break;
    }
    delay(1000);
  }
}
 
 
昨天找了半天的配网工具,其实乐鑫官方就提供了一个很好用的esp-touch
需要先把手机连接到wifi上,然后通过UDP广播,ESP32才可以收到数据包
 
网上各种配网软件乱七八糟的,这个软件在很多手机的应用商店没有上架,所以还是要去乐鑫的官网下载。