nginx 内存管理(二)

ngnix:slab机制 http://www.cnblogs.com/doop-ymc/p/3412572.html http://www.dcshi.com/?cat=19 http://blog.youkuaiyun.com/qifengzou/article/details/11678115 阅读详情

在这里插入图片描述

共享内存结构与接口定义

正常来说,通过malloc函数申请的内存都是进程私有的内存但是Linux会提供共享内存的系统调用,如mmap和munmap等

Nginx基于Linux提供的系统调用,封装了共享内存的数据结构以及共享内存的创建与释放函数,其共享内存结构和接口定义如下:os/unix/ngx_shmem.h

typedef struct {   
	u_char      *addr;   //指向申请的共享内存块首地址
	size_t       size;    //共享内存块大小
	ngx_str_t    name;    //共享内存块名字
	ngx_log_t   *log;   //共享内存块日志
	ngx_uint_t   exists;//标志是否已经存在
} ngx_shm_t;//共享结构

//以下共享接口
ngx_int_t ngx_shm_alloc(ngx_shm_t *shm);//创建共享内存块
void ngx_shm_free(ngx_shm_t *shm);//释放共享内存块
ngx_int_tngx_shm_alloc(ngx_shm_t *shm)
{    
shm->addr = (u_char *) mmap(NULL, shm->size,  PROT_READ|PROT_WRITE,  MAP_ANON|MAP_SHARED, -1, 0);  //创建
if (shm->addr == MAP_FAILED) { //错误处理
	ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "mmap(MAP_ANON|MAP_SHARED, %uz) failed", shm->size);       
	return NGX_ERROR;   
}    
return NGX_OK;//成功,返回
}
void ngx_shm_free(ngx_shm_t *shm)
{   
if (munmap((void *) shm->addr, shm->size) == -1)//是否成功
{    //失败处理,记录
   ngx_log_error(NGX_LOG_ALERT, shm->log, ngx_errno, "munmap(%p, %uz) failed", shm->addr, shm->size);  
}
}

nginx共享内存在操作系统上的兼容性设计

#if (NGX_HAVE_MAP_ANON)//匿名共享内存
………
#elif (NGX_HAVE_MAP_DEVZERO)//文件共享内存
………
#elif (NGX_HAVE_SYSVSHM)//IPC System V共享内存
………
#endif

互斥锁

  • 并发进程访问共享内存时需要加锁。nginx提供了互斥锁的机制,保证了正确的共享内存的访问。nginx的进程主要是通过ngx_shmtx_t进行加锁、解锁等操作。
  • nginx实现的时候,如果操作系统提供原子操作机制,就使用操作系统的原子操作实现互斥锁,否则nginx采用文件锁实现互斥。

互斥锁模型
在这里插入图片描述

锁的结构体

//core/ngx_shmtx.h
typedef struct {  
	ngx_atomic_t   lock;//0为锁开(空闲),其它(进程号)已上锁
	#if (NGX_HAVE_POSIX_SEM)  //如果有SEM信号量
		ngx_atomic_t   wait;//等待共享内存进程总数
	#endif
} ngx_shmtx_sh_t;

上锁、解锁的结构体模型:

typedef struct {
	#if (NGX_HAVE_ATOMIC_OPS) //若有原子操作
	…………
	#if (NGX_HAVE_POSIX_SEM) //如果有信号量 
	…………
	#endif
	#else    
	…………
	#endif    
	ngx_uint_t     spin;
} ngx_shmtx_t;
typedef struct {
	#if (NGX_HAVE_ATOMIC_OPS) //若有原子操作
		ngx_atomic_t  *lock;//进程内指向共享内存锁的地址
		#if (NGX_HAVE_POSIX_SEM) //如果有信号量 
			 ngx_atomic_t  *wait; //指向共享内存等待进程总数
			 ngx_uint_t     semaphore;    //是否使用信号量,1使用
			 sem_t        sem;//sem_t信号量,可用于线程之中,也可用于进程
		#endif
	#else    //操作系统无原子操作和信号量支持,用文件
		ngx_fd_t   fd; 
		u_char        *name;
	#endif    
	ngx_uint_t     spin;
}   ngx_shmtx_t;

锁的一系列操作(core/ngx_shmtx.c)

  1. ngx_int_t ngx_shmtx_create(ngx_shmtx_t *mtx, ngx_shmtx_sh_t *addr, u_char *name);//创建锁
  2. void ngx_shmtx_destroy(ngx_shmtx_t *mtx);//销毁锁
  3. void ngx_shmtx_lock(ngx_shmtx_t *mtx);//获取锁
  4. ngx_uint_t ngx_shmtx_trylock(ngx_shmtx_t *mtx);//尝试加锁
  5. void ngx_shmtx_unlock(ngx_shmtx_t *mtx);//释放锁
  6. ngx_uint_t ngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid);//强制解锁
  7. static voidngx_shmtx_wakeup(ngx_shmtx_t *mtx)//唤醒等进程

临界区管理的基本思路
①找到临界区
②在临界区前面增加一段用于进行检查的代码,当不满足进入临界区的条件,就不进入,直到满足条件才进入,称为进入区(entry section)。
③在临界区后面加上一段称为离开区(exit section)的代码,作为善后处理。基本形式如下:

在这里插入图片描述

创建锁
ngx_int_t ngx_shmtx_create( ngx_shmtx_t *mtx,ngx_shmtx_sh_t *addr, u_char *name);//创建锁

//ngx_shmtx_t *mtx,是进程操作锁结构地址
//ngx_shmtx_sh_t *addr,是共享内存中保存的锁结构地址
//u_char *name,名字(用于区别不同锁)地址

{   
mtx->lock = &addr->lock;  //将共享内存锁信息储存到进程操作锁结构体中
if (mtx->spin == (ngx_uint_t) -1) {        return NGX_OK;    }  
mtx->spin = 2048;//自旋次数指定

#if (NGX_HAVE_POSIX_SEM)   //如果是信号量,初始化sem为1,并将semaphore设为1
	mtx->wait = &addr->wait;  
	if (sem_init(&mtx->sem, 1, 0) == -1) {      
	   ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,                    "sem_init() failed");    } 
	else {        mtx->semaphore = 1;    }
#endif  
return NGX_OK;
}
  • 进程操作锁结构需要获得(保存)共享内存锁的信息,对于自旋锁,
    1)保存共享内存锁的lock;
    2设置自旋锁的自旋次数;以便于后续进行加锁、解锁等操作;
mtx->lock = &addr->lock;  
 if (mtx->spin == (ngx_uint_t) -1) {    //已经加锁了   ?
	return NGX_OK;  
 }
mtx->spin = 2048;//nginx设置的进程自旋次数
  • 对于信号量,
    1)保存共享内存锁的保存wait;
    2设置信号量的semaphore或sem的值;以便于后续进行加锁、解锁等操作;
mtx->wait = &addr->wait;  //保存指向保存共享内存进程总数指针
if (sem_init(&mtx->sem, 1, 0) == -1)   //线程信号量初始化失败
{       
     ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,                      "sem_init() failed");    
} 
else  // 线程信号量初始化成功,初始化semaphore为1
{        
	mtx->semaphore = 1;   //使用信号量
}
  • 其它可能需要记录的调试信息以及可能的错误处理等

原子操作

计算机系统并发的基础

  • 两个原子操作
ngx_atomic_cmp_set(a,old,new):如果*a==old,将*a赋值为new,返回1。否则返回0。

ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid),(原子操作)若*mtx->lock为0,即将*mtx->lock赋值为ngx_pid。
ngx_atomic_fetch_add(old,v):将*old加上v,并返回*old。

ngx_atomic_fetch_add(mtx->wait, 1),将*mtx->wait加上1,并返回加之前的*mtx->wait值。
nginx的上锁操作
当共享内存lock为0(表示空闲)时可以上锁。对于上锁的操作,Nginx将其标准化为将lock(当其为0时)设为进程的PID。即
*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)。
尝试加锁
ngx_uint_tngx_shmtx_trylock(ngx_shmtx_t *mtx)
{   
   return (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid));
}
获取锁
  • 进程自旋锁的获取
    • 当共享内存lock为0(表示空闲)时可以上锁。对于上锁的操作,nginx将其标准化为将lock(当其为0时)设为进程的PID。即
      *mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)。

    • 因为*mtx->lock 为0时,可能有很多进程都来上锁,但只能有一个进程会成功上锁。因此对上锁进程来讲,以上上锁操作可能不成功。

    • 此时,当有多个CPU时,上锁进程可以等待一段T时间后,再次尝试上锁操作。Ngnix对T的构造有其独特的方法。

    • 上锁失败,放弃使用CPU

void ngx_shmtx_lock(ngx_shmtx_t *mtx)//自旋锁
{
 ngx_uint_t         i, n;  //初始化变量
ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx lock");
for(;;){//不断循环进行
     自旋方式加锁;
      #if (NGX_HAVE_POSIX_SEM)
      信号量方式加锁,wait记录等待共享进程总数,等待进程挂入sem等待队列;
      #endif
      ngx_sched_yield();//优化方式放弃CPU
     }
}


//自旋式加锁
for ( ;; ) {   
      if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)) 
       {           return;     }     //成功上锁返回  
      if (ngx_ncpu > 1) { //当有多个CPU时,等待T时间后,再次尝试上锁  
           for (n = 1; n < mtx->spin; n <<= 1){//构造等待时间T,再多次尝试上锁
               {              
                     for (i = 0; i < n; i++) { //每次都有等待时间T ,每次内循环等待次数不一样
                       ngx_cpu_pause();    //(借用CPU机制)优化自旋等待
              }           
             if (*mtx->lock == 0    && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid))      
              {                    return;                }  //再次尝试上锁若成功,则返回
      } 
   } 
ngx_sched_yield();//(优化)上锁失败,放弃使用CPU 。调度选中后,再次自旋上锁(为啥?)。
}
  • 信号量处理锁的获取
    如果是信号量:
    • 等待共享内存进程总数(预先)(原子性操作)加一;
    • 当lock为0(表示空闲)时可以上锁。按照nginx标准化上锁操作,也就是将lock(当其为0时)设为进程的PID。即
      *mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid)。
      如果成功,将等待共享内存进程数减一(因已成功上锁,预计加需扣除),返回。
 (void) ngx_atomic_fetch_add(mtx->wait, 1);   //原子操作预加一
         if (*mtx->lock == 0 && ngx_atomic_cmp_set(mtx->lock, 0, ngx_pid))
        {      //上锁成功了        
             (void) ngx_atomic_fetch_add(mtx->wait, -1); //原子操作减一        
             return;    //返回
        }
  • 如果上锁失败,将(该加锁进程)挂入sem的等待队列中。由于挂入sem的等待队列操作可能失败,为了确保1)中的加一操作与实际等待进程总数一致性,需要不断尝试挂入等待队列操作,直至成功挂入为止。否则数据将不一致。挂入等待队列的某进程,由释放锁某进程唤醒。
while (sem_wait(&mtx->sem) == -1) {//如果失败,再次进行挂入sem等待队列操作 
            ngx_err_t  err;               
            err = ngx_errno;     //获取错误原因   
           if (err != NGX_EINTR) { //若是系统原因,进行错误日志处理后,终止尝试      
                ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, err,   
                                "sem_wait() failed while waiting on shmtx");
                break;       
         }      
      }        
      ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, "shmtx awoke");      
      continue; //进行下一个循环   
释放锁
void ngx_shmtx_unlock(ngx_shmtx_t *mtx);//释放锁
{   
 if (mtx->spin != (ngx_uint_t) -1) //调试信息处理
      {        ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0,
              "shmtx unlock"); 
       }  
  if (ngx_atomic_cmp_set(mtx->lock, ngx_pid, 0)) {//将lock设为0就是释放
        ngx_shmtx_wakeup(mtx);   //唤醒等待进程
 }
}
强迫解锁
ngx_uint_tngx_shmtx_force_unlock(ngx_shmtx_t *mtx, ngx_pid_t pid)//强迫解锁
{   
      ngx_log_debug0(NGX_LOG_DEBUG_CORE, ngx_cycle->log, 0, 
                  “shmtx forced unlock”); //记录调试信息
      if (ngx_atomic_cmp_set(mtx->lock, pid, 0)) { //共享内存lock为0(空闲)    
           ngx_shmtx_wakeup(mtx);    //唤醒等待共享进程进程   
           return 1;   
       }  
       return 0;//强制失败,返回0;
}
唤醒等待进程
  • 如果有信号量支持://因为只有有信号量支持时,才有sem等待队列
    • 如果没有标记使用信号量,(没有构造等待队列)返回。
#if (NGX_HAVE_POSIX_SEM)//由信号量支持
if (!mtx->semaphore) 
   {       
        return;  
    }
………//剩下的其它操作实现
#endif
  • 不断使用ngx_atomic_cmp_set(mtx->wait, wait, wait - 1)对mtx->wait减一操作,直至成功将mtx->wait(原子操作)减一。
for ( ;; ) {  //不断尝试进行以下方式原子操作减一
    wait = *mtx->wait;     
    if ((ngx_atomic_int_t) wait <= 0) 
       {            return;        }    //没有等待共享内存进程,返回。
    if (ngx_atomic_cmp_set(mtx->wait, wait, wait - 1))    
          {          
                 break;  //成功原子操作减一,终止尝试原子减一。     
          }   
 }
  • 从sem等待队列中唤醒一个进程;
if (sem_post(&mtx->sem) == -1) 
{   //失败唤醒一个进程,错误日志处理
         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, ngx_errno,                      "sem_post() failed while wake shmtx");  
  }

slab共享内存块管理

nginx设计与实现了一种基于slab理念的共享内存块机制,并提供了创建共享内存块、从共享内存块中申请与释放内存的API。其结构体包括(core/ngx_slab.h以及core/ngx_slab.c):

  • ngx_slab_page_s:内存块管理结构体
    ngx_slab_stat_t:内存页使用信息管理结构体
    ngx_slab_pool_t:共享内存块结构体
    typedef struct ngx_slab_page_s ngx_slab_page_t;

nginx的slab大小规格

在这里插入图片描述

内存池结构体

typedef struct ngx_slab_page_s  ngx_slab_page_t;
struct ngx_slab_page_s 
{   
	uintptr_t         slab;   
	ngx_slab_page_t  *next; //后向
	uintptr_t         prev;//前向
};

typedef struct {   
	ngx_uint_t        total;  //总数  
	ngx_uint_t        used;   //使用总数 
	ngx_uint_t        reqs;  //请求总数 
	ngx_uint_t        fails;//失败总数
} ngx_slab_stat_t;

// 共享内存池结构体
typedef struct {    
	ngx_shmtx_sh_t    lock;  //内存锁 
	size_t            min_size;  //可以分配最小内存大小,即为8
	size_t            min_shift;  //最小slab内存的幂数,即min_size=2^ min_shift
	ngx_slab_page_t  *pages;  //指向第一页的管理结构
	ngx_slab_page_t  *last;   //指向最后页的管理结构
	ngx_slab_page_t   free;   //指向空闲首页的一个结点
	ngx_slab_stat_t  *stats;    //指向记录各种规格slab统计信息链表
	ngx_uint_t        pfree;   //空闲总页数
	u_char           *start;   //空闲页始址
	u_char           *end;//空闲末址
	ngx_shmtx_t       mutex;   //进程操作锁结构
	u_char           *log_ctx;  
	u_char            zero;   
	unsigned          log_nomem:1;  
	void             *data;   
	void             *addr;//共享内存池结构地址
} ngx_slab_pool_t;

在这里插入图片描述

共享内存池结构体slots

1.初始化共享内存池管理结构体各数据成员的值,理清控制管理关系。
2.分出控制管理结构后,剩余的即为可以共享分配的内存池。

管理不同规格的ngx_slab_page_t的首地址,nginx用宏ngx_slab_slots(pool)描述了这一大小位置关系:

在这里插入图片描述
(按情形)初始化共享池为0xA5(除共享池管理结构外)
在这里插入图片描述
初始化管理不同大小slab的ngx_slab_page_t
在这里插入图片描述
(按情形)初始化ngx_slab_stat_t
在这里插入图片描述
计算总页数pages

在这里插入图片描述
初始化pool的pages

在这里插入图片描述
初始化pool的free
在这里插入图片描述
初始化管理空页的首个ngx_slab_page_t
在这里插入图片描述
初始化pool的start

在这里插入图片描述
初始化pool的start,因对齐,修正总空闲数

在这里插入图片描述
初始化pool的其它成员

在这里插入图片描述

分配共享内存池
  1. 理论上,每个大小为KB的系统物理页,可以包含k/m个大小为mB规格的slab块。
  2. 为了标明一个系统物理页中含有的大小为mB规格slab块的占有情况,Nginx为每个系统物理页使用bitmap描述其含有的每个slab块是否空闲。
  3. 这样,每个大小为KB的系统物理页,需要k/m位描述其每个slab的空闲占有情况,如位1表示占有,如位0表示空闲。
  4. 对于小块内存(大小8Byte~32Byte),需要较多位(512b~128b)。nginx在内存首页开辟固定区域,码放这些bitmap。
  5. 对于精确内存(大小为64Byte),需要64b。nginx使管理内存页的ngx_slab_page_t结构体的slab字段作为bitmap。
  6. 对于大块内存(大小128Byte~2048Byte),需要(32b~2b)使用slab的前32位作为bitmap
void* ngx_slab_alloc(ngx_slab_pool_t *pool, size_t size)
{
	void  *p;  
	ngx_shmtx_lock(&pool->mutex);//互斥分配
	p = ngx_slab_alloc_locked(pool, size); 
	ngx_shmtx_unlock(&pool->mutex); //互斥分配
	return p;
}
Nginx 内存管理源码分析 文章目录Nginx 介绍Nginx 内存管理用到的数据数据结构 Nginx 介绍 Nginx是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。其特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好,中国大陆使用nginx网站用户有:百度、京东、新浪、网易、腾讯、淘宝等。 Nginx 内... 阅读详情

相关推荐

nginx+uwsgi部署实践的踩坑总结(二)

承接上一篇 nginx+uwsgi部署实践的踩坑总结(一) 这篇中将继续罗列我在配置nginx+uwsgi中踩过的坑。 如果在这篇中没有找到的问题可以去前一篇中查看。 1.一段非常常见的nginx报错 在启动nginx后,查看日志,会看到这么一段报错 [error] 1198#1198: *224 connect() to unix:///home/myproject/mypro...

踩坑小王子 6299

Nginx十三(slab)

nginx中的slab

weixin_43155199的博客 554

19_Nginx_模块、内存管理

19_Nginx_模块、内存管理

AntHub的博客 2255

nginx 共享内存(2)

接上文,继续分享下nginx共享内存源码实现。nginx中共享内存又称为slab内存分配器,slab内存分配器按照page为单位去进行分配,page大小 为操作系统的页大小,每一个page 用ngx_slab_page_t去描述,所有的page存放在连续的内存数组中。

shuzishiyingzhong的博客 1397

nginx slab内存管理精简源码及注释

通过把nginx slab的精简,把需要的头文件单独整理出来,增加了main方法,可以单独运行,代码包含了大量的中文注释,方便了了解和学习slab的运行机制 int main(int argc, char **argv) { ngx_log_t log; ngx_shm_t shm; ngx_slab_pool_t *shpool; char *ssl_session[10]; int n; ngx_pid = ngx_getpid(); memset(&log;, 0, sizeof(ngx_log_t)); memset(&shm;, 0, sizeof(ngx_shm_t)); shm.size = 512000; ngx_pagesize_shift = 0; ngx_pagesize = getpagesize(); for (n = ngx_pagesize; n >>= 1; ngx_pagesize_shift++) { /* void */ } printf("--%d\n", 1 << ngx_pagesize_shift); if (ngx_shm_alloc(&shm;) != NGX_OK) { return 1; } if (ngx_init_zone_pool(&log;, &shm;)) { return 1; } shpool = (ngx_slab_pool_t *) shm.addr; ssl_session[0] = (char *) ngx_slab_alloc_locked(shpool, 12); ssl_session[0] = (char *) ngx_slab_calloc(shpool, 56); ssl_session[1] = (char *) ngx_slab_alloc_locked(shpool, 14); ssl_session[2] = (char *) ngx_slab_alloc_locked(shpool, 11); ngx_slab_free(shpool, ssl_session[2]); ngx_slab_free(shpool, ssl_session[0]); ssl_session[2] = (char *) ngx_slab_alloc_locked(shpool, 65); return 0; } nginx的slab的内存管理方式,这种方式的内存管理在nginx中,主要是与nginx 的共享内存协同使用的。nginx的slab管理与linux的slab管理相同的地方在于均是利用了内存 的缓存与对齐机制,slab内存管理中一些设计相当巧妙的地方,也有一些地方个人感觉设计 不是很完美,或许是作为nginx设计综合考虑的结果。 nginx slab实现中的一大特色就是大量的位操作,这部分操作很多是与slot分级数组相关的。 为方便描述下面做一些说明: 1.将整个slab的管理结构称slab pool. 2.将slab pool前部的ngx_slab_pool_t结构称slab header. 3.将管理内存分级的ngx_slab_page_t结构称slot分级数组. 4.将管理page页使用的ngx_slab_page_t结构称slab page管理结构. 5.将具体page页的存放位置称pages数组. 6.将把page分成的各个小块称为chunk. 7.将标记chunk使用的位图结构称为bitmap.

告别付费!手把手教你用DataV.GeoAtlas获取全国街道级GeoJSON数据(附完整避坑指南)

本文详细介绍了如何免费使用阿里云DataV.GeoAtlas工具获取全国街道级GeoJSON数据。通过可视化选取、格式转换、数据校验等步骤,提供了一套完整的避坑指南和工作流,帮助前端和可视化开发者高效解决高精度地图数据获取难题,节省成本并提升开发效率。

weixin_29085865的博客 899

NGINX原理分析 之 SLAB分配机制

1 引言   众所周知,操作系统使用伙伴系统管理内存,不仅会造成大量的内存碎片,同时处理效率也较低下。SLAB是一种内存管理机制,其拥有较高的处理效率,同时也有效的避免内存碎片的产生,其核心思想是预分配。其按照SIZE对内存进行分类管理的,当申请一块大小为SIZE的内存时,分配器就从SIZE集合中分配一个内存块(BLOCK)出去,当释放一个大小为SIZE的内存时,则将该内存块放回到原有集合,

BOKE 907

自抗扰(ADRC)控制原理及控制器设计

自抗扰控制原理以及控制器设计

weixin_43487974的博客 3万+

Nginx slab 分配机制

C/C++Linux服务器开发/后台架构师知识体系 1、引言 众所周知,操作系统使用伙伴系统管理内存,不仅会造成大量的内存碎片,同时处理效率也较低下。SLAB是一种内存管理机制,其拥有较高的处理效率,同时也有效的避免内存碎片的产生,其核心思想是预分配。其按照SIZE对内存进行分类管理的,当申请一块大小为SIZE的内存时,分配器就从SIZE集合中分配一个内存块(BLOCK)出去,当释放一个大小为SIZE的内存时,则将该内存块放回到原有集合,而不是释放给操作系统。当又要申请相同大小的内存时,可以复用之前被回收的

C/C++Linux、音视频、DPDK 473

数字IC后端设计实战:从floorplan到powerplan的优化策略

本文深入探讨了数字IC后端设计中从Floorplan到Powerplan的核心优化策略。文章强调了Floorplan作为布局基础的重要性,并详细解析了Powerplan规划,特别是针对低功耗设计中MTCMOS的应用与IR Drop分析。通过实战经验分享,提供了从模块摆放到电源网络构建、再到IR Drop问题层层递进的解决方案,旨在帮助后端工程师构建稳健高效的芯片物理设计。

weixin_28338005的博客 348

sap2000 api matlab,SAP2000_API入门指南.pdf

SAP2000_API入门指南北 京 金 土 木 软 件 技 术 有 限 公 司Beijing Civil King Software TechnologyCo., Ltd.SAP2000 API 入门指南余承飞 韦群跃 汤娣概述SAP2000 API 是从 SAP2000 V11 开始引进的,即应用软件编程接口。用户可以编写程序,通过API 随心所欲地调用 SAP2000...

weixin_42118423的博客 1941

nginx源码解析(二)-内存池与内存管理ngx_pool_t

ngx_pool_t是一个非常重要的数据结构,在很多重要的场合都有使用,很多重要的数据结构也都在使用它。那么它究竟是一个什么东西呢?简单的说,它提供了一种机制,帮助管理一系列的资源(如内存,文件等),使得对这些资源的使用和释放统一进行,免除了使用过程中考虑到对各种各样资源的什么时候释放,是否遗漏了释放的担心。 例如对于内存的管理,如果我们需要使用内存,那么总是从一个ngx_pool_t的对象中获

我只是一个单纯的2的博客 1255

R语言实战:5分钟搞定NHANES数据库的加权分析与可视化(附完整代码)

本文提供了一份R语言实战指南,帮助研究者在5分钟内完成NHANES数据库的加权分析与可视化。通过详细的代码示例,涵盖数据获取、清洗、加权分析和可视化全流程,特别适合公共卫生和流行病学研究者快速掌握复杂抽样数据的处理方法。

www00的博客 254

Nginx学习之内存管理

Nginx内存管理模块中,ngx_align_ptr()函数是用来对指针的设置。具体设置是:将指针按照设定的字节对齐返回对齐设置后的指针。 其实也很简单。通过代码案例来理解比较清楚的理解,代码运行环境为Linux 64位操作系统。具体代码如下: #include <stdio.h> #include <stdlib.h> #include <sys/types.h> #include <inttypes.h> #defi...

向往天空的鱼 3908

PCIE的MSI中断处理机制与优化策略

PCIe设备的。

xiaoheshang_123的博客 516

21、空间数据处理中的克里金方法及应用

本文介绍了空间数据处理中的克里金方法,特别是带外部漂移的克里金法(KED)及其在遥感数据融合和支持变化问题中的应用。讨论了克里金方法的基本原理、优缺点以及在不同空间分辨率遥感图像融合中的具体操作流程。同时,还涉及了地统计数据融合和支持变化问题的解决方案,包括块克里金法、面到点克里金法和多边形克里金法等。

gold的博客 87

深入理解Nginx的内存管理

本篇文章给大家带来的内容是关于Nginx的内存管理的深入理解(图),有一定的参考价值,有需要的朋友可以参考一下,希望对你有所帮助。 一. 概述 应用程序的内存可以简单分为堆内存,栈内存。对于栈内存而言,在函数编译时,编译器会插入移动栈当前指针位置的代码,实现栈空间的自管理。而对于堆内存,通常需要程序员进行管理。我们通常说的内存管理亦是只堆空间内存管理。 对于内存,我们的使用可以简化为3步,申请内存、使用内存、释放内存。申请内存,使用内存通常需要程序员显示操作,释放内存却并不一定需要程序员显

月梦工作室 1525

QXDM.4.0.450.2.Windows-x86.7z

QXDM.4.0.450.2.Windows-x86.7z

nginx 内存管理(一)

对于栈内存,函数编译的时候,编译器会移动栈到当前指针位置的代码,实现栈空间的管理。但是对于堆内存,通常需要程序员进行管理,我们常说的内存管理其实就是对堆空间的管理。nginx的内存管理可以分为两个部分,一种是常规的内存池,也就是进程平时所需要的内存管理;这里主要讲的是内存池管理内存。内存池的结构如下:一般来说,内存池的第一个结点会包含以下的数据结构,而从第二个结点开始,max——log部分会被缺省,当做空间进行分配。nginx使用内存池来管理内存,当进程需要内存时,向内存池申请,使用后释放内存池。

@@老胡的博客 857

基于Vue.js与SpringBoot的学生课程管理系统设计与实现(源码+论文)

学生课程管理系统是一个基于Vue.js前端框架与SpringBoot后端框架的现代化Web应用系统,主要用于高校或教育机构的学生课程管理场景。该系统采用前后端分离架构,实现了学生、教师和管理员角色的完整业务流程,为毕业设计、课程设计提供了高质量的技术实现方案。系统功能方面,学生课程管理系统涵盖了课程管理、选课管理、成绩管理、用户管理等多个核心模块。学生用户可以查看课程信息、进行在线选课、查询个人成绩和课表;教师用户可以发布课程信息、管理学生选课、录入和查询学生成绩;管理员用户则负责系统用户管理、课程信息维护、系统数据统计等高级功能。系统界面友好,操作流程清晰,符合现代教育管理需求。技术实现上,前端采用Vue.js框架配合ElementUI组件库,实现了响应式设计和良好的用户体验。后端基于SpringBoot框架构建,采用分层架构设计,包含控制器层、服务层、数据访问层等。系统使用了单例模式、工厂模式和观察者模式等多种设计模式,提高了代码的可维护性和扩展性。数据交互通过axios实现前后端通信,保证了数据传输的效率和安全性。该毕业设计项目完整实现了学生课程管理系统的所有功能模块,代码结构清晰,注释详细,适合作为计算机科学、软件工程等相关专业的毕业设计参考。系统源码包含完整的项目文件、数据库脚本和部署文档,论文部分详细阐述了系统设计思路、技术选型依据和实现过程。对于正在寻找毕业设计课题的学生来说,这个系统提供了从需求分析、系统设计到编码实现的全过程参考。项目采用当前主流的技术栈,架构设计合理,既体现了技术的前沿性,又保证了系统的实用性。无论是用于学习Vue.js和SpringBoot技术,还是作为课程设计、毕业设计的模板,都具有很高的参考价值。下载该资源后,您可以获得完整的系统源码和配套论文,快速了解前后端分离项目的开发流程,掌握现代化Web系统的设计方法。系

上市公司-托宾Q值数据集.xlsx

上市公司-托宾Q值数据集.xlsx

Nginx源码剖析之内存池,与内存管理

Nginx源码剖析之内存池,与内存管理 作者:July、dreamice、阿波、yixiao。 出处:http://blog.youkuaiyun.com/v_JULY_v/。 引言         Nginx(发音同 engine x)是一款轻量级的Web 服务器/反向代理服务器及电子邮件(IMAP/POP3)代理服务器,并在一个BSD-like 协议下发行。

Cynric 的博客 7493

基于深度学习框架YOLOv8目标检测算法模型训练风力发电机叶片表面缺陷识别检测数据集7K张图像包含腐蚀龟裂隐性龟裂表面附着物表面腐蚀表面眼状缺陷表面损伤表面油污雷击痕迹等十种缺陷类.zip

基于深度学习框架YOLOv8目标检测算法模型训练风力发电机叶片表面缺陷识别检测数据集7K张图像包含腐蚀龟裂隐性龟裂表面附着物表面腐蚀表面眼状缺陷表面损伤表面油污雷击痕迹等十种缺陷类.zip

nginx源码那些事之内存管理模块一

nginx主要使用内存池进行内存管理,nginx中从内存池中分配内存的大小为NGX_MAX_ALLOC_FROM_POOL,为ngx_pagesize - 1,其中ngx_pagesize的大小在操作系统中为4095.         nginx中主要的内存管理函数:         1.创建内存池(ngx_create_pool() )            调用ngx_memalign(

qunqin的专栏 2150

Nginx 内存管理机制深度解析:共享内存空间与平缓内存增长

Nginx通过共享内存空间和按需分配缓冲区架构优势:事件驱动模型避免进程/线程复制开销内存管理:多级内存池 + 缓冲区复用机制性能优化:零拷贝技术减少数据移动开销实际效果:万级并发内存消耗仅为传统模型的1-2%这种设计使Nginx成为高并发场景下的首选解决方案,特别适合云原生、微服务等资源敏感环境。

老韩的Linux云计算架构师进阶之路 1168

nginx slab内存管理机制

slab内存管理

hahackeris的专栏 1149

用gperftools优化Nginx和MySQL内存管理

Google 开发的 gperftools 包含四个工具,分别是:TCMalloc、heap-checker、heap-profiler 和 cpu-profiler,TCMalloc是 gperftools 的其中一个工具,用于优化C++写的多线程应用,与标准的glibc库的malloc相比,TCMalloc在内存的分配效率和速度要高,可以在高并发的情况下很好的控制内存的使用,提高服务...

163
上一篇: 深度学习与计算机视觉(一)
下一篇: nginx 进程模型
@@老胡
博客等级 码龄7年 291粉丝 184原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值