TLSF算法1:二级索引的计算

TLSF算法1:二级索引的计算TLSF算法(一)分配中的位图计算一、什么是TLSF算法二,f的确定三、s的确定四、实验结果一、什么是TLSF算法在嵌入式系统中,内存需要在分配和释放时有一个确定的相应时间,才能进一步分析其实时任务的可调度性。因此TLSF算法是一个十分适用嵌入式领域的动态内存分配算法。在关于TLSf算法的经典文章中《TLSF:aNewDynamicMemoryAllocatorforReal-TimeSystems》详细介绍了TLSF算法相关知识。TLSF算法使用隔离匹配机制来实现良好匹配策略。基本的

大家好,又见面了,我是你们的朋友全栈君。

一、什么是TLSF算法

在嵌入式系统中,内存需要在分配和释放时有一个确定的相应时间,才能进一步分析其实时任务的可调度性。因此TLSF算法是一个十分适用嵌入式领域的动态内存分配算法。在关于TLSf算法的经典文章中《TLSF: a New Dynamic Memory Allocator for Real-Time Systems》详细介绍了TLSF算法相关知识。

TLSF算法使用隔离匹配机制来实现良好匹配策略。基本的隔离匹配机制使用一组空闲列表,每个数组都包含一定大小范围内的空闲块。为了加快访问空闲块以及访问管理大量的隔离列表(以减少碎片),列表数组已组织为两个级别数组。一级数组将空闲块划分为类是2的幂(16、32、64、128等);和第二级将每个第一级类别线性划分,划分的数量(简称第二级别索引数,2SLI)是用户可配置的参数。每个数组列表具有关联的位图,用于标记哪些列表是为空,哪些包含空闲块。每个块有关的信息都存储在块本身中。
TLSF空闲块的结构图
在TLSf的结构中,最主要的算法是位的操作,本文重点分析有关位的操作的原理与代码。当系统需要分配一个指定大小为r的内存时,需要计算出相应的两级位图的值,其公式如下所示:
计算公式
为了有一个直观的结果,我们假设SLI=4,即第二级索引将一级的内存块大小范围划分为2∧SLI=16块,则一级索引f=8,二级索引s=12。
示例

二,f的确定

很显然,f的值就是所需内存大小的二进制位的最高非0位的数。首先最简单可以考虑到的就是从低位遍历即可,不断的对r进行”>>”操作,只要r不为0,就不断执行,同时定义一个变量统计移位的次数。但是因为是嵌入式系统,当然不能采用遍历的方法,会导致内存分配的不确定性。

方法一首先考虑折半查找的方式,32位的数字,折半对比5次既可求出f的值。代码参考如下:

int getF1(int r){ 
   
	int f = 0;
	if(!r){ 
   
		return 0;
	}
	if(r & 0xffff0000){ 
   
		r >>= 16;
		f += 16;
	}
	if(r & 0xff00){ 
   
		r >>= 8;
		f += 8;
	}
	if(r & 0xf0){ 
   
		r >>= 4; 
		f += 4;
	}
	if(r & 12){ 
   
		r >>= 2; 
		f += 2;
	}
	if(r & 2){ 
   
		r >>= 1; 
		f += 1;
	}
	return f;
}

方法二:方法一需要进行6次比较,消耗时间较旧,因此采用空间换时间的方式,一个有8个bit位的数,可以通过一个数组索引出来2∧8=256个数最高的位是几,最后就可以通过查表快速得知最高的bit位数。索引数组的初始化如下:

int TLSF_Table[256];	
int i;
int j = 0;
int k = 0;
TLSF_Table[0] = 0xffffffff;	
for(i=2;i<=256;i=i*2,k++){ 
   
	for(;j<i;j++){ 
   
		TLSF_Table[j]=k;
	}
}

此时,我们看到进行两次对比后,通过查表和移位运算就可以快速确定相应的f值了。

int getF2(int r){ 
   
	int a, f;
	a = r <= 0xffff ? (r <= 0xff ? 0 : 8) : (r <= 0xffffff ? 16 : 24);
	f = TLSF_Table[r >> a] + a;
return f;
}

三、s的确定

从公式中可以知道s,和f,SLI都相关。当然如果先求出f,而SLI已知,自然可以通过计算得出s的值。
方法一,直接通过公式完成相应的计算即可:

int getS1(int r, int f){ 
   
	return (r - (1<<f))>>(f-SLI);
}

方法一计算过程比较繁琐,我们先通过将公式进行简单的化简,再考虑程序的实现。公式化简如下所示:
计算化简
此时减少了频繁的左移和右移,移动一次,再相减即可。最终减少了计算量。

int getS2(int r, int f){ 
   
	return (r >> (f - SLI))- (1<<SLI) ;
}

四、实验结果

将上面几个计算函数实现有后,在main函数中添加测试数据,进行验证,整个程序代码如下。

#include <stdio.h>

static int TLSF_Table[256];
static int SLI = 4;

int getF1(int r){ 
   
	int f = 0;
	if(!r){ 
   
		return 0;
	}
	if(r & 0xffff0000){ 
   
		r >>= 16;
		f += 16;
	}
	if(r & 0xff00){ 
   
		r >>= 8;
		f += 8;
	}
	if(r & 0xf0){ 
   
		r >>= 4; 
		f += 4;
	}
	if(r & 12){ 
   
		r >>= 2; 
		f += 2;
	}
	if(r & 2){ 
   
		r >>= 1; 
		f += 1;
	}
	return f;
}

int getF2(int r){ 
   
	int  a;
	a = r <= 0xffff ? (r <= 0xff ? 0 : 8) : (r <= 0xffffff ? 16 : 24);
	return TLSF_Table[r >> a] + a;
}
	
int getS1(int r, int f){ 
   
	return (r - (1<<f))>>(f-SLI);
}

int getS2(int r, int f){ 
   
	return (r >> (f - SLI))- (1<<SLI) ;
}

main(){ 
   
	int i;
	int j = 0;
	int k = 0;
	TLSF_Table[0] = 0xffffffff;	
	for(i=2;i<=256;i=i*2,k++){ 
   
		for(;j<i;j++){ 
   
			TLSF_Table[j]=k;
		}
	}
	int a=460;
	int f1 = getF1(a);
	int f2 = getF2(a);
	printf("compute f\n");
	printf("first method get f:%d\n", f1);
	printf("second method get f:%d\n", f2);
	printf("compute s\n");
	printf("first method get s:%d\n", getS1(a,f1));
	printf("second method get s:%d\n", getS2(a,f2));
}

程序运行结果,如下。
实验结果
针对内存需求r=460,验证结果符合预期。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/149629.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java集合系列——List集合之Stack介绍(五)「建议收藏」

    Stack的简介Stack 类表示后进先出(LIFO)的对象堆栈。它通过五个操作对类 Vector 进行了扩展 ,允许将向量视为堆栈。它提供了通常的 push 和 pop 操作,以及取堆栈顶点的 peek 方法、测试堆栈是否为空的 empty 方法、在堆栈中查找项并确定到堆栈顶距离的 search 方法。

    2022年2月26日
    42
  • 力矩< torque>详解

    力矩< torque>详解力矩:物理学里是指作用力使得物体绕着转动轴或支点转动的趋向。单位是牛顿-米。力对物体产生转动作用的物理量(分为:力对轴的矩和力对点的矩)即为:M=L*F。L是从转动轴到着力点的距离矢量,F也是矢量力;因此力矩也是矢量。力对轴的矩是力对物体产生绕某一轴转动作用的物理量,其大小等于力在垂直于该轴的平面上的分量和此分力作用线到该轴垂直距离的乘积。例如开门时,外力F平行于门轴的分力FП

    2022年5月14日
    56
  • WIN10系统 Indirect Display 虚拟显示器之特殊应用

    WIN10系统 Indirect Display 虚拟显示器之特殊应用byfanxiushu2020-05-20转载或引用请注明原始作者。有人询问我是否可以实现这样一种功能:对windows输出的每一帧图像数据显示做一些特殊处理(比如球形桌面,曲面化等特效),然后再显示到显示器上。而且还不止一个人这样咨询过,虽然我不大清楚这种需求具体用在何处,估计也是一些特殊场所。这种需求,最先想到的,也最直观的想法就是能否给显卡驱动添加一个过滤驱动,然后拦截图像数据,然后再做些特殊处理。可惜想法是美好的,却是难以实现的,甚至是不大可能实现的。首先windows中就没显卡过

    2022年8月21日
    3
  • sklearn linear regression_auto sklearn

    sklearn linear regression_auto sklearnK折交叉验证:sklearn.model_selection.KFold(n_splits=3,shuffle=False,random_state=None)思路:将训练/测试数据集划分n_splits个互斥子集,每次用其中一个子集当作验证集,剩下的n_splits-1个作为训练集,进行n_splits训练和测试,得到n_splits个结果注意点:对于不能均等份的数据集,其前n_sa

    2022年9月20日
    0
  • json_decode的结果是null

    json_decode的结果是null一、前言      突然发现一个接口出了问题,经过排查之后发现是json_decode($str,true)的问题,返回竟然是null。这个问题大家可能都碰到过,出现问题的原因就那么几种,再次记录一下吧二、原因1、首先使用json_last_error确定问题$arrDataList=json_decode($content…

    2022年7月17日
    16
  • 关于component-scan中base-package包含通配符的问题探究

    关于component-scan中base-package包含通配符的问题探究今天在配置Spring的component-scan时,发现了一个有趣的问题。就是在指定base-package时,如果使用了星号通配符*,有时会出现类扫描不到的情况。下面研究一下这个问题。先介绍一下项目结构: 为了演示,我在java文件夹下创建名为controller的包,并在该包下创建了一个名为IndexController的类。如图所示: 先来看正常情况: 在Spring配置…

    2022年6月13日
    86

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号