"bara" är ett mycket relativt begrepp och är inte riktigt meningsfullt utan mer sammanhang, i synnerhet:hur stora är dessa nyttolaster?
Men för att klargöra några punkter som hjälper dig att undersöka:
- det finns inget behov av att låsa en
IDatabase
såvida det inte är enbart för dina egna syften; SE.Redis sysslar med trådsäkerhet internt och är tänkt att användas av konkurrerande trådar - för närvarande kommer din tidpunkt för detta att inkludera all serialiseringskod (
JsonConvert.SerializeObject
); detta kommer att läggas ihop, särskilt om dina föremål är stora; För att få ett anständigt mått rekommenderar jag starkt att du tar tid för serialisering och redis tider separat batch.Execute()
Metoden använder ett pipeline-API och väntar inte på svar mellan samtal, så:tiden du ser är inte den kumulativa effekten av latens; som bara lämnar lokal CPU (för serialisering), nätverksbandbredd och server-CPU; klientbiblioteksverktygen kan inte påverka någon av dessa saker- det finns ett
StringSet
överbelastning som accepterar ettKeyValuePair<RedisKey, RedisValue>[]
; du kunde välj att använda detta istället för en batch, men den enda skillnaden här är att det är varadicMSET
snarare än fleraSET
; hur som helst, du kommer att blockera anslutningen för andra uppringare så länge (eftersom syftet med batch är att göra kommandona sammanhängande) - det gör du inte faktiskt måste använda
CreateBatch
här, särskilt eftersom du låser databasen (men jag föreslår fortfarande att du inte behöver göra detta); syftet medCreateBatch
är att göra en sekvens av kommandon sekventiell , men jag ser inte att du behöver detta här; du kan bara använda_database.StringSetAsync
för varje kommando i tur och ordning, vilket också skulle göra har fördelen att du skulle köra serialisering parallellt med det föregående kommandot som skickas - det skulle tillåta dig att överlappa serialisering (CPU bunden) och redis ops (IO bunden) utan något arbete förutom att ta bortCreateBatch
ringa upp; detta innebär också att du inte monopoliserar uppkopplingen från andra uppringare
Så; den första det jag skulle göra skulle vara att ta bort lite kod:
private static StackExchange.Redis.IDatabase _database;
static JsonSerializerSettings _redisJsonSettings = new JsonSerializerSettings {
ContractResolver = new SerializeAllContractResolver(),
ReferenceLoopHandling = ReferenceLoopHandling.Ignore };
public void SetAll<T>(Dictionary<string, T> data, int cacheTime)
{
TimeSpan expiration = new TimeSpan(0, cacheTime, 0);
var list = new List<Task<bool>>();
foreach (var item in data)
{
string serializedObject = JsonConvert.SerializeObject(
item.Value, Formatting.Indented, _redisJsonSettings);
list.Add(_database.StringSetAsync(item.Key, serializedObject, expiration));
}
Task.WhenAll(list.ToArray());
}
Det andra jag skulle göra skulle vara att tajma serialiseringen separat till redis-arbetet.
Det tredje jag skulle göra är att se om jag kan serialisera till en MemoryStream
istället, helst en som jag kan återanvända - för att undvika string
alocation och UTF-8-kodning:
using(var ms = new MemoryStream())
{
foreach (var item in data)
{
ms.Position = 0;
ms.SetLength(0); // erase existing data
JsonConvert.SerializeObject(ms,
item.Value, Formatting.Indented, _redisJsonSettings);
list.Add(_database.StringSetAsync(item.Key, ms.ToArray(), expiration));
}
}