操作系统实验二——内存平均利用率与分配策略的研究

原创 2006年05月22日 12:10:00

    参考windows任务管理器中内存占用的情况,在256M的总内存中,各个进程所占的内存从几十K到几十M不等,基本可以看成是均匀分布。即,每个进程申请使用的内存占总内存的百分比比较接近实际的数据为从千分之几到百分之十几,在这里,我们取从0.02%15%

    但是为了说明情况,在实验中,我将申请内存占总内存的比率分为六个区间,分别为:0.02%——2%0.02%——8%0.02%——15%0.02%——25%0.02%——40%0.02%——60%。对于四种不同的分配策略,分别考察从区间0.02%——2%变化到0.02%——60%时内存平均利用率的变化情况。可以得出较一般的结论。

实验结果如下:

将实验结果用图示的方法表现出来如下图所示:

    从这张内存分配策略实验比较图可以看出,总体来说,仅就内存平均利用率这一个指标来看,best-fit > first-fit > next-fit > worst-fit。且随着申请内存占总内存比率的增大,各种分配策略的内存平均利用率趋于一致。从各种分配策略单独来看,随着申请内存占总内存比率的增大,各种分配策略的内存平均利用率都有所下降,但下降的速率有所差别。相比较而言,平均利用率最大的best-fit下降的幅度最大,而平均利用率最小的worst-fit下降的幅度最小,first-fitnext-fit居于它们之间。

    总体结论:内存平均利用率的好坏不仅和内存的分配策略有关,还和进程申请内存占总内存的平均比率有关。在同等条件下,若仅考虑内存分配策略,则best-fit > first-fit > next-fit > worst-fit,若仅考虑申请内存占总内存的比率,则随着申请内存占总内存比率的增大,内存平均使用率下降,下降的斜率best-fit > first-fit > next-fit > worst-fit

附:

对程序的一点说明:

程序中,用两个数据结构来维护内存使用状况,分别是USED_LINKFREE_LINK。链表中的每一项都是一个BLOCK_NODE,其定义为:

typedef struct block{
 //int blockId;
 int startPosition;
 int endPosition;
 int length;
 struct block *next;
} BLOCK_NODE, *pBLOCK_NODE;

程序中,模拟内存的大小为256M,即

#define MEM_SIZE 268435456 //256M

内存初始化,申请内存以及释放内存的函数分别定义为:

void mem_init();

int mem_request(int size, STRATEGY strategy);

bool mem_release(int startPosition);

其中,STRATEGY对应于四种不同的分配策略:

typedef enum {FIRST_FIT, NEXT_FIT, BEST_FIT, WORST_FIT} STRATEGY;

完整的源代码如下:

mem.h

#ifndef _MEM_H
#define _MEM_H

#include <stdio.h>

//#define MEM_SIZE 1024   //1K
//#define MEM_SIZE 1048576  //1M
#define MEM_SIZE 268435456 //256M

typedef struct block{
 //int blockId;
 int startPosition;
 int endPosition;
 int length;
 struct block *next;
} BLOCK_NODE, *pBLOCK_NODE;

typedef struct {
 pBLOCK_NODE head;
 pBLOCK_NODE tail;
 int blockNum;
}USED_LINK, FREE_LINK;

typedef enum {FIRST_FIT, NEXT_FIT, BEST_FIT, WORST_FIT} STRATEGY;

void mem_init();
int mem_request(int size, STRATEGY strategy);
bool mem_release(int startPosition);

#endif

 

mem.cpp

#include <stdio.h>
#include <memory.h>
#include "mem.h"

USED_LINK used_link;
FREE_LINK free_link;

pBLOCK_NODE fromThis = free_link.head;
//char memory[MEM_SIZE];

//内存初始化。
void mem_init() {
 //memset(memory, 0, MEM_SIZE);

 //使用链表置空。
 used_link.head = NULL;
 used_link.tail = NULL;
 used_link.blockNum = 0;

 //空闲连标初始为一个完整的空闲块,块大小为整个内存区。
 pBLOCK_NODE tmp = new BLOCK_NODE;
 tmp->startPosition = 0;
 tmp->endPosition = MEM_SIZE - 1;
 tmp->length = MEM_SIZE;
 tmp->next = NULL;

 free_link.head = tmp;
 free_link.tail = tmp;
 free_link.blockNum = 1;
}

//内存请求,按一定的分配策略分配,
//并返回分配后内存的首地址。
int mem_request(int size, STRATEGY strategy) {
 //若size小于等于零或者大于总内存大小,则错误返回。
 if (size <= 0 || size > MEM_SIZE) {
  //printf("Memory size error!/n");
  return -1;
 }

 pBLOCK_NODE temp = NULL;

 //first_fit
 //搜索能够满足请求的内存块。
 //若没有满足要求的内存块,则返回-1。
 if (strategy == FIRST_FIT) {
  temp = free_link.head;
  while (free_link.blockNum > 0) {
   if (temp == NULL) {
    break;
   } else if (temp->length >= size) {
    break;
   } else {
    temp = temp->next;
   }
  }
 }

 //next_fit strategy
 if (strategy == NEXT_FIT) {
  int blockNum = free_link.blockNum;
  for (int i = 0; i < blockNum; i++) {
   if (fromThis == NULL) {
    fromThis = free_link.head;
   }
   if (fromThis->length >= size) {
    temp = fromThis;
    fromThis = fromThis->next;
    break;
   } else {
    fromThis = fromThis->next;
   }
  }
 }

 //best_fit
 if (strategy == BEST_FIT) {
  int t = MEM_SIZE + 1;
  pBLOCK_NODE tp = free_link.head;
  while (free_link.blockNum > 0) {
   if (tp == NULL) {
    break;
   } else if (tp->length >= size) {
    if (tp->length < t) {
     temp = tp;
     t = tp->length;
    }
    tp = tp->next;
   } else {
    tp = tp->next;
   }
  }
 }

 //worst_fit strategy
 if (strategy == WORST_FIT) {
  int t = 0;
  pBLOCK_NODE tp = free_link.head;
  while (free_link.blockNum > 0) {
   if (tp == NULL) {
    break;
   } else if (tp->length >= size) {
    if (tp->length > t) {
     temp = tp;
     t = tp->length;
    }
    tp = tp->next;
   } else {
    tp = tp->next;
   }
  }
 }

 if (temp == NULL) {
  //printf("Alloc Failed!/n");
  return -1;
 } else {
  //若存在满足要求的内存块,则创建新的内存块。
  pBLOCK_NODE newNode = new BLOCK_NODE;
  newNode->startPosition = temp->startPosition;
  newNode->endPosition = newNode->startPosition + size - 1;
  newNode->length = size;
  newNode->next = NULL;

  //将新分配的内存块信息插入到使用链表中。
  if (used_link.blockNum == 0) {
   used_link.head = newNode;
   used_link.tail = newNode;
   used_link.blockNum = 1;
  } else if (used_link.blockNum >= 1) {
   //按内存块首地址递增的方式插入。
   pBLOCK_NODE preNode = NULL;
   pBLOCK_NODE curNode = used_link.head;
   if (newNode->startPosition < curNode->startPosition) {
    newNode->next = used_link.head;
    used_link.head = newNode;
    used_link.blockNum++;
   } else {
    while (curNode->startPosition < newNode->startPosition) {
     preNode = curNode;
     curNode = curNode->next;
     if (curNode == NULL) {
      break;
     }
    }
    if (curNode == NULL) {
     used_link.tail->next = newNode;
     used_link.tail = newNode;
     used_link.blockNum++;
    } else {
     newNode->next = curNode;
     preNode->next = newNode;
     used_link.blockNum++;
    }
   }
  }

  //修改空闲链表中可用内存块的信息。
  if (temp->length == size) {
   if (temp == free_link.head) {
    free_link.head = temp->next;
    if (free_link.head == NULL) {
     free_link.tail = NULL;
    }

    delete temp;
    free_link.blockNum--;
   } else {
    pBLOCK_NODE preNode = free_link.head;
    pBLOCK_NODE curNode = free_link.head->next;
    while (temp != curNode) {
     preNode = curNode;
     curNode = curNode->next;
    }
    if (curNode == free_link.tail) {
     free_link.tail = preNode;
     preNode->next = NULL;
    } else {
     preNode->next = curNode->next;
    }

    delete temp;
    free_link.blockNum--;
   }
  } else if (temp->length > size) {
   temp->startPosition += size;
   temp->length -= size;
  }

  //返回分配成功后的首地址。
  return newNode->startPosition;
 }
}

bool mem_release(int startPosition) {
 pBLOCK_NODE release_target = used_link.head;
 pBLOCK_NODE preNode = NULL;

 //此时使用链表为空。
 if (release_target == NULL) {
  printf("No such alloced memory!/n");
  return false;
 }
 //搜索需要释放的内存块。
 while (release_target->startPosition != startPosition) {
  preNode = release_target;
  release_target = release_target->next;
  if (release_target == NULL) {
   break;
  }
 }

 //修改使用链表中内存使用信息。删除释放内存的信息结点。
 if (release_target == NULL) {
  printf("No such alloced memory!/n");
  return false;
 } else if (release_target == used_link.head && release_target == used_link.tail) {
  used_link.head = NULL;
  used_link.tail = NULL;
  used_link.blockNum--;
 } else if (release_target == used_link.head) {
  used_link.head = used_link.head->next;
  used_link.blockNum--;
 } else if (release_target == used_link.tail) {
  preNode->next = release_target->next;
  used_link.tail = preNode;
  used_link.blockNum--;
 } else {
  preNode->next = release_target->next;
  used_link.blockNum--;
 }

 //修改空闲链表信息,将释放后可重新使用的内存块信息写入空闲链表,
 //并进行必要的合并。
 pBLOCK_NODE insertBefore = free_link.head;
 preNode = NULL;
 if (free_link.head == NULL) {
  free_link.head = release_target;
  free_link.tail = release_target;
  release_target->next = NULL;
  free_link.blockNum++;
 } else if (release_target->startPosition < free_link.head->startPosition) {
  if (release_target->endPosition + 1 == free_link.head->startPosition) {
   free_link.head->startPosition = release_target->startPosition;
   free_link.head->length += release_target->length;
   delete release_target;
  } else {
   release_target->next = free_link.head;
   free_link.head = release_target;
   free_link.blockNum++;
  }
 } else {
  while (insertBefore->startPosition < release_target->startPosition) {
   preNode = insertBefore;
   insertBefore = insertBefore->next;
   if (insertBefore == NULL) {
    break;
   }
  }
  if (insertBefore == NULL) {
   if (release_target->startPosition - 1 == preNode->endPosition) {
    preNode->endPosition = release_target->endPosition;
    preNode->length += release_target->length;
    delete release_target;
   } else {
    preNode->next = release_target;
    free_link.tail = release_target;
    release_target->next = NULL;
    free_link.blockNum++;
   }
  } else {
   if (release_target->startPosition - 1 == preNode->endPosition
    && release_target->endPosition + 1 == insertBefore->startPosition) {
    if (insertBefore == free_link.tail) {
     preNode->endPosition = insertBefore->endPosition;
     preNode->length += (release_target->length + insertBefore->length);
     preNode->next = insertBefore->next;

     if (fromThis == insertBefore) {
      fromThis = preNode;
     }

     delete insertBefore;
     delete release_target;
     free_link.tail = preNode;
     free_link.blockNum--;
    } else {
     preNode->endPosition = insertBefore->endPosition;
     preNode->length += (release_target->length + insertBefore->length);
     preNode->next = insertBefore->next;

     if (fromThis == insertBefore) {
      fromThis = preNode;
     }

     delete insertBefore;
     delete release_target;
     free_link.blockNum--;
    }
   } else if (release_target->startPosition - 1 == preNode->endPosition) {
    preNode->endPosition = release_target->endPosition;
    preNode->length += release_target->length;
    delete release_target;
   } else if (release_target->endPosition + 1 == insertBefore->startPosition) {
    insertBefore->startPosition = release_target->startPosition;
    insertBefore->length += release_target->length;
    delete release_target;
   } else {
    release_target->next = preNode->next;
    preNode->next = release_target;
    free_link.blockNum++;
   }
  }
 }

 return true;
}

 

allocate.cpp

#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include "mem.h"

#define ROUNDS 1000000
extern FREE_LINK free_link;
extern USED_LINK used_link;

int computeSize(double rangeLow, double rangeHigh);
double computeFraction(STRATEGY strategy, double rangeLow, double rangeHigh);
double averageRand(double min, double max);
void computeAndPrint(double rangeLow, double rangeHigh);

main() {
 mem_init();
 srand((unsigned)time(NULL));

 printf("申请内存占总内存比率为0.02%%--2%%时:/n");
 computeAndPrint(0.0002, 0.02);
 printf("/n申请内存占总内存比率为0.02%%--8%%时:/n");
 computeAndPrint(0.0002, 0.08);
 printf("/n申请内存占总内存比率为0.02%%--15%%时:/n");
 computeAndPrint(0.0002, 0.15);
 printf("/n申请内存占总内存比率为0.02%%--25%%时:/n");
 computeAndPrint(0.0002, 0.25);
 printf("/n申请内存占总内存比率为0.02%%--40%%时:/n");
 computeAndPrint(0.0002, 0.40);
 printf("/n申请内存占总内存比率为0.02%%--60%%时:/n");
 computeAndPrint(0.0002, 0.60);

 return 0;
}

void computeAndPrint(double rangeLow, double rangeHigh) {
 printf("first_fit内存平均利用率:/t%f/n", computeFraction(FIRST_FIT, rangeLow, rangeHigh));
 printf("next_fit内存平均利用率:/t%f/n", computeFraction(NEXT_FIT, rangeLow, rangeHigh));
 printf("best_fit内存平均利用率:/t%f/n", computeFraction(BEST_FIT, rangeLow, rangeHigh));
 printf("worst_fit内存平均利用率:/t%f/n", computeFraction(WORST_FIT, rangeLow, rangeHigh));
}

double computeFraction(STRATEGY strategy, double rangeLow, double rangeHigh) {
 int pointerTemp = -1;
 double fraction = 0;
 for (int i = 0; i < ROUNDS; i++) {
  int requestSize = 0;
  do {
   requestSize = computeSize(rangeLow, rangeHigh);
   pointerTemp = mem_request(requestSize, strategy);
  } while (pointerTemp != -1);

  int temp = 0;
  pBLOCK_NODE nodeTemp = free_link.head;
  while (nodeTemp != NULL) {
   temp += nodeTemp->length;
   nodeTemp = nodeTemp->next;
  }
  fraction += (MEM_SIZE - (double)temp)/MEM_SIZE;

  if (used_link.blockNum != 0) {
   int releaseBlock = rand() % used_link.blockNum;
   nodeTemp = used_link.head;
   for (int j = 0; j < releaseBlock; j++) {
    nodeTemp = nodeTemp->next;
   }
   mem_release(nodeTemp->startPosition);
  }
 }
 fraction /= ROUNDS;

 //printf("Average used fraction: %f/n", fraction);
 return fraction;
}

int computeSize(double rangeLow, double rangeHigh) {
 return (int)(averageRand(rangeLow, rangeHigh)*MEM_SIZE);
}

double averageRand(double min, double max) {
 int minInteger = (int)(min*10000);
 int maxInteger = (int)(max*10000);
 int diffInteger = maxInteger - minInteger;
 double randInteger = (double)rand()/RAND_MAX;
 int resultInteger = (int) ( randInteger * diffInteger + minInteger );

 return resultInteger/10000.0;
}

相关文章推荐

Delphi7高级应用开发随书源码

  • 2003年04月30日 00:00
  • 676KB
  • 下载

深入理解Java虚拟机学习笔记——二、垃圾收集器与内存分配策略

1、对象是否存活判定算法 引用计数算法 给对象添加一个引用计数器,当有其他对象引用它时,计数器加1;当引用失效时,计数器减1。任何时刻计数器为0的对象就是不可能在被使用的。引用计数算法实现简单,判...

ptmalloc,tcmalloc和jemalloc内存分配策略研究

url:https://www.owent.net/2013/07/ptmalloctcmalloc%E5%92%8Cjemalloc%E5%86%85%E5%AD%98%E5%88%86%E9%85...

ptmalloc,tcmalloc和jemalloc内存分配策略研究

最近看了glibc的ptmaoolc,Goolge的tcmalloc和jemalloc,顺便做了一点记录。可能有些地方理解地不太对,如有发现还请大神指出。   操作系统内存布局     各种ma...

《深入理解java虚拟机》笔记——第三章 垃圾收集器与内存分配策略

第三章 3.1 概述 哪些内存需要回收? 什么时候回收? 怎么回收? 这里垃圾回收器关注的是Java堆和方法区的内存,程序计数器、虚拟栈、本地方法栈三个区域会随着线程而生,随着线程而灭, 不用...

JVM学习笔记——垃圾收集器与内存分配策略(1)

概述上一篇文章介绍了java运行时内存的各个区域,其中虚拟机栈,程序计数器,本地方法栈三个区域随线程而生,随线程而灭。栈中的栈帧随着方法的进入和退出有条不紊的执行着出栈与入栈的操作,每一个栈帧分配多少...

深入理解JVM(四)——对象内存的分配策略

http://blog.csdn.net/u010425776/article/details/51192448 Java所承诺的自动内存管理主要是针对对象内存的回收和对象内存的分配。 ...

垃圾收集器与内存分配策略——对象的生命、垃圾收集算法

为什么要了解垃圾回收?——当需要排查各种内存溢出、内存泄露问题时,当垃圾收集成为系统达到更高并发量的瓶颈时,我们就需要对这些“自动化”的技术实施必要的监控和调节     如何判断对象已死?      ...

深入理解Java虚拟机 读书笔记——垃圾收集器与内存分配策略

第3章 垃圾收集器与内存分配策略关于Java中的引用类型 强引用(Strong Reference):Object obj = new Object(); 这样的常规引用,只要引用还在,就永远不会回收...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:操作系统实验二——内存平均利用率与分配策略的研究
举报原因:
原因补充:

(最多只允许输入30个字)