Re: Bad perfomance of mass insertion to Redis DB with Sider .NET client

768 views
Skip to first unread message

Garry Shutler

unread,
Oct 11, 2012, 5:39:47 AM10/11/12
to redi...@googlegroups.com
Do you have the same performance without the Console.Write? Writing to the console can be rather slow.

Garry Shutler


On 11 October 2012 10:14, Макс Бартенев <maxt...@gmail.com> wrote:

I need to insert about one million key-value pairs in Redis DB. I have a Redis server instance on the same computer with my C# application. I use Sider client to connect to Redis. All settings are default. The following code executes for 4 seconds:

    redis_client.Pipeline(c =>
   
{
       
for (int i = 0; i < 1000; ++i)
       
{
           
Console.Write("\r" + i);
           
string key = "aaaaaaaaaaa" + i;
           
string value = "bbbbbbbbbb";
            c
.Set(key, value);
       
}
   
});

I tried both usual and pipeline method of insertion. Standard benchmark of Redis shows similar results. CPU or HDD have no problems and them enough for another mass insertion in different databases.Official benchmark page of Redis says about possibility of ~100000 SET operations per second. I have less then 1000... What's the problem?

--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To view this discussion on the web visit https://groups.google.com/d/msg/redis-db/-/LaNo5G_ZcIEJ.
To post to this group, send email to redi...@googlegroups.com.
To unsubscribe from this group, send email to redis-db+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/redis-db?hl=en.

Макс Бартенев

unread,
Oct 11, 2012, 6:07:45 AM10/11/12
to redi...@googlegroups.com
Yes, of course I tried and without writing to console. Current code I write just for testing and to demonstrate my trouble. My real problem (where 1 million pairs) doesn't have any console input/output operations and has the same perfomance.

четверг, 11 октября 2012 г., 13:39:52 UTC+4 пользователь Garry Shutler написал:

Didier Spezia

unread,
Oct 11, 2012, 7:11:56 AM10/11/12
to redi...@googlegroups.com

>> .Official benchmark page of Redis says about possibility of ~100000 SET operations per second. I have less then 1000... What's the problem?

I would suggest to try the benchmark program by yourself: it is trivial to launch
and part of the Redis distribution. So you will be able to check if the problem is
on server side or client side.

Regards,
Didier.

AcidZombie24

unread,
Oct 11, 2012, 7:17:06 AM10/11/12
to redi...@googlegroups.com
It depends on your machine. For example my i7 with FAST RAM can do 1M inserts in ~5seconds. Thats 200K per second

Heres my code. I use booksleeve which you can grab using nuget http://code.google.com/p/booksleeve/

WARNING i do a FlushAll so comment that out if you have data on your server

        static void memorytest()
        {
            using (var conn = new RedisConnection("localhost", allowAdmin: true))
            {
                var stopwatch = new System.Diagnostics.Stopwatch();
                conn.Open();
                conn.Server.FlushAll();
                //var buf = new byte[1024/2];
                var buf = new byte[8];
                var amount = 150;
                stopwatch.Start();
                for (int i = 0; i < 1000000; ++i)
                {
                    //conn.Strings.Set(1, string.Format("k{0}", i), i.ToString());
                    //ignore this conn.Hashes.Set(1, string.Format("k{0}", i/1000), string.Format("{0}",i%1023), buf);
                    var t = conn.Hashes.Set(1, string.Format("k{0}", i / amount), (i % amount).ToString(), buf);
                    //if ((i & 4095) == 4095) conn.Wait(t);
                }
                conn.Wait(conn.Strings.Set(1,"hi", buf));
                stopwatch.Stop();
                Console.WriteLine("{0}", stopwatch.ElapsedMilliseconds);

Marc Gravell

unread,
Oct 11, 2012, 7:19:33 AM10/11/12
to redi...@googlegroups.com
This looks like a problem with that client; I have the following 2 tests, one using BookSleeve, one using Sider. The first (BookSleeve) takes 3ms, the second (Sider) takes 2391ms. If I don't pause to wait for the replies, BookSleeve takes 1ms:

        [Test]
        public void TestBookSleevePipelinePerformance()
        {
            using (var redis_client = new BookSleeve.RedisConnection("localhost", 6379))
            {
                redis_client.Open();
                var watch = Stopwatch.StartNew();
                Task last = null;
                for (int i = 0; i < 1000; ++i)
                {
                    string key = "aaaaaaaaaaa" + i;
                    string value = "bbbbbbbbbb";
                    last = redis_client.Strings.Set(0, key, value);
                }
                // not required, but for the fun, wait until we've
                // had all of the replies
                redis_client.Wait(last); 
                watch.Stop();
                Console.WriteLine("{0}ms", watch.ElapsedMilliseconds);
            }
        }
        [Test]
        public void TestSiderPipelinePerformance()
        {
            using (var redis_client = new Sider.RedisClient("localhost", 6379))
            {
                var watch = Stopwatch.StartNew();
                redis_client.Pipeline(c =>
                {
                    for (int i = 0; i < 1000; ++i)
                    {
                        string key = "aaaaaaaaaaa" + i;
                        string value = "bbbbbbbbbb";
                        c.Set(key, value);
                    }
                });
                watch.Stop();
                Console.WriteLine("{0}ms", watch.ElapsedMilliseconds);
            }
        }

--
You received this message because you are subscribed to the Google Groups "Redis DB" group.
To view this discussion on the web visit https://groups.google.com/d/msg/redis-db/-/E9ezx7ziAxcJ.

To post to this group, send email to redi...@googlegroups.com.
To unsubscribe from this group, send email to redis-db+u...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/redis-db?hl=en.



--
Regards,

Marc

Marc Gravell

unread,
Oct 11, 2012, 7:24:56 AM10/11/12
to redi...@googlegroups.com
Further, if I add a separate wait after *every* operation (i.e. we completely fail to use the pipeline), then it **still** only takes about 100ms. You can simulate this by the addition of a Wait in the loop:

                for (int i = 0; i < 1000; ++i)
                {
                    string key = "aaaaaaaaaaa" + i;
                    string value = "bbbbbbbbbb";
                    last = redis_client.Strings.Set(0, key, value);
                    redis_client.Wait(last); 
                }

So: I don't know what Sider is doing for the rest of the time, but it isn't a redis-server issue.

Marc
--
Regards,

Marc

Salvatore Sanfilippo

unread,
Oct 11, 2012, 7:27:31 AM10/11/12
to redi...@googlegroups.com
Tcp_nodelay?
Salvatore 'antirez' Sanfilippo
open source developer - VMware
http://invece.org

Beauty is more important in computing than anywhere else in technology because software is so complicated. Beauty is the ultimate defence against complexity.
       — David Gelernter

Marc Gravell

unread,
Oct 11, 2012, 7:39:45 AM10/11/12
to redi...@googlegroups.com
I don't think so - at least, not at cursory glance; it has:

      _socket.NoDelay = true;

which will disable local buffering, and it looks like it is also using a BufferedStream in RedisWriter, which is entirely appropriate and should prevent packet fragmentation / saturation (i.e. you don't want a packet per parameter / command / space / etc). So it looks like it *should* be OK, but I'll leave it to the library author to investigate and fix. Perhaps wireshark would be a good starting place.

Marc
Regards,

Marc

Salvatore Sanfilippo

unread,
Oct 11, 2012, 8:20:53 AM10/11/12
to redi...@googlegroups.com
Thank you for verifying this, I said that because it is a very common
source of incredibly shitty performances.

Cheers,
Salvatore

Макс Бартенев

unread,
Oct 11, 2012, 2:42:59 PM10/11/12
to redi...@googlegroups.com
Thanks, I tried both main .NET clients for Redis DB: ServiceStack and Booksleeve. Results are very good: 1000 SET operations execute for about 23ms. So on, now I have about 50000 SET operations per second on my notebook with Core i3 and 4GB DDR3 RAM. Thats acceptable results for me.
I have only one strange thing. Why does the standard benchmark show not so good results? It shows about 4000 SET operations per second...

Salvatore Sanfilippo

unread,
Oct 11, 2012, 2:58:16 PM10/11/12
to redi...@googlegroups.com
On Thu, Oct 11, 2012 at 8:42 PM, Макс Бартенев <maxt...@gmail.com> wrote:
> I have only one strange thing. Why does the standard benchmark show not so
> good results? It shows about 4000 SET operations per second...

You mean redis-benchmark? This is odd indeed.

Salvatore

Adam Liverman

unread,
Sep 14, 2014, 12:34:53 AM9/14/14
to redi...@googlegroups.com
Sorry this is a bit late. (2 years!) Unsure if this will be helpful to others, but here goes :)

I played around with the Sider code and traced *most* of the performance issues down to the SAssert class with "Compile" calls to lambdas.

Thankfully most of these calls have the "DEBUG" conditional. Set to release mode , and be sure to 'rebuild'. (setting to release mode should remove the "debug" checkbox in the build second of the project "Define DEBUG constant"

Command: SET
Before:  1000 entries takes about 4 seconds. (what you seem to experience)
After: 1000 entries takes about 219 milliseconds.

Command: MSET 

Before: 1000 entries takes about 2.5 seconds
After 1000 entries takes about 47 milliseconds.

Still room for improvement, but a lot faster than before.




On Thursday, October 11, 2012 2:14:34 AM UTC-7, Макс Бартенев wrote:

I need to insert about one million key-value pairs in Redis DB. I have a Redis server instance on the same computer with my C# application. I use Sider client to connect to Redis. All settings are default. The following code executes for 4 seconds:

    redis_client.Pipeline(c =>

   
{
       
for (int i = 0; i < 1000; ++i)
       
{

           
Console.Write("\r" + i);

           
string key = "aaaaaaaaaaa" + i;
           
string value = "bbbbbbbbbb";
            c
.Set(key, value);
       
}
   
});

I tried both usual and pipeline method of insertion. Standard benchmark of Redis shows similar results. CPU or HDD have no problems and them enough for another mass insertion in different databases.Official benchmark page of Redis says about possibility of ~100000 SET operations per second. I have less then 1000... What's the problem?

Adam Liverman

unread,
Sep 14, 2014, 5:03:38 PM9/14/14
to redi...@googlegroups.com
After a little more work, and using Pipelining I have performance on the level of about 4-5 milliseconds for 1000 entries which seems to be what you were originally looking for.

 client.Pipeline(p =>
                {
                    for (int i = 0; i < 1000; ++i)
                    {
                        //     Console.Write("\r" + i);
                        string key = "aaaaaaaaaaa" + i;
                        client.Set(key, "bbbbbbbbbbbb");
                    }

                }); 

I did make a few performance enhancements to the client, as well as adding pooling capabilities to it
 (in mono, just doing " _socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream, ProtocolType.Tcp);" was taking 90+ milliseconds! normal .net was fine)

Having said that, the default client should be not too far behind.

MSET took around 3-4 milliseconds per 1000.
Reply all
Reply to author
Forward
0 new messages