- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
我正在使用 Stackexchange Redis 客户端实现一个 Redis 缓存层,而现在的性能几乎无法使用。
我有一个本地环境,其中 Web 应用程序和 Redis 服务器在同一台机器上运行。我针对我的 Redis 服务器运行了 Redis 基准测试,结果实际上非常好(我只是在我的文章中包括设置和获取操作):
C:\Program Files\Redis>redis-benchmark -n 100000
====== PING_INLINE ======
100000 requests completed in 0.88 seconds
50 parallel clients
3 bytes payload
keep alive: 1
====== SET ======
100000 requests completed in 0.89 seconds
50 parallel clients
3 bytes payload
keep alive: 1
99.70% <= 1 milliseconds
99.90% <= 2 milliseconds
100.00% <= 3 milliseconds
111982.08 requests per second
====== GET ======
100000 requests completed in 0.81 seconds
50 parallel clients
3 bytes payload
keep alive: 1
99.87% <= 1 milliseconds
99.98% <= 2 milliseconds
100.00% <= 2 milliseconds
124069.48 requests per second
因此,根据基准,我每秒查看超过 100,000 组和 100,000 次获取。我编写了一个单元测试来执行 300,000 次设置/获取:
private string redisCacheConn = "localhost:6379,allowAdmin=true,abortConnect=false,ssl=false";
[Fact]
public void PerfTestWriteShortString()
{
CacheManager cm = new CacheManager(redisCacheConn);
string svalue = "t";
string skey = "testtesttest";
for (int i = 0; i < 300000; i++)
{
cm.SaveCache(skey + i, svalue);
string valRead = cm.ObtainItemFromCacheString(skey + i);
}
}
这使用以下类通过 Stackexchange 客户端执行 Redis 操作:
using StackExchange.Redis;
namespace Caching
{
public class CacheManager:ICacheManager, ICacheManagerReports
{
private static string cs;
private static ConfigurationOptions options;
private int pageSize = 5000;
public ICacheSerializer serializer { get; set; }
public CacheManager(string connectionString)
{
serializer = new SerializeJSON();
cs = connectionString;
options = ConfigurationOptions.Parse(connectionString);
options.SyncTimeout = 60000;
}
private static readonly Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(options));
private static ConnectionMultiplexer Connection => lazyConnection.Value;
private static IDatabase cache => Connection.GetDatabase();
public string ObtainItemFromCacheString(string cacheId)
{
return cache.StringGet(cacheId);
}
public void SaveCache<T>(string cacheId, T cacheEntry, TimeSpan? expiry = null)
{
if (IsValueType<T>())
{
cache.StringSet(cacheId, cacheEntry.ToString(), expiry);
}
else
{
cache.StringSet(cacheId, serializer.SerializeObject(cacheEntry), expiry);
}
}
public bool IsValueType<T>()
{
return typeof(T).IsValueType || typeof(T) == typeof(string);
}
}
}
我的 JSON 序列化程序只使用 Newtonsoft.JSON:
using System.Collections.Generic;
using Newtonsoft.Json;
namespace Caching
{
public class SerializeJSON:ICacheSerializer
{
public string SerializeObject<T>(T cacheEntry)
{
return JsonConvert.SerializeObject(cacheEntry, Formatting.None,
new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
public T DeserializeObject<T>(string data)
{
return JsonConvert.DeserializeObject<T>(data, new JsonSerializerSettings()
{
ReferenceLoopHandling = ReferenceLoopHandling.Ignore
});
}
}
}
我的测试时间约为 21 秒(300,000 组和 300,000 次获取)。这给了我每秒大约 28,500 次操作(至少比我预期使用基准测试慢 3 倍)。我正在转换为使用 Redis 的应用程序非常繁琐,某些繁重的请求可能对 Redis 进行大约 200,000 次总操作。显然,我没有预料到我在使用系统运行时缓存时会遇到同样的情况,但此更改后的延迟很明显。我的实现是否有问题,有人知道为什么我的基准数据比我的 Stackechange 测试数据快得多吗?
谢谢,保罗
最佳答案
我从下面的代码中得到的结果:
Connecting to server...
Connected
PING (sync per op)
1709ms for 1000000 ops on 50 threads took 1.709594 seconds
585137 ops/s
SET (sync per op)
759ms for 500000 ops on 50 threads took 0.7592914 seconds
658761 ops/s
GET (sync per op)
780ms for 500000 ops on 50 threads took 0.7806102 seconds
641025 ops/s
PING (pipelined per thread)
3751ms for 1000000 ops on 50 threads took 3.7510956 seconds
266595 ops/s
SET (pipelined per thread)
1781ms for 500000 ops on 50 threads took 1.7819831 seconds
280741 ops/s
GET (pipelined per thread)
1977ms for 500000 ops on 50 threads took 1.9772623 seconds
252908 ops/s
===
服务器配置:确保禁用持久性等
您应该在基准测试中做的第一件事是:基准测试一件事。目前,您包含了大量的序列化开销,这无助于获得清晰的画面。理想情况下,对于同类基准测试,您应该使用 3 字节的固定负载,因为:
3 bytes payload
接下来,您需要了解并行性:
50 parallel clients
不清楚您的测试是否是并行的,但如果不是,我们绝对期望看到更少的原始吞吐量。方便的是,SE.Redis 被设计成易于并行化:你可以启动多个线程与同一个连接(这实际上也有避免数据包碎片的优点,因为你最终可以每个数据包多条消息,其中单线程同步方法保证每个数据包最多使用一条消息。
最后,我们需要了解列出的基准测试在做什么。它在做什么:
(send, receive) x n
或者它在做什么
send x n, receive separately until all n are received
?两种选择都是可能的。您的同步 API 使用是第一个,但第二个测试同样定义明确,据我所知:这就是它正在测量的内容。有两种方法可以模拟第二个设置:
*Async
API,并且仅对最后一个 Task
使用 Wait()
或 await
这是我在上面使用的基准测试,它显示了“每个操作同步”(通过同步 API)和“每个线程的管道”(使用 *Async
API 并等待每个线程的最后一个任务),都使用 50 个线程:
using StackExchange.Redis;
using System;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
static class P
{
static void Main()
{
Console.WriteLine("Connecting to server...");
using (var muxer = ConnectionMultiplexer.Connect("127.0.0.1"))
{
Console.WriteLine("Connected");
var db = muxer.GetDatabase();
RedisKey key = "some key";
byte[] payload = new byte[3];
new Random(12345).NextBytes(payload);
RedisValue value = payload;
DoWork("PING (sync per op)", db, 1000000, 50, x => { x.Ping(); return null; });
DoWork("SET (sync per op)", db, 500000, 50, x => { x.StringSet(key, value); return null; });
DoWork("GET (sync per op)", db, 500000, 50, x => { x.StringGet(key); return null; });
DoWork("PING (pipelined per thread)", db, 1000000, 50, x => x.PingAsync());
DoWork("SET (pipelined per thread)", db, 500000, 50, x => x.StringSetAsync(key, value));
DoWork("GET (pipelined per thread)", db, 500000, 50, x => x.StringGetAsync(key));
}
}
static void DoWork(string action, IDatabase db, int count, int threads, Func<IDatabase, Task> op)
{
object startup = new object(), shutdown = new object();
int activeThreads = 0, outstandingOps = count;
Stopwatch sw = default(Stopwatch);
var threadStart = new ThreadStart(() =>
{
lock(startup)
{
if(++activeThreads == threads)
{
sw = Stopwatch.StartNew();
Monitor.PulseAll(startup);
}
else
{
Monitor.Wait(startup);
}
}
Task final = null;
while (Interlocked.Decrement(ref outstandingOps) >= 0)
{
final = op(db);
}
if (final != null) final.Wait();
lock(shutdown)
{
if (--activeThreads == 0)
{
sw.Stop();
Monitor.PulseAll(shutdown);
}
}
});
lock (shutdown)
{
for (int i = 0; i < threads; i++)
{
new Thread(threadStart).Start();
}
Monitor.Wait(shutdown);
Console.WriteLine($@"{action}
{sw.ElapsedMilliseconds}ms for {count} ops on {threads} threads took {sw.Elapsed.TotalSeconds} seconds
{(count * 1000) / sw.ElapsedMilliseconds} ops/s");
}
}
}
关于c# - 与基准测试相比,StackExchange redis 客户端非常慢,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35707867/
我正在阅读一些基准测试技巧,并在此站点上发现了一条提示“重新启动 MySQL 服务器以消除任何不需要的缓存因素”:http://blog.monitor.us/2012/09/the-gold-sta
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 7 年前。
我在linux上测量cpu时间和排序算法的时间。我使用getrusage来测量cpu时间,并使用clock_gettime CLOCK_MONOTONIC来获取墙时间。尽管我注意到cpu时间大于墙上时
我可以阅读很多关于 OpenCL 的文章,它似乎是最有前途的(唯一的?)多架构库。 OpenCL应该是第一个并行架构编程标准,它最终会被大部分程序员采用。这很好,但是从 native 编程库迁移到 O
我想在不使用外部依赖项的情况下对一些 Lua 进行基准测试。我目前正在使用 os.clock: local function dummy() end local start = os.clock()
我对此很好奇。 我想检查哪个函数更快,所以我编写了一些代码并执行了很多次。 public static void main(String[] args) { long ts;
有没有办法在项目的开发阶段对 SQL 查询进行基准测试? 有问题的表中只有几个示例行,但我想在行数达到数千、数百万、数十亿、数万亿、数亿等等之前对一些查询进行基准测试 用数千行样本数据填充表格是唯一的
我正在尝试测量使用 rdtsc 执行函数“check()”所需的时间,如下所示: a = rdtsc(); check(pw); b = rdtsc(); return (b-a); 但是,我收到的时
我想在我的 Hadoop 集群上执行基准测试和性能测试。我知道 hadoop-mapreduce*test*.jar 和 hadoop-mapreduce-examples*.jar 有很多用于基准测
按照目前的情况,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
这个现在非常常见的算法问题是在白板考试期间由监考人员提出的。我的工作是观察、倾听和客观判断给出的答案,但我无法控制这个问题,也无法与回答者互动。 给了五分钟的时间分析问题,考生可以写项目符号,伪代码(
我把代码从 http://www.bonto.ch/blog/2011/12/08/json-libraries-for-ios-comparison-updated/并在我的本地机器上进行了测试。
我正在尝试使用 MySQL 基准测试来测试一些查询。但是,我遇到了一个错误。 SELECT benchmark (10000, (select title from user)); 作为返回,我得到了
我很好奇这个。 我想检查哪个函数更快,所以我创建了一些代码并执行了很多次。 public static void main(String[] args) { long ts;
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 9 年前。 Improve this qu
我经常想比较同一函数的多个实现的运行时性能。对于个人输入,标准是一个很好的工具。 但是有什么简单的方法可以在不同的输入大小上绘制代码的性能,例如看算法复杂度? 理想情况下,我向库传递一个类型为 Ben
我有一系列旨在完成相同功能的功能。相同的输入产生相同的输出,但是执行这些输出所需的时间因功能而异。我想确定哪个是“最快”的,我想对自己的测量结果具有“统计学意义”有一定的信心。 细读Wikipedia
我想编写一个加载基准测试,它以编译时已知的步幅跨过给定的内存区域,并在该区域的末尾(2 的幂)使用尽可能少的非加载指令进行包装有可能。 例如,给定步长 4099,rdi 中的迭代计数以及 rsi 中指
我有多个组件与 RabbitMQ 相连。有些是生产者和消费者。我需要对我的系统进行基准测试/负载测试。我需要确保消费者每秒可以处理 N 条消息。我在互联网上做了一些搜索,但还没有真正找到任何东西。有没
是否有任何基准或研究来比较这两个 IDE --稳定性-- 开发人员生产力 - 特征 - 表现-- 等等 最佳答案 我是 Eclipse 用户(不是自愿的)。不确定稳定性,但性能方面 NetBeans
我是一名优秀的程序员,十分优秀!