[sip-comm-dev] GenericBuffer explainations


#1

Hey all,

As some of you may have notice, many optimizations have been recently done
on SIP Communicator. I know with certainty that all of you do want to
optimize your code ;)... but sometimes you are not always sure on how to do
it or don't want to spend time on this. That's why I recently added the
GenericBuffer tool in package util. This little tool will help you to easily
and efficiently optimize your code (sounds great isn't it ?).

So let's call back John Smith. John Smith is currently developping a very
simple function.

His function has the following characteristic:
- Returns the same result when called with the same parameters
- Takes a ~lot~ of time to execute (more than tenth of milliseconds on a
recent computer)
- Is suspected to be called more than one time with the same parameters
during the program execution

So, currently, John's code is:
doSomething(int a, b, c) {
   return doSomethingElse(a, b);
}

John wants to optimize it. How can he do ? Right ! By using the brand new
GenericBuffer. Here is how he will do:
doSomething(int a, b, c) {
   result = genericbuffer.get("" + a + "/" + b); (1)
   if (result != null) return result; (2)

   result = doSomethingElse(a, b); (3)
   genericBuffer.add(result, "" + a + "/" + b); (4)
   return result; (5)
}

And here is what this new code does:
1 - We try to find in the buffer if we didn't already compute the same
operation
2 - If the value has already been computed, return the precomputed result
3 - Else compute
4 - Store the result for a possible next call with the same parameters
5 - Return the result

To be more clear, these buffers can be considered as hashtables able to
store already computed results using the parameters that influence the
result as a key. The string built in (1) and (4) using the value of a and b
explicitely shows this key: we construct here a key depending on all the
values that may modify the function result (and we ensure that this key is
unique by adding a tiny slash between the two numbers to separate them).

I'm not sure that all this is really clear so if any of you needs
explainations, don't hesitate to ask.

If you have any remarks, suggestion or comment I'll be glad to hear it.

Thanks for reading until here,

Ben


#2

Hello Ben,

I proposed some time ago a possibility to reuse class parameters, but they
live only in the instance of a class. Your GenericBuffer do the same but
here you are not limited by class instantination, that's cool. But how you
are going to limit the size of it? I suppose it can be a case of a memory
leak.
Another question: Do you have a set of sipcomm methods like John found
that take a ~lot~ of time to execute (more than tenth of milliseconds on a
recent computer) ?

Vladimir

···

On Thu, Oct 9, 2008 at 5:20 AM, Benoit Pradelle <b.pradelle@gmail.com>wrote:

Hey all,

As some of you may have notice, many optimizations have been recently done
on SIP Communicator. I know with certainty that all of you do want to
optimize your code ;)... but sometimes you are not always sure on how to do
it or don't want to spend time on this. That's why I recently added the
GenericBuffer tool in package util. This little tool will help you to easily
and efficiently optimize your code (sounds great isn't it ?).

So let's call back John Smith. John Smith is currently developping a very
simple function.

His function has the following characteristic:
- Returns the same result when called with the same parameters
- Takes a ~lot~ of time to execute (more than tenth of milliseconds on a
recent computer)
- Is suspected to be called more than one time with the same parameters
during the program execution

So, currently, John's code is:
doSomething(int a, b, c) {
   return doSomethingElse(a, b);
}

John wants to optimize it. How can he do ? Right ! By using the brand new
GenericBuffer. Here is how he will do:
doSomething(int a, b, c) {
   result = genericbuffer.get("" + a + "/" + b); (1)
   if (result != null) return result; (2)

   result = doSomethingElse(a, b); (3)
   genericBuffer.add(result, "" + a + "/" + b); (4)
   return result; (5)
}

And here is what this new code does:
1 - We try to find in the buffer if we didn't already compute the same
operation
2 - If the value has already been computed, return the precomputed result
3 - Else compute
4 - Store the result for a possible next call with the same parameters
5 - Return the result

To be more clear, these buffers can be considered as hashtables able to
store already computed results using the parameters that influence the
result as a key. The string built in (1) and (4) using the value of a and b
explicitely shows this key: we construct here a key depending on all the
values that may modify the function result (and we ensure that this key is
unique by adding a tiny slash between the two numbers to separate them).

I'm not sure that all this is really clear so if any of you needs
explainations, don't hesitate to ask.

If you have any remarks, suggestion or comment I'll be glad to hear it.

Thanks for reading until here,

Ben


#3

Hi Lubomir,

Actually when you create the buffer, you specify a capacity so there is no
risk of memory leak. This capacity also allows you to do some tricky things
with the buffer when specifying a size of 1 as the buffer will behave as a
simple memory of what were the last call parameters. This behavior will be
very useful for optimizing self-modifying classes.

About the methods that take a lot of time to execute it's up to each dev to
find them and we're not restricted to functions but any tough code parts can
be optimized this way. Profiler4J will be very useful in exposing these
methods.

Ben

···

2008/10/9 Vladimir Shkarupelov <voviss@gmail.com>

Hello Ben,

I proposed some time ago a possibility to reuse class parameters, but they
live only in the instance of a class. Your GenericBuffer do the same but
here you are not limited by class instantination, that's cool. But how you
are going to limit the size of it? I suppose it can be a case of a memory
leak.
Another question: Do you have a set of sipcomm methods like John found
that take a ~lot~ of time to execute (more than tenth of milliseconds on a
recent computer) ?

Vladimir
On Thu, Oct 9, 2008 at 5:20 AM, Benoit Pradelle <b.pradelle@gmail.com>wrote:

Hey all,

As some of you may have notice, many optimizations have been recently done
on SIP Communicator. I know with certainty that all of you do want to
optimize your code ;)... but sometimes you are not always sure on how to do
it or don't want to spend time on this. That's why I recently added the
GenericBuffer tool in package util. This little tool will help you to easily
and efficiently optimize your code (sounds great isn't it ?).

So let's call back John Smith. John Smith is currently developping a very
simple function.

His function has the following characteristic:
- Returns the same result when called with the same parameters
- Takes a ~lot~ of time to execute (more than tenth of milliseconds on a
recent computer)
- Is suspected to be called more than one time with the same parameters
during the program execution

So, currently, John's code is:
doSomething(int a, b, c) {
   return doSomethingElse(a, b);
}

John wants to optimize it. How can he do ? Right ! By using the brand new
GenericBuffer. Here is how he will do:
doSomething(int a, b, c) {
   result = genericbuffer.get("" + a + "/" + b); (1)
   if (result != null) return result; (2)

   result = doSomethingElse(a, b); (3)
   genericBuffer.add(result, "" + a + "/" + b); (4)
   return result; (5)
}

And here is what this new code does:
1 - We try to find in the buffer if we didn't already compute the same
operation
2 - If the value has already been computed, return the precomputed result
3 - Else compute
4 - Store the result for a possible next call with the same parameters
5 - Return the result

To be more clear, these buffers can be considered as hashtables able to
store already computed results using the parameters that influence the
result as a key. The string built in (1) and (4) using the value of a and b
explicitely shows this key: we construct here a key depending on all the
values that may modify the function result (and we ensure that this key is
unique by adding a tiny slash between the two numbers to separate them).

I'm not sure that all this is really clear so if any of you needs
explainations, don't hesitate to ask.

If you have any remarks, suggestion or comment I'll be glad to hear it.

Thanks for reading until here,

Ben


#4

Hi Ben,

Thank you for the explanation!

Just a mild note that it was Vladimir Shkarupelov who asked the
questions and not Lubomir Marinov.

Please don't understand the following as an argument against the
possibly-good idea of GenericBuffer. I searched for references to it
in SIP Communicator and I didn't find any. Is there a specific case in
which it's to be used in the near future? I'm asking because it's yet
one more file to maintain. Moreover, without use cases demonstrating
actual advantages over, for example, plain caching in a class or
instance field tuned to the specific needs of the case, I guess the
adoption rate will be very low.

Best regards,
Lubo

···

On Thu, Oct 9, 2008 at 5:04 PM, Benoit Pradelle <b.pradelle@gmail.com> wrote:

Hi Lubomir,

Actually when you create the buffer, you specify a capacity so there is no
risk of memory leak. This capacity also allows you to do some tricky things
with the buffer when specifying a size of 1 as the buffer will behave as a
simple memory of what were the last call parameters. This behavior will be
very useful for optimizing self-modifying classes.

About the methods that take a lot of time to execute it's up to each dev to
find them and we're not restricted to functions but any tough code parts can
be optimized this way. Profiler4J will be very useful in exposing these
methods.

Ben

2008/10/9 Vladimir Shkarupelov <voviss@gmail.com>

Hello Ben,

I proposed some time ago a possibility to reuse class parameters, but they
live only in the instance of a class. Your GenericBuffer do the same but
here you are not limited by class instantination, that's cool. But how you
are going to limit the size of it? I suppose it can be a case of a memory
leak.
Another question: Do you have a set of sipcomm methods like John found
that take a ~lot~ of time to execute (more than tenth of milliseconds on a
recent computer) ?

Vladimir
On Thu, Oct 9, 2008 at 5:20 AM, Benoit Pradelle <b.pradelle@gmail.com> >> wrote:

Hey all,

As some of you may have notice, many optimizations have been recently
done on SIP Communicator. I know with certainty that all of you do want to
optimize your code ;)... but sometimes you are not always sure on how to do
it or don't want to spend time on this. That's why I recently added the
GenericBuffer tool in package util. This little tool will help you to easily
and efficiently optimize your code (sounds great isn't it ?).

So let's call back John Smith. John Smith is currently developping a very
simple function.

His function has the following characteristic:
- Returns the same result when called with the same parameters
- Takes a ~lot~ of time to execute (more than tenth of milliseconds on a
recent computer)
- Is suspected to be called more than one time with the same parameters
during the program execution

So, currently, John's code is:
doSomething(int a, b, c) {
   return doSomethingElse(a, b);
}

John wants to optimize it. How can he do ? Right ! By using the brand new
GenericBuffer. Here is how he will do:
doSomething(int a, b, c) {
   result = genericbuffer.get("" + a + "/" + b); (1)
   if (result != null) return result; (2)

   result = doSomethingElse(a, b); (3)
   genericBuffer.add(result, "" + a + "/" + b); (4)
   return result; (5)
}

And here is what this new code does:
1 - We try to find in the buffer if we didn't already compute the same
operation
2 - If the value has already been computed, return the precomputed result
3 - Else compute
4 - Store the result for a possible next call with the same parameters
5 - Return the result

To be more clear, these buffers can be considered as hashtables able to
store already computed results using the parameters that influence the
result as a key. The string built in (1) and (4) using the value of a and b
explicitely shows this key: we construct here a key depending on all the
values that may modify the function result (and we ensure that this key is
unique by adding a tiny slash between the two numbers to separate them).

I'm not sure that all this is really clear so if any of you needs
explainations, don't hesitate to ask.

If you have any remarks, suggestion or comment I'll be glad to hear it.

Thanks for reading until here,

Ben

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net


#5

Hi Lubornir,

I apology for the name mistake, I'm so used to chat with you about
performances issues that I didn't paid enough attention to the name so
please excuse me.

And actually in term of performance there is no advantages of this tool over
a specifically tuned implementation and this generic implementation will
probably be a little bit worse in many cases. The advantage is that this
class allows a quick and easy implementation of the optimization for people
who don't want to spend much time on that or who are not sure about what
they have to do. It's just more dev-friendly than expecting everyone from
doing manually tuned optimization in each class.

Concerning its applicability, this class can replace any previous similar
optimization written in a class specific way. And I've planned to replace my
recent optimizations with calls to this class but I'd like to have other dev
opinion before spreading calls to this class.

Cheers,

Ben

···

2008/10/9 Lubomir Marinov <lubomir.marinov@gmail.com>

Hi Ben,

Thank you for the explanation!

Just a mild note that it was Vladimir Shkarupelov who asked the
questions and not Lubomir Marinov.

Please don't understand the following as an argument against the
possibly-good idea of GenericBuffer. I searched for references to it
in SIP Communicator and I didn't find any. Is there a specific case in
which it's to be used in the near future? I'm asking because it's yet
one more file to maintain. Moreover, without use cases demonstrating
actual advantages over, for example, plain caching in a class or
instance field tuned to the specific needs of the case, I guess the
adoption rate will be very low.

Best regards,
Lubo

On Thu, Oct 9, 2008 at 5:04 PM, Benoit Pradelle <b.pradelle@gmail.com> > wrote:
> Hi Lubomir,
>
> Actually when you create the buffer, you specify a capacity so there is
no
> risk of memory leak. This capacity also allows you to do some tricky
things
> with the buffer when specifying a size of 1 as the buffer will behave as
a
> simple memory of what were the last call parameters. This behavior will
be
> very useful for optimizing self-modifying classes.
>
> About the methods that take a lot of time to execute it's up to each dev
to
> find them and we're not restricted to functions but any tough code parts
can
> be optimized this way. Profiler4J will be very useful in exposing these
> methods.
>
> Ben
>
> 2008/10/9 Vladimir Shkarupelov <voviss@gmail.com>
>>
>> Hello Ben,
>>
>> I proposed some time ago a possibility to reuse class parameters, but
they
>> live only in the instance of a class. Your GenericBuffer do the same but
>> here you are not limited by class instantination, that's cool. But how
you
>> are going to limit the size of it? I suppose it can be a case of a
memory
>> leak.
>> Another question: Do you have a set of sipcomm methods like John found
>> that take a ~lot~ of time to execute (more than tenth of milliseconds on
a
>> recent computer) ?
>>
>> Vladimir
>> On Thu, Oct 9, 2008 at 5:20 AM, Benoit Pradelle <b.pradelle@gmail.com> > >> wrote:
>>>
>>> Hey all,
>>>
>>> As some of you may have notice, many optimizations have been recently
>>> done on SIP Communicator. I know with certainty that all of you do want
to
>>> optimize your code ;)... but sometimes you are not always sure on how
to do
>>> it or don't want to spend time on this. That's why I recently added the
>>> GenericBuffer tool in package util. This little tool will help you to
easily
>>> and efficiently optimize your code (sounds great isn't it ?).
>>>
>>> So let's call back John Smith. John Smith is currently developping a
very
>>> simple function.
>>>
>>> His function has the following characteristic:
>>> - Returns the same result when called with the same parameters
>>> - Takes a ~lot~ of time to execute (more than tenth of milliseconds on
a
>>> recent computer)
>>> - Is suspected to be called more than one time with the same parameters
>>> during the program execution
>>>
>>> So, currently, John's code is:
>>> doSomething(int a, b, c) {
>>> return doSomethingElse(a, b);
>>> }
>>>
>>> John wants to optimize it. How can he do ? Right ! By using the brand
new
>>> GenericBuffer. Here is how he will do:
>>> doSomething(int a, b, c) {
>>> result = genericbuffer.get("" + a + "/" + b); (1)
>>> if (result != null) return result; (2)
>>>
>>> result = doSomethingElse(a, b); (3)
>>> genericBuffer.add(result, "" + a + "/" + b); (4)
>>> return result; (5)
>>> }
>>>
>>> And here is what this new code does:
>>> 1 - We try to find in the buffer if we didn't already compute the same
>>> operation
>>> 2 - If the value has already been computed, return the precomputed
result
>>> 3 - Else compute
>>> 4 - Store the result for a possible next call with the same parameters
>>> 5 - Return the result
>>>
>>> To be more clear, these buffers can be considered as hashtables able to
>>> store already computed results using the parameters that influence the
>>> result as a key. The string built in (1) and (4) using the value of a
and b
>>> explicitely shows this key: we construct here a key depending on all
the
>>> values that may modify the function result (and we ensure that this key
is
>>> unique by adding a tiny slash between the two numbers to separate
them).
>>>
>>> I'm not sure that all this is really clear so if any of you needs
>>> explainations, don't hesitate to ask.
>>>
>>> If you have any remarks, suggestion or comment I'll be glad to hear it.
>>>
>>> Thanks for reading until here,
>>>
>>> Ben
>>
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@sip-communicator.dev.java.net
For additional commands, e-mail: dev-help@sip-communicator.dev.java.net