高性能缓存 [英] High performance caching

查看:105
本文介绍了高性能缓存的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

下面code应该缓存最后一次读取。该 LastValueCache 是一个可以由多个线程访问(这就是为什么我使用的是共享内存)的高速缓存。这是OK,让我有比赛的条件,但我想,其他线程将看到改变 LastValueCache

The following code is supposed to cache the last read. The LastValueCache is a cache that can be accessed by many threads (this is why I use the shared-memory). It is OK for me to have race conditions but I want that other threads would see the changed LastValueCache.

class Repository
{
    public Item LastValueCache
    {
        get
        {
            Thread.MemoryBarrier();
            SomeType result = field;
            Thread.MemoryBarrier();
            return result;
        }
        set
        {
            Thread.MemoryBarrier();
            field = value;
            Thread.MemoryBarrier();
        }
    }

    public void Save(Item item)
    {
        SaveToDatabase(item);
        Item cached = LastValueCache;
        if (cached == null || item.Stamp > cached.Stamp)
        {
            LastValueCache = item;
        }
    }

    public void Remove(Timestamp stamp)
    {
        RemoveFromDatabase(item);
        Item cached = LastValueCache;
        if (cached != null && cached.Stamp == item.Stamp)
        {
            LastValueCache = null;
        }
    }

    public Item Get(Timestamp stamp)
    {
        Item cached = LastValueCache;
        if (cached != null && cached.Stamp == stamp)
        {
            return cached;
        }

        return GetFromDatabase(stamp);
    }
}

对象由多个线程。我不想用锁,因为它会影响性能,这在我的情况比数据的一致性更重要。现在的问题是什么最小的同步,将适合我的需要的机制?也许挥发性或单 MemoryBarrier GET 设置就足够了?

The Repository object is used by many threads. I do not want to use locking because it would affect performance which in my case is more important than data consistency. The question is what smallest synchronizing mechanism that will fit my need? Maybe volatile or single MemoryBarrier in get and set would be enough?

推荐答案

如果这是愚蠢的,你不需要投我失望。
只要告诉我,我会删除。
但我不遵循这一逻辑。

If this is stupid you don't need to vote me down.
Just tell me and I will delete.
But I am not following this logic.

public void Save(Item item)
{
    SaveToDatabase(item);
    Item cached = LastValueCache;
    if (cached == null || item.Stamp > cached.Stamp)
    {
        LastValueCache = item;
    }
}

您担心内存毫秒,但你在等待写入到数据库更新缓存之前。
基于公共项目获取邮票是一个关键。

You are worried about memory milliseconds but you are waiting on a write to the database before you update the cache.
Based on the public Item Get stamp is a key.

让我们假设一个数据库写为20毫秒
一个数据库读取为10毫秒
缓存GET和缓存设置都为2毫秒

Lets assume a db write is 20 ms
A db read is 10 ms
Cache get and cache set are each 2 ms

公共无效保存(逐项)
SaveToDatabase(项目); 20毫秒
项目缓存= LastValueCache; 2毫秒
如果(缓存== NULL || item.Stamp> cached.Stamp)1毫秒
LastValueCache =项目; 2毫秒

public void Save(Item item)
SaveToDatabase(item); 20 ms
Item cached = LastValueCache; 2 ms
if (cached == null || item.Stamp > cached.Stamp) 1 ms
LastValueCache = item; 2 ms

在之前LastValueCache =项23毫秒;任何调用公共项目获取(时间戳标记)将要访问数据库,而不是缓存。

During that 23 ms prior to the LastValueCache = item; any call to public Item Get(Timestamp stamp) is going to hit the DataBase and not the cache.

在23毫秒之前LastValueCache =项目; LastValueCache任何调用公共项目 得到的是要得到一个值,该值是陈旧的,最多23毫秒。 该规定的目的是为其他线程看到LastValueCache - 但看到一个陈旧的LastValueCache。

During the 23 ms prior to the LastValueCache = item; any call to public Item LastValueCache get is going to get a value that is stale by up 23 ms. The stated objective is for other threads to see LastValueCache - but the are seeing a stale LastValueCache.

同样的事情删除。
你将有几个点击你就可以避免数据库。

Same thing with Remove.
You are going to have several hits to the database you could have avoided.

什么是你想达到什么目的?
你有异形吗?

What are you trying to achieve?
Have you profiled this?

我敢打赌瓶颈就是对数据库的调用。
数据库呼叫是1000倍长于锁定和MemoryBarrier之间的差异。

My bet is the bottle neck is the calls to the database.
A database call is 1000x longer than the difference between a lock and MemoryBarrier.

public void Save(Item item)
{   
   // add logic that the prior asynchonous call to SaveToDatabase is complete
   // if not wait for it to complete 
   // LastValueCache will possible be replaced so you need last item in the database 
   // the time for a lock is not really a factor as it will be faster than the prior update 
   Item cached = LastValueCache;
   if (cached == null || item.Stamp > cached.Stamp)
   {
       LastValueCache = item;
   }
   // make the next a task or background so it does not block    
   SaveToDatabase(item);
}

甚至可以改变的逻辑,只能等待调用之前,如果你设置LastValueCache =项目;
但是,你需要以某种方式油门数据库

Could even change the logic to only wait for prior call if you setting LastValueCache = item;
But you need to throttle the database somehow

下一步将缓存最近的X和使用,在项目获取(时间戳标记)
该数据库是电话是什么,你需要优化
同样,你需要配置文件

The next step would be to cache the last X and use that in Item Get(Timestamp stamp)
The database are calls are what you need to optimize
Again you need to profile

在该逻辑将变得越来越复杂,但饲料数据库调用到BlockingCollection。将需要确保最后的X缓存大于BlockingCollections大小。如果不能阻止,等待BC清除。你将需要使用相同的BC的插入和删除,使他们处理的顺序。能否获得足够聪明,你只是不插入记录具有删除。而且不只是插入或删除单个记录的时间。

After that the logic would get more complex but feed the database calls to a BlockingCollection. Would need to be sure the last X cache is bigger than the BlockingCollections size. If not block and wait for the BC to clear. And you would need to use the same BC for insert and delete so they are processed in order. Could get smart enough that you just don't insert a records that has a delete. And don't just insert or delete a single record at a time.

这篇关于高性能缓存的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆