自增长容器重新分配内部数组垃圾的大小自适应优化

StringBuilder、MemoryStream等的自增长容器自增长原理是在需要是重新分配更大内部数组或其它。而重新分配就意味着原空间的垃圾生成加重垃圾回收的负担,在内存资源紧张的情况中可能会有比较大的问题产生。因此写了这个自适应库,实践中效果良好。值得注意到是本库适用于访问量比较大的场合。如果访问不很频繁,不需要使用词库,垃圾回收可以很好的处理这些垃圾。

基本原理:

采集一定数量样本sampleCount,设定调整因子levelFactor=80%,然后分析样本,效率原因,这里简单的提取可以适应levelFactor(这里没有取100%是为了剔除少数异常情况,当然各位可以修改为100%)样本大小的数值作为优化值,取优化值的levelFactor(80%)值作为降级线。当失败数量大于levelFactor或降级数大于levelFactor时重新设定优化值。

 

1、样本数据结构

 

    class FitSizeTrackItem

    {

        public int size;

        public DateTime enterTime;

    }

2、序列优化类

 

    class FitSizeTrackSeries : IComparer<FitSizeTrackItem>

    {

        private int ttlMinutes = 60 * 24 * 3;

        private int optimized;

        private int floatDownAlertValue;

        private int sampleCount;

        private int biggerCount;

        private int smallerCount;

        private bool optiRunning = false;

        private double downGradeFactor;

        private double levelFactor;

        private FloatChannel<FitSizeTrackItem> channel;

 

        public FitSizeTrackSeries()

        {

            InitSeries(0.8, 0.5, 100);

        }

 

        public FitSizeTrackSeries(double lvlFactor, double downFactor, int sample)

        {

            InitSeries(lvlFactor, downFactor, sample);

        }

 

        void InitSeries(double lvlFactor, double downFactor, int sample)

        {

            levelFactor = lvlFactor;

            sampleCount = sample;

            downGradeFactor = downFactor;

            channel = new FloatChannel<FitSizeTrackItem>(sampleCount);

        }

 

        public void Track(int size)

        {

            FitSizeTrackItem item = new FitSizeTrackItem();

            item.enterTime = DateTime.Now;

            item.size = size;

            channel.Put(item);

            if (item.size > optimized) ++biggerCount;

            else if (item.size < floatDownAlertValue) ++smallerCount;

            if (biggerCount % sampleCount > levelFactor * 100 || smallerCount % sampleCount > downGradeFactor * 100)

            {

                ThreadPool.QueueUserWorkItem(new WaitCallback(Optimize));

            }

        }

 

        public int Optimized

        {

            get { return optimized; }

            set { floatDownAlertValue = optimized = value; }

        }

 

        void Optimize(object state)

        {

            if (optiRunning) return;

            optiRunning = true;

            try

            {

                biggerCount = (int)(sampleCount * (1 - levelFactor));

                List<FitSizeTrackItem> list = new List<FitSizeTrackItem>();

                for (int i = 0; i < channel.Length; ++i)

                {

                    if (IsValid(channel[i]))

                    {

                        list.Add(channel[i]);

                    }

                }

                list.Sort(this);

                optimized = list[(int)(levelFactor * (list.Count - 1))].size;

                floatDownAlertValue = (int)(list[0].size + levelFactor * (optimized - list[0].size));

                smallerCount = 0;

                for (int i = list.Count - 1; i >= 0; --i)

                    if (list[i].size < floatDownAlertValue)

                        ++smallerCount;

            }

            finally

            {

                optiRunning = false;

            }

        }

 

        bool IsValid(FitSizeTrackItem item)

        {

            return item != null && DateTime.Now.Subtract(item.enterTime).TotalMinutes < ttlMinutes;

        }

 

        public int Compare(FitSizeTrackItem item1, FitSizeTrackItem item2)

        {

            return item1.size - item2.size;

        }

    }

3、优化器类
    class AutoFitSizeOptimizer
    {
        private Hashtable cache = new Hashtable();
        public void Track(IAutoFitSize auto, int size)
        {
            FitSizeTrackSeries series = this[auto];
            series.Track(size);
        }
        public int OptimizedSize(IAutoFitSize auto)
        {
            FitSizeTrackSeries fit = this[auto];
            return fit.Optimized;
        }
        public FitSizeTrackSeries this[IAutoFitSize auto]
        {
            get
            {
                FitSizeTrackSeries series = cache[auto] as FitSizeTrackSeries;
                if (series == null)
                {
                    lock (cache.SyncRoot)
                    {
                        series = new FitSizeTrackSeries();
                        series.Optimized = auto.DefaultSize;
                        cache[auto] = series;
                    }
                }
                return series;
            }
        }
    }
3、使用接口
  interface IAutoFitSize
    {
        object Key { get; set; }
        int DefaultSize { get; set; }
    }
4、帮助结构
   此结构是一个非循环数组,不重复分配内存以保证高效,这里存在一个问题,就是访问量很集中时可能新数据可能被旧数据覆盖,考虑到如此集中的情况下两个样本不存在必然的差异,因此采用此结构。
    class FloatChannel<T>
    {
        private int position;
        private T[] buckets;
        private object locker = new object();
        public FloatChannel(int capicity)
        {
            buckets = new T[capicity];
            position = -1;
        }
        int GetNextPosition()
        {
            int pos = -1;
            lock (locker)
            {
                if (++position >= buckets.Length)
                    position = 0;
                pos = position;
            }
            return pos;
        }
        public void Put(T value)
        {
            int p = GetNextPosition();
            buckets[p] = value;
        }
        public int Length
        {
            get { return buckets.Length; }
        }
        public T this[int index]
        {
            get { return buckets[index]; }
        }
    }

 

 

5、使用方法:

 

 

使用的类应事先IAutoFitSize,应为每个需优化的场景创建单独的优化器,或者使用不同的Key区分。
class Test: IAutoFitSize
{
public int Key
{
get{return 1;}
set{;}
public int DefaultSize
{
get{return 16;}
set{;}

...
AutoFitSizeOptimizer optimizer=new AutoFitSizeOptimizer();
....
Test t=new Test();
a、追踪样本:
    optimizer.Track( realSize);
b、提取优化值:
    int optimized=optimizer.OptimizedSize(t)
 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值