get a counter value by using INCRBY 0

59 views
Skip to first unread message

Oded Peer

unread,
Mar 10, 2010, 5:32:24 AM3/10/10
to Redis DB
Hi,

I have a counter I save in redis.
I see that get() is a string operation, and as such it returns a byte
array.
converting this byte array to a counter involves a huge overhead in
Java, as I suppose is the case for other languages as well.
long counter = Long.parseLong( new String( jredis.get( "mykey" ) ) )

I changed the code to use INCRBY 0, to reduce the parsing and
converting overhead.
jredis.incrby( "mykey", 0 )

Do you see any problem with this approach?

Salvatore Sanfilippo

unread,
Mar 10, 2010, 7:48:18 AM3/10/10
to redi...@googlegroups.com
On Wed, Mar 10, 2010 at 11:32 AM, Oded Peer <peer...@gmail.com> wrote:
> Hi,
>
> I have a counter I save in redis.
> I see that get() is a string operation, and as such it returns a byte
> array.
> converting this byte array to a counter involves a huge overhead in
> Java, as I suppose is the case for other languages as well.
> long counter = Long.parseLong( new String( jredis.get( "mykey" ) ) )

Helo Oded!

There is something strange about this, converting a string into a long
should be a *fast* operation.
For fast I mean, many millions per second per core. So IMHO the right
way to fix the issue is to fix the conversion.

It's just a matter of, for all the digits, finding the ASCII value,
subtracting a constant to get the integer value of the digit,
multiplying by 10 the old value and summing the new one.

> I changed the code to use INCRBY 0, to reduce the parsing and
> converting overhead.
> jredis.incrby( "mykey", 0 )
>
> Do you see any problem with this approach?

Sorry I'm not understanding this, how incrementing by zero reduces the cost?

Cheers,
Salvatore

> --
> You received this message because you are subscribed to the Google Groups "Redis DB" group.
> 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.
>
>

--
Salvatore 'antirez' Sanfilippo
http://invece.org

"Once you have something that grows faster than education grows,
you’re always going to get a pop culture.", Alan Kay

Oded Peer

unread,
Mar 10, 2010, 9:26:11 AM3/10/10
to Redis DB
Right.
My mistake.
I saw Joubin already implemented this in the Convert class of JRedis.
Please ignore my previous post.

Joubin Houshyar

unread,
Mar 10, 2010, 10:24:16 AM3/10/10
to Redis DB
Hi Salvatore,


> There is something strange about this, converting a string into a long
> should be a *fast* operation.

Just FYI so you don't get the wrong impression about Java :)

Java strings are not c strings. They are immutable, and the
underlying byte array is a unicode representation. So you can't
simply bump a pointer as you go along.

And the Long class first determines if the string rep is signed it
need to visit the String class again to get a proper subset (see above
and thus more overhead).

Finally, it will do what you would expect (as you outlined), but again
here the implementation is generalized for various bases (radix), so a
bit more involved than the base-10 conversion. (For example, bound
checking the number of digits for a given base.)

Its comprehensive, but obviously the overheads add up.

/R

Joubin Houshyar

unread,
Mar 10, 2010, 10:45:41 AM3/10/10
to Redis DB
Hi Oded,

I haven't got around to effectively document patterns like this -- the
test suite is a fairly good place to see the various usage patterns.

And yes, Convert is there precisely for that reason, but it is
stepping on the DefaultCodec's territory and may get rolled into that
class; so use DefaultCodec instead as convert may be retired at some
point in the future. (Yes, there is a method overhead but JIT will
optimize that away, so don't worry about it.)

// expecting an integer
int value = DefaultCodec.toInt(jredis.get("foo"));

// expecting a long
long value = DefaultCodec.toLong(jredis.get("foo"));

// expecting an array of long values
List<Long> values = DefaultCodec.toLong(jredis.smembers("my_set"));

etc.

(Use static import and you can omit the class name and give your eyes/
fingers a rest.)

/R

Reply all
Reply to author
Forward
0 new messages