封装:内存镜像文件(MemoryMappedFile)封装,一维二维三维定点访问

MemoryMappedFile简介:



1、问题:公司底层限制使用32位应用程序,针对大数据数据模型会产生内存溢出;

2、解决方案:C#中可以使用MemoryMappedFile类将内存映射到硬盘中,将大网格数据保存在硬盘中节省内存;


3、实测结果:读取写入速度可以接受,持久化效果良好;

4、针对使用结构进行了如下封装,可用于泛型索引访问

    /// <summary> 泛型 T 内存映射文件 </summary>
    public partial class MmfEntity<T> where T : struct
    {
        #region - 成员变量 -

        private long _size;
        /// <summary> 文件大小 </summary>
        public long Size
        {
            get { return _size; }
        }

        /// <summary> 实体大小 </summary>
        public int MLeight
        {
            get { return Marshal.SizeOf(typeof(T)); }
        }

        private int _count;
        /// <summary> T 类型的数量 </summary>
        public int Count
        {
            get { return _count; }
            set
            {
                //  设置容器大小
                this._size = MLeight * value;

                _count = value;
            }
        }

        private string _file;
        /// <summary> 文件全路径 </summary>
        public string FileInf
        {
            get { return _file; }
            set { _file = value; }
        }

        private string _name;
        /// <summary> 镜像名称 </summary>
        public string Name
        {
            get
            {
                if (string.IsNullOrEmpty(_name))
                {
                    _name = Path.GetFileNameWithoutExtension(_file);
                }
                return _name;
            }
        }

        private MemoryMappedFile _mmf;
        /// <summary> 内存镜像 </summary>
        protected MemoryMappedFile Mmf
        {
            get
            {
                BuildFile();

                return _mmf;
            }
        }





        /// <summary> 创建文件 </summary>
        void BuildFile()
        {
            if (File.Exists(this.FileInf))
            {
                this.Dispose();

                File.Delete(this.FileInf);
            }



            //  如果存在删除
            _mmf = MemoryMappedFile.CreateFromFile(this.FileInf, FileMode.OpenOrCreate, _name, _size, MemoryMappedFileAccess.ReadWriteExecute);


        }

        private MemoryMappedViewAccessor _mapView;
        /// <summary> 随机访问视图  </summary>
        protected MemoryMappedViewAccessor MapView
        {
            get
            {
                if (_mmf == null)
                {
                    this.BuildFile();
                }

                if (_mapView == null)
                {
                    _mapView = _mmf.CreateViewAccessor();
                }

                return _mapView;
            }
        }

        private MemoryMappedViewStream _mapStream;
        /// <summary> 按循序访问的流 </summary>
        protected MemoryMappedViewStream MapStream
        {
            get
            {

                if (_mmf == null)
                {
                    this.BuildFile();
                }

                if (_mapStream == null)
                {
                    _mapStream = _mmf.CreateViewStream();
                }


                return _mapStream;
            }
            private set { _mapStream = value; }
        }

        #endregion

        /// <summary> 将 T 类型的结构从访问器读取到提供的引用中 </summary>
        public T GetPostion(long position)
        {
            T structure;

            MapView.Read<T>(position, out structure);

            return structure;
        }

        /// <summary> 读取指定索引处结构 </summary>
        public T GetIndex(int index)
        {
            long postion = index * this.MLeight;

            return this.GetPostion(postion);
        }

        /// <summary> 将 T 类型的结构从访问器读取到 T 类型的数组中 </summary>
        public T[] GetPostion(int count, long position = 0)
        {
            T[] arr = new T[count];

            MapView.ReadArray<T>(position, arr, 0, count);

            return arr;
        }

        /// <summary> 将 T 类型的结构从访问器读取到 T 类型的数组中 </summary>
        public T[] GetAll(long position = 0)
        {
            T[] arr = new T[this._count];

            MapView.ReadArray<T>(position, arr, 0, this._count);

            return arr;
        }

        /// <summary> 将一个结构写入访问器 </summary>
        public void SetPosition(long position, T structure)
        {
            MapView.Write<T>(position, ref structure);
        }

        /// <summary> 写入指定索引处结构 </summary>
        public void SetIndex(int index, T structure)
        {
            long postion = index * this.MLeight;

            this.SetPosition(postion, structure);

        }

        /// <summary> 将结构从 T 类型的数组写入访问器 </summary>
        public void SetPosition(long position, T[] arr)
        {
            MapView.WriteArray<T>(position, arr, 0, arr.Length);
        }

        /// <summary> 将结构从 T 类型的数组写入访问器 </summary>
        public void SetAll(T[] arr)
        {
            MapView.WriteArray<T>(0, arr, 0, arr.Length);
        }

        /// <summary> 将结构从 T 类型的数组写入访问器 </summary>
        public void SetAll(T t)
        {
            T[] arr = new T[this.Count];

            this.Count.DoCountWhile(l => arr[l] = t);

            MapView.WriteArray<T>(0, arr, 0, this.Count);
        }



        /// <summary> 重置大小 </summary>
        public void ReSetSize(int count)
        {
            this._count = count;

            this._size = count * this.MLeight;

            this.BuildFile();
        }


    }

    partial class MmfEntity<T> : IDisposable
    {
        #region - 构造函数 -

        public MmfEntity(string fileFullPath, int Tcount)
        {
            this._file = fileFullPath;

            this._count = Tcount;

            this._size = Tcount * this.MLeight;

            this._name = Path.GetFileNameWithoutExtension(fileFullPath);

            this.BuildFile();
        }

        #endregion


        #region - 资源释放 -

        private bool _isDisposed = false;

        ~MmfEntity()
        {
            Dispose(false);
        }

        public void Dispose()
        {
            Dispose(true);
            GC.SuppressFinalize(this);
        }
        protected virtual void Dispose(bool disposing)
        {
            if (!_isDisposed)
            {
                if (disposing)
                {
                    if (this._mapView != null) this._mapView.Dispose();

                    if (this._mmf != null) this._mmf.Dispose();
                }
                this._isDisposed = true;
            }
        }

        #endregion
    }

5、针对二维三维的定点结构访问

    /// <summary> 二维存储结构 </summary>
    public class DxyMmfEntity<T> : MmfEntity<T> where T : struct
    {
        #region - 构造函数 -
        public DxyMmfEntity(string fileFullPath, int Tcount)
            : base(fileFullPath, Tcount)
        {
        }

        #endregion

        private int _x;
        /// <summary> X维数 </summary>
        public int X
        {
            get { return _x; }
            set { _x = value; }
        }

        private int _y;
        /// <summary> Y维数 </summary>
        public int Y
        {
            get { return _y; }
            set { _y = value; }
        }

        public void Set(int x, int y, T value) 
        {
            this.SetIndex(TranFucntion(x, y), value);
        }

        /// <summary> 获取指定二维值 </summary>
        public T Get(int x, int y)
        {
            return this.GetIndex(TranFucntion(x, y));
        }

        Func<int, int, int> tranFucntion;
        /// <summary> 设置指定二维值 </summary>
        public Func<int, int, int> TranFucntion
        {
            get { return (x, y) => y * this.X + x; }
        }


    }


    /// <summary> 三维存储结构 </summary>
    public class DxyzMmfEntity<T> : MmfEntity<T> where T : struct
    {
        #region - 构造函数 -
        public DxyzMmfEntity(string fileFullPath, int x, int y, int z)
            : base(fileFullPath, x * y * z)
        {
            this.X = x;
            this.Y = y;
            this.Z = z;
        }

        /// <summary> 初始化方法 </summary>
        public void Init(int x, int y, int z)
        {
            this.X = x;
            this.Y = y;
            this.Z = z;

            base.ReSetSize(x * y * z);
        }
        #endregion

        private int _x;
        /// <summary> X维数 </summary>
        public int X
        {
            get { return _x; }
            set { _x = value; }
        }

        private int _y;
        /// <summary> Y维数 </summary>
        public int Y
        {
            get { return _y; }
            set { _y = value; }
        }

        private int _z;
        /// <summary> Z方向维数 </summary>
        public int Z
        {
            get { return _z; }
            set { _z = value; }
        }

        public void Set(int x, int y, int z, T value)
        {
            this.SetIndex(TranFucntion(x, y, z), value);
        }

        /// <summary> 获取指定二维值 </summary>
        public T Get(int x, int y, int z)
        {
            return this.GetIndex(TranFucntion(x, y, z));
        }

        Func<int, int, int> tranFucntion;
        /// <summary> 设置指定二维值 </summary>
        public Func<int, int, int, int> TranFucntion
        {
            get { return (x, y, z) => z * this.X * this.Y + y * this.X + x; }
        }
    }

6,测试用例

 class Program
    {
        static void Main(string[] args)
        {
            long offset = 0x10000000; // 256 megabytes
            long length = 0x20000000; // 512 megabytes

            long test = 800 * 1024;// 800 * 1024 * 1024;// 800MB

            DateTime time = DateTime.Now;
            Console.WriteLine("开始创建文件!");

            using (MmfEntity<int> mmf = new MmfEntity<int>(@"E:\ExtremelyLargeImage.data", 100))
            {

                for (int i = 0; i < 100; i++)
                {
                    mmf.SetIndex(i, i);
                }

                for (int i = 0; i < 100; i++)
                {
                    Console.WriteLine("执行:" + i + "  值:" + mmf.GetIndex(i));
                }
            }
           Console.WriteLine("完成!");
        Console.WriteLine("大小:" + test + "用时:" + (DateTime.Now - time).ToString());
        Console.Read();
      }
}

7、MemoryMappedFile结构图



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值