用C ++缓存(对于初学者或多或少)

时间:2015-06-15 19:32:02

标签: c++ performance caching optimization hash

所以我并不是C ++的新手,但是性能优化和缓存的整个概念是。我用C ++(学校)实现了一个Extendible Hashing Class,现在我必须在这里和那里进行优化。

有人可以用简单的语言向我解释一下缓存是什么(以及如何在C ++中实现)......我找到了一些教程,但我几乎一无所知。我读了一些关于静态变量的内容,这些变量记忆并保存在Cache内存中,最后一些方法计算并返回它。功能只会在初始参数发生变化时重新计算(对不起,如果我没有解释那么好:D)。

从我到目前为止我所理解的缓存(我的ExtHash类中的min和max方法),我可以某种方式缓存变量中的min和max值,然后每次添加或删除元素在表格中,我只需要将该元素与缓存的最小值或最大值进行比较,以确定最小值和最大值是否必须更改(我不需要再次遍历整个数组以找到新的最小值和最大)。 我理解正确吗?怎么办?

如果有人花时间解释一下,我真的很感激。

3 个答案:

答案 0 :(得分:1)

让我们说吧。缓存是你暂时存储将来可能需要的东西。

我会举个例子。在这里,你的函数foo具有一些计算功能(无论如何)。

虽然函数foo()可能是一个昂贵的计算函数。

您的客户端代码可能包含:

int a = foo(10);
int b = foo(11);
int c = foo(11);

如果您不知道c与b相同,您将按'foo'计算,这可能很昂贵。

现在让我们将其改为缓存:

int bar(int key)
{
    static int s_key;
    static int s_value;
    if ( key == s_key ) return s_value;

    s_key   = key;
    s_value = foo(key);
    return s_value;
}

现在您不必在foo(11)上复制计算。

但是,这只是一个单项缓存,只能在计算简单重复输入时处理。

如果您正在处理n条目缓存,则需要一些其他算法来管理缓存,例如“LRU”

答案 1 :(得分:0)

术语缓存可以被认为是将经常使用的值或变量存储到可以快速访问的位置。

磁盘驱动缓存数据,用于频繁访问的扇区,以帮助加快访问速度。如果扇区数据没有改变,访问时间将比内存更快,而不是从盘片读取。

许多处理器都有Cache Memory,它位于非常接近处理器的位置。 数据缓存将用于存储频繁访问的数据;因此,处理器不是访问远处的内存(RAM),而是访问已经获取的缓存中的数据。高速缓冲存储器旨在实现非常快速的访问。

程序可以用各种方法实现缓存,具体取决于操作和数据。从硬盘驱动器中读取大量数据到缓冲区是一种缓存形式。组织矩阵和其他结构以适应 Cache Memory 系列是另一种形式的Cache优化。

答案 2 :(得分:0)

当你谈到你的程序缓存时,这通常用于存储事务时间很长的数据,即需要一些时间来获取数据的进程(你正在缓存内容的原因)。一些常见的例子是数据库中的数据读取,磁盘上的文件等。在这些情况下我经常遇到的是数据结构在c ++中使用,如矢量,地图或列表等。我观察到的另一件事是缓存是针对或多或少的静态数据(不会随时更改;如果缓存动态数据,则是愚蠢的)。这些结构的类型取决于您要存储的类型数据。例如,你有一些参考。数据存储在数据库中,您希望将这些数据缓存在程序空间中。

class MyCacheExample
{
public:
    // cctor and destructor
    MyCacheExample(void);
    ~MyCacheExample(void);

    // Caching structures
    std::vector<CString> firstNameVec;
    std::vector<CString>::iterator itr;

    void CacheSomeData()
    {
        // Setup DB related stuff which is required to create session and connect to a DB
        CDatabase dbConn;
        CRecordset rcrdSet(&dbConn);
        CString sDbConnString = L"ODBC;DSN=FOO;UID=abcd;PWD=efgh";

        // query to be fired on the data (in this case the data we want to cache as DB transactions are any day slower than local memory lookup)
        CString sQry = L"select first_name from name_table";

        // Open the DB connection and fire the query
        dbConn.OpenEx(sDbConnString,CDatabase::noOdbcDialog);
        // fire the query and get the result in the CRecordset object
        rcrdSet.Open(CRecordset::snapshot,sQry);

        // Setup the iterator to start caching your data
        itr = firstNameVec.begin();

        // Get data from the result set stored in rcrdSet object
        while(!rcrdSet.IsEOF())
        {
            CString tmp;
            rcrdSet.GetFieldValue(short(1),tmp);
            // insert the data into the vector i.e. "cache" the data for quick look up
            firstNameVec.insert(itr,tmp);
            rcrdSet.MoveNext();
            it++;
        }
        rcrdSet.Close();
        dbConn.Close();
    }
};

int _tmain(int argc, _TCHAR* argv[])
{
    MyCacheExample ex;
    ex.CacheSomeData();
    /* your logic code here about what you want to do with the cached data */
}

忽略数据库的东西(如果你想知道它是基于MFC的数据库连接和数据获取)。 &#34;缓存&#34;这里发生在while循环中。假设有一个名为user_details的表,并且包含first_name,last_name,age等字段。我正在缓存此表中所有人的名字。现在,在while循环完成之后,每次我想要名字时都不必查找数据库,而是可以使用本地结构中缓存的数据(这里是向量)。 使用的结构类型基于您想要的逻辑和缓存数据的性质,例如map和set用于基于密钥val对的数据。 如果你想比较两个读数I.e.缓存和数据库后者需要大约几秒到大约几分钟,具体取决于数据的大小。但前者只需几微秒。

请注意,缓存是一个术语,在这种情况下与计算机(处理器)缓存无关。事实上,这些数据是你所拥有的&#34;缓存&#34;将被取出程序存储器,即RAM。还有一件事你永远不会获取大量的缓存数据。显而易见的原因是你将缺乏RAM(系统中存在100万+用户的用户信息;此类数据会运行到GB)。其次,你的节目空间会膨胀,因此你的节目不再是&#34;光&#34;。

同样,您可以从数据源读取数据,其中读取可能会花费您的时间并影响系统性能,例如磁盘上的文件(使用fstream和string / stringstream) 同时制作静态内容并不意味着您缓存数据。 static是一种定义数据范围的方法,即它是对象级还是类级。 缓存数据可能是静态的,也可能不是静态的,取决于数据的性质和正在使用的逻辑以及在对象引用后是否需要数据。 是的,您可能还需要一些缓存策略,例如LRU LFU FIFO等等(当你想要缓存动态数据以供将来参考时,以及当数据集很大并且必须删除一些缓存值以为新的数据集腾出空间时,可以使用它) 希望这能回答你的问题吗?