精华内容
下载资源
问答
  • 易语言复制内存速度测试源码,复制内存速度测试,test2,test1,MemCpy_rep,MemCpy,MemCpy_2,MemCpy_rep_4,RtlMoveMemory
  • 内存复制速度居然和内存的内容相关 memcpy 和 一个字节一个字节的复制的一个区别就是,memcpy 可以复制一个cpu 的字 而 单字节复制只能复制一个字节。 但是,今天还发现了一个很重要的特点,...

    内存复制的速度居然和内存的内容相关

    memcpy 和 一个字节一个字节的复制的一个区别就是,memcpy 可以复制一个cpu 的字 而 单字节复制只能复制一个字节。

    但是,今天还发现了一个很重要的特点,复制的速度 还和 内存的内容相关,如果目标内存 和 当前内存的内容差不多,发现

    居然复制速度要快一些。

     

    这个是我在测试字符串复制的性能的时候发现的,可以参考我前面的文章。

    http://www.cnblogs.com/niniwzw/archive/2009/12/23/1630777.html

    前面文章中,我说的最后一种速度是 96ms, 是错误的。

    测试代码如下:

        t = clock();
        strcpy1(dest, src); //我的复制方法 140ms
        printf("%d ms\n", clock() - t);
        t = clock();
        strcpy(dest, src); //系统函数的复制方法  96ms
        printf("%d ms \n", clock() - t);


        t = clock();
        strcpy(dest, src); //系统函数的复制方法  140ms
        printf("%d ms \n", clock() - t);

        t = clock();
        strcpy1(dest, src); //我的复制方法 96ms
        printf(" %d ms\n", clock() - t);

     

    如果你测试一下 用memcpy,可以发现这 96ms就是memcpy复制这个内存区域的速度。

    具体原因不知道是为什么。哪位高手可以告诉我。

    posted @ 2009-12-28 14:11 暮夏 阅读(...) 评论(...) 编辑 收藏
    展开全文
  • 易语言源码易语言复制内存速度测试源码.rar
  • 如果是在DOS下,则应在autoexec.bat 文件中加入一行“LH C:\dos\smartdrv.exe”(这里假设smartdrv 程序在C:\dos 目录下),即可实现内存作为硬盘的缓存。 如果您想使其成为光驱的 缓存,只要把autoexec.bat中的执行...
  • swprintf(message_, L"复制成功,共耗时%f秒, 平均速度%fMB/s", seconds, total_bytes / (SZ(1, M) * seconds)); MessageBox(get_handle(), message_, L"提示", MB_OK | MB_ICONINFORMATION); } else { ...
    如题,先贴图,后续上传源码和exe
    测试文件大小7.08GB:

    结果:


    商业软件ExtremeCopy 2.1测试结果:
    最新代码:
    /*
    * Copyright (c) purelib 2012-2015.
    */
    #include <purelib/movable_window.h>
    #include <purelib/file_mapping.h>
    #include <purelib/controls.h>
    #include <purelib/nsconv.h>
    #include <thread>
    using namespace purelib;
    using namespace purelib::gui;
    using namespace purelib::filesystem;
    
    #ifdef _DEBUG
    #pragma comment(lib, "purelib32_d.lib")
    #else
    #pragma comment(lib, "purelib32.lib")
    #endif
    
    class fixed_window : public movable_window
    {
    public:
        fixed_window()
        {
            append_style(WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU);
        }
    };
    
    class extremely_copier : public fixed_window
    {
    public:
    
        extremely_copier()
        {
    		set_opacity(0.95f);
            set_text(L"extremely_copier");
            resize(700, 360);
            int delta = 30;
    
            this->input_.reset(new controls::xxedit(L"D:\\vs2013.4_ult_chs.iso", 17, 10, 200, 25, *this, WS_BORDER | ES_AUTOHSCROLL));
            this->input_->set_font(purelib::gui::DEF_FONT_NORM_10);
            this->input_->set_left(5);
            this->input_->set_top(5);
    
            this->output_.reset(new controls::xxedit(L"D:\\TDDOWNLOAD\\bak\\vs2013.4_ult_chs.iso", 17, 10, 200, 25, *this, WS_BORDER | ES_AUTOHSCROLL));
            this->output_->set_font(purelib::gui::DEF_FONT_NORM_10);
            this->output_->set_left(350 + 20);
            this->output_->set_top(5);
    
    
            this->time_used_.reset(new controls::xxedit(L"00:00:00", 17, 10, 200, 25, *this, WS_BORDER | ES_READONLY | ES_AUTOHSCROLL));
            this->time_used_->set_font(purelib::gui::DEF_FONT_NORM_10);
            this->time_used_->set_left(5);
            this->time_used_->set_top(100);
    
            this->launcher_.reset(new controls::xxbutton(L"启动复制", 17, 10, 118, 25, *this, WS_BORDER | BS_PUSHBUTTON));
            this->launcher_->set_font(purelib::gui::DEF_FONT_BOLD_10);
            this->launcher_->set_left(this->output_->get_location().x + this->output_->get_size().width);
            this->launcher_->set_top(280 + 15 + delta);
    
            this->cachesize_.reset(new controls::xxedit(L"8192", 17, 10, 200, 25, *this, WS_BORDER | ES_AUTOHSCROLL | ES_NUMBER));
            this->cachesize_->set_font(purelib::gui::DEF_FONT_NORM_10);
            this->cachesize_->set_left(this->output_->get_location().x + this->output_->get_size().width - delta - this->cachesize_->get_size().width);
            this->cachesize_->set_top(280 + 15 + delta);
    
            progress_.reset(new controls::xxprogressbar(17, 280, 670, 25, *this));
    
            register_event(WM_TIMER, [this](void){
                ++time_used_seconds_;
    
                auto hh = time_used_seconds_ / 3600;
                auto left = time_used_seconds_ - hh * 3600;
                auto mm = left / 60;
                auto ss = left % 60;
    
                static wchar_t svalue[128];
                swprintf(svalue, L"%02d:%02d:%02d", hh, mm, ss);
                time_used_->set_text(svalue);
            });
    
            register_event(this->launcher_->get_id(), [this](void){
    			// start new worker thread, avoid block UI thread.
                std::thread copier([this]{
                    auto input = input_->get_text();
                    auto output = output_->get_text();
                    auto cachesize = atol(nsc::transcode(cachesize_->get_text()).c_str());
                    if (cachesize == 0)
                        cachesize = 8192;
                    
                    launcher_->set_text(L"正在复制...");
                    launcher_->disable();
                    progress_->set_value(0);
    
                    uint64_t total_bytes = 0;
                    
                    time_used_seconds_ = 0;
                    this->start_timer(1000);
                    auto start = clock();
                    if ((total_bytes = progress_->extremely_copy(input.c_str(), output.c_str(), cachesize)) > 0)
                    {
                        auto seconds = (clock() - start) / (long double)CLOCKS_PER_SEC;
                        
                        this->stop_timer();
    
                        swprintf(message_, L"复制成功,共耗时%f秒, 平均速度%fMB/s", seconds, total_bytes / (SZ(1, M) * seconds));
                        
                        MessageBox(get_handle(), message_, L"提示", MB_OK | MB_ICONINFORMATION);
                    }
                    else
                    {
                        MessageBox(get_handle(), L"复制失败", L"提示", MB_OK | MB_ICONERROR);
                    }
    
                    launcher_->set_text(L"启动复制");
                    launcher_->enable();
                });
    
                copier.detach();
            });
        }
    
    private:
        std::unique_ptr<controls::xxedit>        input_;
        std::unique_ptr<controls::xxedit>        output_;
        std::unique_ptr<controls::xxedit>        time_used_;
        std::unique_ptr<controls::xxedit>        cachesize_;
        std::unique_ptr<controls::xxbutton>      launcher_;
    
        std::unique_ptr<controls::xxprogressbar> progress_;
        u_long                                   time_used_seconds_;
    
        wchar_t                                  message_[256];
    };
    
    
    purelibGUIEntry
    {
        // enable_leak_check();
    
        extremely_copier copier;
    
        copier.update();
        copier.show();
    
        copier.message_loop();
    
        return 0;
    }
    
    


    extremely_copier可执行文件: http://pan.baidu.com/s/1hqEfBDU
    
    
    
    展开全文
  • 一般每个杀毒软件里都会有一个设置,就是在访问和更改 [创建、... 2、把虚拟内存设置大一些看看3、以前复制很快吗?如果以前很快,参照以下办法。右键“我的电脑”-“管理”-“设备管理器”,点开“IDE ATA/ATAPI...

    一般每个杀毒软件里都会有一个设置,就是在访问和更改 [创建、打开、移动、复制、运行…] 的时候会扫描文件,这个时候就会卡。
    象诺顿、卡巴、nod32,甚至国内的瑞星之流都有。
    把这个设置取消就可以啦!
    一般还有一个选项,就是类似创建时扫描之类的。 2、把虚拟内存设置大一些看看3、以前复制很快吗?如果以前很快,参照以下办法。右键“我的电脑”-“管理”-“设备管理器”,点开“IDE ATA/ATAPI控制器”,双击那些主要IDE通道和次要IDE通道,高级设置,看当前传送模式是否为“仅PIO”,如果是,那数据传递速度会非常慢的。
    ●如果硬盘出现PIO传输模式的话,还可以通过以下步骤来解决:第一步:正确安装主板驱动 由于IDE传输模式是受主板芯片所控制的,所以主板驱动安装错误等问题会出现硬盘无法切换到DMA模式的情况。因此用户需要经常主板驱动程序。另外还可以在“设备管理器”—“IDE ATA/ATAPI 控制器”中,右键“主要IDE通道”、“次要IDE通道”选择“卸载”,重启电脑后由系统重新安装驱动。若PIO模式是由驱动引起的,一般都能就此得到解决。 用户在选择驱动程序的时候,最好不要选用最新的测试版驱动,可能存在一定的危险。第二步:禁止“休眠”功能,避免系统自动切换成PIO传输模式
    ●可将“休眠”功能关闭,避免自动切换到PIO传输模式。 由于Windows IDE/ATAPI 端口驱动程序的工作问题,会导致系统在“休眠”状态被唤起后,产生硬盘超时或循环冗余检验错误,最终致使系统错误地把设备传输模式强行切换到PIO状态。为此,可在系统中取消“休眠”功能。具体步骤为:在“控制面板”—“电源管理”—“休眠”中,将“启用休眠”前面的勾去掉即可。

    展开全文
  • 为了实现面向对象编程,对于的复杂型结构快速构造与...对象构造采用原始构造,非动态申请和复制构造,提高速度。 加锁,实现多线程支持。 通过giveUpOne方法放弃对象使用权,不需要释放对象,实现高度对象复用。 ...
    为了实现面向对象编程,对于的复杂型结构快速构造与释放,写了个内存池管理模板。他特点是允许用户放弃内存池生成对象使用权,而不是执行析构。实现对象的复用。
    1. 实现同类型对象的全局化管理。无需显示构造内存池。采用newOne宏申请对象。
    2. 内存块的大小可调。内存池状态可输出显示。
    3. 采用内存预分配方式。对象构造采用原始构造,非动态申请和复制构造,提高速度。
    4. 加锁,实现多线程支持。(加锁会额外耗费cpu时间,可设置宏CLMP_USE_LOCK_TYPE ,决定采用哪种方案)
    #define CLMP_USE_LOCK_TYPE 0 // 0=无锁(快),1=用C++锁(慢),2=用windows临界区锁
    
    1. 通过giveUpOne()方法,放弃对象使用权,不需要释放对象,实现快速对象复用。

    演示代码:应用案例: 【C++高速矩阵类实现】.

    //定义任意类型,其构造含有动态内存的申请。
    struct MyStruct
    {
    	int * c;
    	string name;
    	MyStruct(const char* lpName = "" )
    		:c(new int[100]) , name(lpName)
    	{	
    		cout << "\nMyStruct 构造!: " << name << endl;
    	}
    	~MyStruct() {
    		delete[] c;
    		cout << "\nMyStruct 析构!  " << name << endl;
    	}
    };
    
    
    int main() {
    
    	auto p1 = newOne(MyStruct,"p1"); //申请一个对象,命名未p1
    
    	giveUpOne(p1); //放弃使用权,不执行对象析构
    
    	auto p2 = newOne(MyStruct,"p2"); //申请第二个对象,命名未p2
    
    	if (p1 == p2) //由于giveUpOne调用,前后两次newOne产生复用
    		cout << "\np2 获得了复用对象: " << p2->name << endl; 
    
    	auto p3 = newOne(MyStruct, "p3"); //再申请一个对象
    	
    	// ...
    	//使用完成后释放对象,归还到内存池
    	deleteOne(p1); // 注意:此处应该避免继续使用p1,因为他意见显示放弃了使用权。
    	deleteOne(p2); // 因为p2与p1保存同一个对象指针,不会重复释放。
    	deleteOne(p3);
    
    	getchar();
    	return 1;
    

    运行结果:
    在这里插入图片描述
    模板库头源码:
    CLMemPool.h

    //DESIGNED BY CAILUO @2020-02-10 
    //MINI-SUPPORT @ C++14
    
    #pragma once
    
    #ifndef __CL_MEMPOOL_H__
    #define __CL_MEMPOOL_H__
    
    #include <cassert>
    #include <map>
    #include <string>
    #include <stdexcept>
    
    #define CLMP_USE_LOCK_TYPE 0 // 0=无锁(快),1=用C++锁(慢),2=用windows临界区锁
    
    #if CLMP_USE_LOCK_TYPE == 2
    #include "windows.h" //windows平台,临界区
    class CLLock {
    private:
    	CRITICAL_SECTION cs;
    public:
    	CLLock() { InitializeCriticalSection(&cs); }
    	~CLLock() { DeleteCriticalSection(&cs); }
    	void lock() { EnterCriticalSection(&cs); }
    	void unlock() { LeaveCriticalSection(&cs); }
    };
    #elif CLMP_USE_LOCK_TYPE == 1
    #include <mutex> // C++ STL mutex
    class CLLock {
    private:
    	std::mutex mt;
    public:
    	void lock() { mt.lock(); }
    	void unlock() { mt.unlock(); }
    };
    #else
    class CLLock {  //no use lock, it do nothing
    public:
    	void lock() {} 
    	void unlock() {} 
    };
    #endif
    
    #ifndef _CL_DIFVARS_SUPPORT_
    #define _CL_DIFVARS_SUPPORT_
    #ifdef UNICODE
    typedef wchar_t Char;
    #define tstring wstring
    #ifndef _T
    #define _T(x)  L ## x
    #endif
    #ifndef _tprintf_s
    #define _tprintf_s wprintf_s
    #define _stprintf_s swprintf_s
    #define _tcscpy_s wcscpy_s
    #endif
    #else
    typedef char Char;
    #define tstring string
    #ifndef _T
    #define _T(x)  x
    #endif
    #ifndef _tprintf_s
    #define _tprintf_s printf_s
    #define _stprintf_s sprintf_s
    #define _tcscpy_s strcpy_s
    #endif
    #endif
    typedef const Char* PCStr;
    typedef Char* PStr;
    #ifndef BUFSIZE
    #define BUFSIZE 256
    #endif
    #ifndef max
    #define max(a,b) ((a) < (b) ? (b) : (a))
    #define min(a,b) ((a) < (b) ? (a) : (b))
    #endif
    #endif
    
    template <typename classTag>
    class CLMemPoolBlock;
    
    template <typename classTag>
    class CLMemPool;
    
    内存池表类型
    class MemPoolsTable
    	:public std::map< CLMemPool<void*>*, std::tstring>,
    	public CLLock
    {};
    //取得内存池表
    inline MemPoolsTable* getMemPoolsTable() {
    	static MemPoolsTable _mplst;
    	return &_mplst;
    }
    增加内存池到内存池表
    inline void addMemPoolToTable(PCStr name, CLMemPool<void*>* pMemPool)
    {
    	getMemPoolsTable()->lock();
    	(*getMemPoolsTable())[pMemPool] = (name == nullptr ? _T("") : name);
    	getMemPoolsTable()->unlock();
    }
    
    //内存池对象单元模板类
    template <typename classTag>
    class CLMemPoolUnit {
    	friend class CLMemPool<classTag>;
    	friend class CLMemPoolBlock<classTag>;
    public:
    	struct DataHead {
    		CLMemPoolUnit<classTag>* pPre;
    		CLMemPoolUnit<classTag>* pNext;
    		CLMemPoolBlock<classTag>* pThisBlock;
    		bool bIsCreate;
    		bool bIsUsed;
    	};
    private:
    	DataHead hdr;
    	classTag data;//包裹数据对象
    
    	//在构造时候显示调用
    	CLMemPoolUnit<classTag>* init(
    		CLMemPoolBlock<classTag>* _pThisBlock = 0,
    		CLMemPoolUnit<classTag>* _pPre = 0,
    		CLMemPoolUnit<classTag>* _pNext = 0,
    		bool _isCreate = false,
    		bool _isUsed = false
    	) { 
    		hdr.pThisBlock = _pThisBlock;
    		hdr.pPre = _pPre;
    		hdr.pNext = _pNext;
    		hdr.bIsCreate = _isCreate;
    		hdr.bIsUsed = _isUsed;
    		return this; 
    	}
    	//注意:构造和析构函数用于显示的调用来构造和析构内部包裹对象
    	//他们不应该被系统调用,且内部不能有任何的数据处理过程;
    	CLMemPoolUnit(){}
    	template <typename... Args>
    	CLMemPoolUnit(Args&&... args):data(std::forward<Args>(args)...){}
    	~CLMemPoolUnit() {}
    public:
    	inline CLMemPoolBlock<classTag>* getOwnerBlock() {return hdr.pThisBlock;}
    };
    
    #define MUHEARDER( classTag, pData )  ((CLMemPoolUnit<classTag>*)(((char*)(pData))-(sizeof(CLMemPoolUnit<classTag>::DataHead))))
    
    //内存池内存块对象模板类
    template <typename classTag>
    class CLMemPoolBlock {
    	friend class CLMemPool<classTag>;
    	friend class CLMemPoolUnit<classTag>;
    private:
    	explicit CLMemPoolBlock(size_t PerBlockMemCapacity_MB , CLMemPool<classTag>* _pOwnerMemPool)
    	:pOwnerMemPool(_pOwnerMemPool)
    	{
    		init();
    		alloc(PerBlockMemCapacity_MB * 1024 * 1024 / sizeof(CLMemPoolUnit<classTag>));
    	}
    	virtual ~CLMemPoolBlock() {
    		releaseObjMenBlock();
    	}
    	//判断该内存块是否存在可用单元
    	inline bool isUsable() {
    		return pUsableLst ? true : false;
    	}
    	//将对象指针回收进入内存块单元,如果对象是已经构造过的就调用标准析构。
    	CLMemPoolUnit<classTag>* freeOneData(CLMemPoolUnit<classTag>* pUnit) {
    		assert(pUnit !=nullptr);
    		//执行对象析构
    		if (pUnit->hdr.bIsCreate) {
    			pUnit->CLMemPoolUnit<classTag>::~CLMemPoolUnit();
    			pUnit->hdr.bIsCreate = false;
    			nHasCreatedCounts--;
    		}
    		return putToUsable(pUnit);
    	}
    	//将对象指针回收进入内存块单元,而不调用析构
    	CLMemPoolUnit<classTag>* giveUpOneData(CLMemPoolUnit<classTag>* pUnit) {
    		assert(pUnit != nullptr);
    		//不执行对象析构,直接放入未用连条
    		return putToUsable(pUnit);
    	}
    	//取出一个待命可用的对象单元,返回其构造后的对象指针。注意:若申请时的当前分配对象已构造,则忽略构造传参。
    	template <typename... Args>
    	classTag* getOneData(Args&&... args) {
    		assert(pUsableLst != nullptr);
    		if(!pUsableLst->hdr.bIsCreate) {
    			//执行对象默认构造,这会构造内部包裹的数据类
    			pUsableLst->CLMemPoolUnit<classTag>::CLMemPoolUnit(std::forward<Args>(args)...);
    			pUsableLst->hdr.bIsCreate = true;
    			nHasCreatedCounts++;
    		}
    		return putToUnusable(pUsableLst);
    	}
    	inline void init() {
    		pUsableLst = 0;
    		nMaxUsable = 0;
    		pUnusableLst = 0;
    		nMaxUnusable = 0;
    		nHasCreatedCounts = 0;
    		pPre = 0;
    		pNext = 0;
    		pMainDataLst = 0;
    		nMaxDataCounts = 0;
    	}
    	//分配内存
    	void alloc(size_t unitCounts = 1) {
    		assert(pMainDataLst == 0 && pUsableLst == 0 && pUnusableLst == 0);
    		if (pMainDataLst == 0) {
    			//第一次申请内存空间
    			pMainDataLst = (CLMemPoolUnit<classTag> *)malloc(sizeof(CLMemPoolUnit<classTag>)*(nMaxDataCounts = nMaxUsable = (unitCounts == 0 ? 1 : unitCounts)));
    			//第一次执行可用队列的初始化连接工作
    			pUsableLst = &pMainDataLst[0];
    			pMainDataLst[0].init(this, 0, nMaxDataCounts <= 1 ? 0 : &pMainDataLst[1]);
    			for (size_t i = 1; i < nMaxDataCounts-1; ++i) {
    				pMainDataLst[i].init(this, &pMainDataLst[i-1], &pMainDataLst[i + 1]);
    			}
    			pMainDataLst[nMaxDataCounts - 1].init(this, nMaxDataCounts <= 1 ? 0 : &pMainDataLst[nMaxDataCounts - 2], 0);
    		}
    	};
    	//析构所有已经构造过的对象,但没有使用的对象。
    	void distructCreatedUsable() {
    		if (nHasCreatedCounts == 0)
    			return;
    		//析构所有在可用连中的已构造
    		for (CLMemPoolUnit<classTag>* pc = pUsableLst; pc != nullptr; ) {
    			if (pc->hdr.bIsCreate) {
    				pc->CLMemPoolUnit<classTag>::~CLMemPoolUnit();
    				pc->hdr.bIsCreate = false;
    				nHasCreatedCounts--;
    			}
    			pc = pc->hdr.pNext;
    		}
    	}
    	//释放内存
    	void releaseObjMenBlock() {
    		if (pMainDataLst) {
    			//析构所有已使用的对象
    			for (CLMemPoolUnit<classTag>* pc = pUnusableLst; pc != nullptr; ) {			
    				pUnusableLst = freeOneData(pc);
    				pc->init();
    				pc = pUnusableLst;
    			}
    			//释放动态内存
    			free(pMainDataLst);
    			pMainDataLst = 0;
    		}		
    	}
    	//处理前后连接,隔离对象,返回原对象指针
    #define _extruct_pUnitBlock(pUnit) \
    		((((pUnit)->pPre) ? ((pUnit)->pPre->pNext = (pUnit)->pNext) : 0),(((pUnit)->pNext)?((pUnit)->pNext->pPre = (pUnit)->pPre):0),(pUnit))
    #define _extruct_pUnit(pUnit) \
    		((((pUnit)->hdr.pPre) ? ((pUnit)->hdr.pPre->hdr.pNext = (pUnit)->hdr.pNext) : 0),(((pUnit)->hdr.pNext)?((pUnit)->hdr.pNext->hdr.pPre = (pUnit)->hdr.pPre):0),(pUnit))
    	//对象放入可用队列头,返回不可用队列头指针
    	CLMemPoolUnit<classTag>*  putToUsable(CLMemPoolUnit<classTag>* pUnit) {
    		assert(this == pUnit->hdr.pThisBlock);
    		pUnit->hdr.bIsUsed = false;
    		//处理不可用列表头
    		if (pUnusableLst && pUnusableLst == pUnit)
    			pUnusableLst = pUnit->hdr.pNext;
    
    		//处理前后连接,隔离对象
    		_extruct_pUnit(pUnit);
    
    		//接入可用列表
    		if (pUsableLst) {pUsableLst->hdr.pPre = pUnit;}
    		pUnit->hdr.pNext = pUsableLst;
    		pUnit->hdr.pPre = 0;
    		pUsableLst = pUnit;
    		nMaxUnusable -= 1;
    		nMaxUsable += 1;
    		return pUnusableLst;
    	}
    
    	//返回可用对象指针
    	classTag*  putToUnusable(CLMemPoolUnit<classTag>* pUnit) {
    		assert(this == pUnit->hdr.pThisBlock);
    		pUnit->hdr.bIsUsed = true;
    		//处理可用列表头
    		if (pUsableLst && pUsableLst == pUnit)
    			pUsableLst = pUnit->hdr.pNext;
    
    		//处理前后连接,隔离对象
    		_extruct_pUnit(pUnit);
    		
    		//接入不可用列表
    		if (pUnusableLst) {	pUnusableLst->hdr.pPre = pUnit;}
    		pUnit->hdr.pNext = pUnusableLst;
    		pUnit->hdr.pPre = 0;
    		pUnusableLst = pUnit;
    		nMaxUnusable += 1;
    		nMaxUsable -= 1;
    		return &pUnit->data;
    	}
    	CLMemPool<classTag>* const pOwnerMemPool; //所属内存池
    	CLMemPoolUnit<classTag>* pMainDataLst;//内存队列
    	size_t nMaxDataCounts;
    	CLMemPoolUnit<classTag>* pUsableLst;//可用列表
    	size_t nMaxUsable;
    	CLMemPoolUnit<classTag>* pUnusableLst;//不可用列表
    	size_t nMaxUnusable;
    	size_t nHasCreatedCounts;
    	CLMemPoolBlock<classTag>* pPre;
    	CLMemPoolBlock<classTag>* pNext;
    public:
    	inline CLMemPool<classTag>* getOwnerMemPool() {	return pOwnerMemPool;}
    };
    
    //标准化接口
    class IMenPool{
    public:
    	virtual void arrangement(bool) = 0;
    	virtual void deallocateOne(void*) = 0;
    	virtual void giveUpOne(void*) = 0;
    };
    
    //内存池对象模板类。
     //请使用静态的getMemPool()方法获取唯一的内存池对象。
    template <typename classTag> 
    class CLMemPool :public IMenPool,public CLLock {
    	friend class CLMemPoolBlock<classTag>; 
    	friend class CLMemPoolUnit<classTag>;
    private:
    	//构造带名称标识的目标类型内存池,加入内存池表。请勿显示调用该构造方法。
    	//请使用静态的getMemPool()方法获取唯一的内存池对象。
    	CLMemPool(PCStr _lpTypeName, size_t PerBlockMemCapacity_MB = 5) :
    		pEntry(nullptr),
    		pCurrentUsingBlock(nullptr)
    	{
    		setPerBlockMemCapacity(PerBlockMemCapacity_MB);
    		setMemPoolTypeName(_lpTypeName);
    	}
    	//构造目标类型内存池,加入内存池表。请勿显示调用该构造方法。
    	//请使用静态的getMemPool()方法获取唯一的内存池对象。	
    	CLMemPool(size_t PerBlockMemCapacity_MB = 5) :
    		pEntry(nullptr),
    		pCurrentUsingBlock(nullptr)
    	{
    		setPerBlockMemCapacity(PerBlockMemCapacity_MB);
    		setMemPoolTypeName(nullptr);
    	}
    public:
    	PCStr lpTypeName;	
    	virtual ~CLMemPool() {
    		//不要释放任何内存,而是做一次整理
    		arrangement();
    		getMemPoolsTable()->lock();
    		for (auto  i = ::getMemPoolsTable()->find((CLMemPool<void*>*)this); 
    			i != ::getMemPoolsTable()->end(); ){
    			::getMemPoolsTable()->erase(i);
    			break;
    		} 
    		getMemPoolsTable()->unlock();
    	}
    	void setMemPoolTypeName(PCStr _lpTypeName) {
    		lpTypeName = _lpTypeName ;
    		::addMemPoolToTable(lpTypeName, (CLMemPool<void*>*)this);//构造之后加入队列
    	}
    	//整理内存,释放当前没有使用的空间归还系统。该函数用于内存池反复使用后占用较大资源后做一次统一释放。
    	//distructCreatedButNoUsed = true 表示析构未被使用但已构造的对象
    	virtual void arrangement(bool distructCreatedButNoUsed = true) {
    		lock();
    		pCurrentUsingBlock = nullptr;	//	置0
    		for (CLMemPoolBlock<classTag>* pi = pEntry; pi != nullptr; )
    		{
    			CLMemPoolBlock<classTag>* pib = pi->pNext;
    			if (distructCreatedButNoUsed)//是否析构未用对象
    				pi->distructCreatedUsable();
    			if (pi->nMaxUnusable == 0 && pi->nHasCreatedCounts == 0) { //释放条件,没有被使用,没有已构造
    				if (pEntry == pi)
    					pEntry = pi->pNext;
    				delete _extruct_pUnitBlock(pi);
    			}
    			pi = pib;
    		}
    		unlock();
    	}
    	//强行释放所有内存。
    	virtual void releaseObjMenPool() {
    		lock();
    		for (CLMemPoolBlock<classTag>* pi = pEntry; pi != nullptr; )
    		{
    			pCurrentUsingBlock = pi->pNext;
    			delete pi; // 释放块
    			pi = pCurrentUsingBlock;
    		}
    		m_PerBlockMemCapacity = 0;
    		pEntry = 0;
    		pCurrentUsingBlock = 0;
    		unlock();
    	}
    	//向内存池储备内存动态申请一个对象,若对象是已经构造过,就返回指针,如果未构造,先构造并返回其对象指针。
    	//该方法接受可变参数构造方式传参。
    	//注意:若申请时的当前分配对象已构造过(比如:是由giveUpOne()放弃使用权而回收的对象),则忽略本次构造传参。
    	template <typename... Args>
    	classTag* allocateOne(Args&&... args) {
    		lock();		
    		classTag* rt = getAvailableBlock()->getOneData(std::forward<Args>(args)...);
    		unlock();
    		return rt;
    	}
    	//向内存池释放一个动态申请的对象,进行相关析构操作。
    	virtual void deallocateOne(void* pDelete) {
    		CLMemPoolUnit<classTag>* pUnit = MUHEARDER(classTag,pDelete);
    		if(!checkPtrValidity(pUnit))return;//指针非法即返回或抛异常
    		lock();
    		pUnit->hdr.pThisBlock->freeOneData(pUnit);
    		unlock();
    	}
    	//向内存池释放一个动态申请的对象,不析构。
    	virtual void giveUpOne(void* pDelete) {
    		CLMemPoolUnit<classTag>* pUnit = MUHEARDER(classTag, pDelete);
    		if (!checkPtrValidity(pUnit))return;//指针非法即返回或抛异常
    		lock();
    		pUnit->hdr.pThisBlock->giveUpOneData(pUnit);
    		unlock();
    	}
    	//判断指针是否属于本内存池构造
    	bool checkPtrValidity(CLMemPoolUnit<classTag>* pUnit){
    		if(pUnit->hdr.pThisBlock->pOwnerMemPool != this)
    			throw std::runtime_error("Tag obj is not created by this mem pool!");
    		//if(pUnit < pUnit->hdr.pThisBlock->pMainDataLst || pUnit > pUnit->hdr.pThisBlock->pMainDataLst + pUnit->hdr.pThisBlock->nMaxDataCounts - 1)
    		//	throw std::runtime_error("Tag obj is not created by this mem pool!");
    		if (!pUnit->hdr.bIsUsed) {			
    #ifdef _DEBUG
    			if(pUnit->hdr.bIsCreate)
    				throw std::runtime_error("Tag obj has been give up!");
    			else
    				throw std::runtime_error("Tag obj has been distructed!");
    #else
    			return false;
    #endif
    		}
    		return true;
    	}
    	//设置单个内存块的大小,单位MB,默认5MB
    	virtual void setPerBlockMemCapacity(size_t PerBlockMemCapacity_MB = 5) {
    		lock();
    		m_PerBlockMemCapacity = PerBlockMemCapacity_MB == 0 ? 1 : PerBlockMemCapacity_MB;
    		unlock();
    	}
    	//统计内存使用量,并控制向控台输出当前内存池的内存使用情况。
    	//bLog = true表示输出信息到控制台否则只统计内存使用量,bDeTail = false表示采用简化输出,outInfoString动态信息字符串内容需要手动释放
    	virtual size_t dumpInfo(bool bLog = true, bool bDeTail = false,PStr* outInfoString = nullptr) {
    		std::tstring strAll;
    #define dumpInfoMax 1000
    		Char tem[dumpInfoMax];
    		if (bLog || outInfoString) {
    			if (bDeTail)
    				_stprintf_s(tem, dumpInfoMax,_T("\r\n>>The MemmeryPool(=%s) Dumper Detail----------------------------------- \r\n>>MemBlock Info:\r\n"),(lpTypeName ? lpTypeName:_T("#UnkownTypeName")));
    			else
    				_stprintf_s(tem, dumpInfoMax,_T("\r\n>>The MemmeryPool(=%s) Dumper Simple----------------------------------- \r\n"), (lpTypeName ? lpTypeName : _T("#UnkownTypeName")));
    			strAll += tem;
    		}
    		size_t si = 0;
    		size_t siu = 0;
    		size_t sit = 0;
    		lock();
    		for (const CLMemPoolBlock<classTag>* pc = pEntry; pc; )
    		{
    			si++;
    			siu += pc->nMaxUnusable;
    			sit += pc->nMaxDataCounts;
    			size_t n = pc->nMaxDataCounts == 0 ? 0 : (pc->nMaxUnusable * 50) / pc->nMaxDataCounts;
    			if ((bLog || outInfoString) && bDeTail) {
    				_stprintf_s(tem, dumpInfoMax,_T(">>MemBlock(%zd): ["), si); strAll += tem;
    				for (size_t i = 0; i < 50; ++i)
    				{
    					if (i < n)_stprintf_s(tem, dumpInfoMax,_T("*"));
    					else _stprintf_s(tem, dumpInfoMax,_T("-"));
    					strAll += tem;
    				}
    				_stprintf_s(tem, dumpInfoMax,_T("] <used=%zd%%>\r\n"), n * 2);
    				strAll += tem;
    			}
    			pc = pc->pNext;
    		}
    		unlock();
    		size_t perObj = sizeof(CLMemPoolUnit<classTag>);
    		size_t mem = perObj*sit + si*sizeof(CLMemPoolBlock<classTag>);
    		if (bLog || outInfoString) {
    			size_t Tb = 0, Gb = 0, Mb = 0, Kb = 0, Byte = 0;
    			Kb = mem / 1024; Byte = mem % 1024;
    			Mb = Kb / 1024; Kb = Kb % 1024;
    			Gb = Mb / 1024; Mb = Mb % 1024;
    			Tb = Gb / 1024; Gb = Gb % 1024;
    			if (Tb > 0)
    				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdT %zdG %zdM %zdK %zdB, blocks=%zd, total=%zd, used=%zd.\r\n\r\n"), Tb, Gb, Mb, Kb, Byte,  si, sit, siu);
    			else if (Gb > 0)
    				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdG %zdM %zdK %zdB, blocks=%zd, total=%zd, used=%zd.\r\n\r\n"), Gb, Mb, Kb, Byte,  si, sit, siu);
    			else if (Mb > 0)
    				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdM %zdK %zdB, blocks=%zd, total=%zd, used=%zd.\r\n\r\n"), Mb, Kb, Byte,  si, sit, siu);
    			else if (Kb > 0)
    				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdK %zdB, blocks=%zd ,total=%zd, used=%zd.\r\n\r\n"), Kb, Byte,  si, sit, siu);
    			else
    				_stprintf_s(tem, dumpInfoMax,_T(">>Summary: mem= %zdB, blocks=%zd, total=%zd, used=%zd.\r\n\r\n"), Byte,  si, sit, siu);
    			strAll += tem;
    		}
    		if (bLog)
    			_tprintf_s(_T("%s"),strAll.c_str());
    		if (outInfoString) {
    			size_t nn = strAll.length() + 1;
    			*outInfoString = new Char[nn];
    			_tcscpy_s(*outInfoString, nn, strAll.c_str());
    		}
    		return mem;
    	}
    	//返回内存使用量bytes
    	size_t getMemSize() const { return dumpInfo(false, false, nullptr); }
    private:
    	CLMemPoolBlock<classTag>* pEntry;
    	CLMemPoolBlock<classTag>* pCurrentUsingBlock;
    	size_t m_PerBlockMemCapacity;
    
    	//检索列表取得可用的块,没有就创建
    	CLMemPoolBlock<classTag>* getAvailableBlock() {
    		if (pCurrentUsingBlock == nullptr) {
    			if (pEntry == nullptr) {
    				pCurrentUsingBlock = pEntry = new CLMemPoolBlock<classTag>(m_PerBlockMemCapacity, this);
    			}
    			else pCurrentUsingBlock = pEntry;
    		}
    		CLMemPoolBlock<classTag>* pStartBlock = pCurrentUsingBlock;
    		//检索可用的块
    		for (; pCurrentUsingBlock->isUsable() == false;)
    		{
    			if (pCurrentUsingBlock->pNext == nullptr) {
    				if (pCurrentUsingBlock != pEntry) {
    					pCurrentUsingBlock = pEntry;
    				}
    				else {
    					pStartBlock = new CLMemPoolBlock<classTag>(m_PerBlockMemCapacity, this);
    					if (pEntry->pNext)
    						pEntry->pNext->pPre = pStartBlock;
    					pStartBlock->pNext = pEntry->pNext;
    					pEntry->pNext = pStartBlock;
    					pCurrentUsingBlock = pStartBlock;
    				}
    			}
    			else if (pCurrentUsingBlock->pNext == pStartBlock) {//插入新块,在队列中
    				pStartBlock = new CLMemPoolBlock<classTag>(m_PerBlockMemCapacity, this);
    				if (pCurrentUsingBlock->pNext)
    					pCurrentUsingBlock->pNext->pPre = pStartBlock;
    				pStartBlock->pNext = pCurrentUsingBlock->pNext;
    				pCurrentUsingBlock->pNext = pStartBlock;
    				pCurrentUsingBlock = pStartBlock;
    			}
    			else pCurrentUsingBlock = pCurrentUsingBlock->pNext;
    		}
    		return pCurrentUsingBlock;
    	}
    public:
    	//取得类型对应的内存池对象
    	static CLMemPool* getMenPool() {
    		static CLMemPool _MenPool;
    		return &_MenPool;
    	}
    	static CLMemPool* getMenPool(PCStr typeName) {
    		CLMemPool* pc = getMenPool();
    		if (pc->lpTypeName == nullptr && typeName != nullptr) {
    			pc->setMemPoolTypeName(typeName);
    		}
    		return pc;
    	}
    	//向内存池动态申请一个对象,返回对象指针。对应的,该指针必须用deleteOne释放。也可用giveUpOne放弃使用权(该方式不执行对象析构)。
    	//注意:若申请时的当前分配对象已构造过(比如:是由giveUpOne()放弃使用权而回收的对象),则忽略本次构造传参。
    	template <typename... Args>
    	static classTag* newOneFromCLMemPool(PCStr name = nullptr, Args&&... args) {
    		return (classTag*)getMenPool(name)->allocateOne(std::forward<Args>(args)...);
    	}	
    	//设置内存池中内存块当个最大内存占用大小,单位MB
    	static void setMemPoolBlockCapacity(size_t mb = 5) {
    		assert(mb != 0);
    		getMenPool()->setPerBlockMemCapacity(mb);
    	}
    };
    
    //将由newOne获得的对象指针释放回内存池,会做相关析构操作。
    inline void deleteOneBackToCLMemPool(void* pDelete) {
    	assert(pDelete != nullptr);
    	MUHEARDER(void*, pDelete)->getOwnerBlock()->getOwnerMemPool()->deallocateOne(pDelete);
    }
    //将由newOne获得的对象指针放弃操作权,归还放回内存池,但是不做析构操作。
    inline void giveUpOneBackToCLMemPool(void* pDelete) {
    	assert(pDelete != nullptr);
    	MUHEARDER(void*, pDelete)->getOwnerBlock()->getOwnerMemPool()->giveUpOne(pDelete);
    }
    
    //目的:构造保存typeName类型的内存池(如果未构造过的话),并返回构造后的对象指针;
    //作用:他向内存池动态申请一个对象(第一个参数是申请的类型,第二个参数可以是可变数量的构造参数),返回对象指针。
    //方法:对应的,该方法返回的指针必须用deleteOne释放,也可用giveUpOne放弃使用权(giveUpOne方式不执行对象析构,只是把对象原样放回内存池)。
    //注意:该内存池采用预分配机制,可以高速的完成读写,但无法分配连续数量的对象(对象队列),只能分配单个对象。
    //注意:若申请时的当前分配对象已构造过(比如:是由giveUpOne()放弃使用权而回收的对象),则忽略本次构造传参。
    #define newOne( typeName , ... ) (CLMemPool<typeName>::newOneFromCLMemPool(_T(#typeName) , __VA_ARGS__ ))
    //生成代标号的内存池和对象指针的宏;并且指定内存池名称(若名称未被指定过的话)
    #define newOneAndNamed( typeName, NameString , ... ) (CLMemPool<typeName>::newOneFromCLMemPool(_T(#NameString), __VA_ARGS__ ))
    //删除对象,typeName是类型名,pObjToDelete是释放的对象指针
    #define deleteOne( pObjToDelete ) (deleteOneBackToCLMemPool((pObjToDelete)))
    //放弃对象使用权(不会析构对象),并放回内存池待用,typeName是类型名,pObjToDelete是释放的对象指针
    #define giveUpOne( pObjToDelete ) (giveUpOneBackToCLMemPool((pObjToDelete)))
    
    //整理所有内存池
    inline void arrangeAllMemPools()
    {
    	getMemPoolsTable()->lock();
    	for (auto& i : *getMemPoolsTable())
    		i.first->arrangement();
    	getMemPoolsTable()->unlock();
    }
    //输出内存池表所有对象
    inline size_t dumpMemPoolsTable(bool bLog = true, bool bDeTail = false,  PStr* outInfoString = nullptr)
    {
    	size_t mem = 0;
    	PStr lpT = 0;
    	std::tstring str, strh;
    	if (bLog || outInfoString) {
    		if (bDeTail)strh = _T("\r\n>>>>The MemmeryPool Table Dumper Detail----------------------------------- \r\n");
    		else strh = _T("\r\n>>>>The MemmeryPool Table Dumper Simple----------------------------------- \r\n");
    	}
    	size_t ic = 1;
    	Char cts[BUFSIZE];
    	getMemPoolsTable()->lock();
    	for (auto i = getMemPoolsTable()->cbegin(); i != getMemPoolsTable()->cend(); ic++)
    	{
    		size_t memc = (i->first->dumpInfo(false, bDeTail, ((bLog || outInfoString) ? &lpT : nullptr)));
    		mem += memc;
    		if (bLog || outInfoString) {
    			if (i->first->lpTypeName)_stprintf_s(cts, _T("<MemPool(%zd)>, mem= %zd Bytes, type= %s \r\n"), ic, memc, i->second.c_str());
    			else _stprintf_s(cts, _T("<MemPool(%zd)>, mem= %zd Bytes, %s \r\n"), ic, memc, _T("#UnkownTypeName"));
    			strh += cts;
    		}
    		if (bLog || outInfoString) {
    			if (lpT) {
    				str += lpT;
    				delete[] lpT;
    				lpT = 0;
    			}
    		}
    		++i;
    	}
    	if (bLog || outInfoString) {
    		_stprintf_s(cts, _T(">>>>Total Mem = %zd Bytes \r\n\r\n>>>>Per MemmeryPool Information: \r\n"), mem);
    		strh += cts;
    		strh += str;
    	}
    	if (bLog)
    		_tprintf_s(_T("%s"), strh.c_str());
    	getMemPoolsTable()->unlock();
    	if (outInfoString) {
    		*outInfoString = new Char[strh.length() + 1];
    		_tcscpy_s(*outInfoString, strh.length() + 1, strh.c_str());
    	}
    	return mem;
    }
    
    #endif
    
    展开全文
  • 测试工具:sysbench测试服务器:DL380G7 2台master-slave模式内存大小:主机内存32G ,INNODB POOL SIZE 20G硬盘:2块普通的HDD盘CPU:12物理coreraid卡写cache开启mysql版本:5.6.19测试结论:1)MYSQL半同步复制可以...
  •  去年下半年开始,往服务器上传或下载大批量文件时出现了Ubuntu系统(常用)下复制速度慢的情况,具体情况看图: 系统配置: Ubuntu12.04, 3.+Ghz 8核CPU 64G内存, 2T主硬盘,整个阵列约...
  • 屡屡遇到这东西,很头疼,主要是没有现成的脱壳程序,需要手动脱壳,虽说难度不大,但它更新的速度挺快,一直在变化,总是给人一种追着才能赶上的感觉,真是不爽。话说来,不知国内是真没有大牛,还是大牛都藏着掖着...
  • 先申明复制速度结果 System.arraycopy() clone() Arrays.copyof() for() 背后原理探究 首先要申明的是这4种方法中的前3种是没有本质区别的,对象都是浅复制(复制地址),而普通类型都是深复制(复制值),简单来说...
  • 内存

    2019-08-19 20:13:35
    读写速度内存 > 固态硬盘 > 机械硬盘 ...安装的软件保存在硬盘中,运行软件时先将硬盘上的数据复制内存,才能让 CPU 来处理,这个过程叫作载入内存(Load into Memory)。完成这个过程需要一个...
  • 内存与虚拟内存

    2019-02-26 12:46:07
    内存是软件的运行的关键,运行一款软件实际是将存储在硬盘中的软件复制内存中,内存的高速处理速度才能使软件有效运行。 对于读写速度内存 &gt; 固态硬盘 &gt; 机械硬盘。机械硬盘是靠电机带动盘片转动...
  • 下面是内存虚拟文件系统的一些常规操作,包括新建文件系统、新建或删除文件、复制文件(包括在虚拟文件系统和真实文件系统之间复制)、创建目录和子目录等。 // 创建一个内存文件系统对象 fs = gith
  • 要试着运行这些示例,需要先复制本代码清单,并将其粘贴到一个名为 malloc.c 的文件中。接下来,我将一次一个部分地对该清单进行解释。 在大部分操作系统中,内存分配由以下两个简单的函数来处理: void *...
  • 提升复制速度(io效率),堆外内存的数据可直接由操作系统写入磁盘。 堆内内存由JVM管理,属于“用户态”; 堆外内存由OS管理,属于“内核态”。 如果从堆内向磁盘写数据时,数据会先被复制到堆外内存,即内核缓冲...
  • FastImageCache是Path团队开发的一个开源库,用于提升图片的加载和渲染速度,让基于图片的列表滑动起来更顺畅,来看看它是怎么做的。优化点iOS从磁盘加载一张图片,使用UIImageVIew显示在屏幕上,需要经过以下步骤:...
  • 首先学习JVM相关需要需要内存的组成。  基本内容  · 堆  java动态创建对象,即对于new的一个实例对象。但是需要注意的是该实例对象的成员变量都存储在各自的堆区域中,其中对象方法是在堆中共享,即不是每次...
  • 内存文件映射

    2019-05-20 09:48:10
    磁盘速度慢,尽量把更多的数据弄到内存去。 内存 内存速度快。不过,内存分两块: 1.操作系统内存 2.用户程序内存 缓冲区 也分两块: 1.操作系统缓冲区内存 2.用户程序进程缓冲区内存 首先,缓冲区都是内存...
  • Java内存模型及volatile

    2019-08-05 00:16:31
    大家都知道,计算机在执行程序时,每条指令都是在CPU中执行的,而执行指令过程中,势必涉及到数据的读取和写入。这时就存在一个问题,由于CPU...也就是说,当程序在运行过程中,会将运算需要的数据从主内存复制一份...
  • 电脑内存(RAM)是程序运行的地方,当你打开一款软件、游戏时,系统会将硬盘中的必要数据复制内存中,CPU 再从内存中获取数据,因为内存速度比硬盘要快的多多多。唯一的遗憾是每次内存断电,其中的数据都会被清空...
  • 电脑内存(RAM)是程序运行的地方,当你打开一款软件、游戏时,系统会将硬盘中的必要数据复制内存中,CPU 再从内存中获取数据,因为内存速度比硬盘要快的多多多。唯一的遗憾是每次内存断电,其中的数据都会被清空...
  • Java内存模型

    2020-07-08 02:26:22
    IO,由于计算机的存储设备与CPU的运算速度有几个数量级的差距,所以现代计算机系统都会引入一层读写速度尽可能接近处理器运算速度的高速缓存来作为内存与处理器之间的缓冲:将运算需要使用到的数据复制到缓存中,让...
  • 当数据在可分页内存时,系统可能会移动数据,此时将该数据传输给GPU时,需要将可分页内存复制到一块“临时的”页锁定内存,然后再从页锁定内存复制到GPU 因此使用页锁定内存会一定程度上加快数据在GPU与CPU之间的...
  • java内存模型

    2017-06-13 00:02:00
    所以现代计算机系统都不得不加入一层读写速度尽可能接近处理器运算速度的高速缓存(cache)来作为内存与处理器之间的缓冲:将运算需要使用到的数据从主内存复制到高速缓存中,让运算能快速进行,当运算结束后再从...
  • 缓存和内存的理解

    2020-04-06 12:20:52
    1、因为缓存只是内存中少部分数据的复制品,所以CPU到缓存中寻找数据时,也会出现找不到的情况(因为这些数据没有从内存复制到缓存中去),这时CPU还是会到内存中去找数据,这样系统的速度就慢下来了,不过CPU会把...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,825
精华内容 730
关键字:

内存复制速度