From: Daniel Pitts on
On 7/14/2010 9:42 AM, Kevin McMurtrie wrote:
> In article<sbnr36ta3l2bqkf0mt23pgg6g3k8nf2ud2(a)4ax.com>,
> Roedy Green<see_website(a)mindprod.com.invalid> wrote:
>
>> On 13 Jul 2010 15:01:35 GMT, Andreas Leitgeb
>> <avl(a)gamma.logic.tuwien.ac.at> wrote, quoted or indirectly quoted
>> someone who said :
>>
>>> It seems so basic that I can't believe such a feature wasn't in
>>> the standard library:
>>
>> it is part of the common11 tools for JDK 1.1+
>> http://mindprod.com/products1.html#COMMON11
>>
>> The method is called StringTools.rep
>>
>> /**
>> * Produce a String of a given repeating character.
>> *
>> * @param c the character to repeat
>> * @param count the number of times to repeat
>> *
>> * @return String, e.g. rep('*',4) returns "****"
>> * @noinspection WeakerAccess,SameParameterValue
>> */
>> public static String rep( char c, int count )
>> {
>> if ( c == ' '&& count<= SOMESPACES.length() )
>> {
>> return SOMESPACES.substring( 0, count );
>> }
>> char[] s = new char[count];
>> for ( int i = 0; i< count; i++ )
>> {
>> s[ i ] = c;
>> }
>> return new String( s ).intern();
>> }
>>
>> /**
>> * used to efficiently generate Strings of spaces of varying
>> length
>> */
>> private static final String SOMESPACES = " ";
>
> Why use intern() on the second case? It's has always been undocumented
> where the pool storage is and what the cost of using it is. The only
> time I use that method is when generating keys for a Properties class.
Why even use it there? I don't think I've ever seen a legitimate case
for using intern(). The *closest* I've seen to a valid use is someone
wanted to use it for synchronization based on a String key.

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: Kevin McMurtrie on
In article <axp%n.70738$Lj2.7209(a)newsfe05.iad>,
Daniel Pitts <newsgroup.spamfilter(a)virtualinfinity.net> wrote:

> On 7/14/2010 9:42 AM, Kevin McMurtrie wrote:
> > In article<sbnr36ta3l2bqkf0mt23pgg6g3k8nf2ud2(a)4ax.com>,
> > Roedy Green<see_website(a)mindprod.com.invalid> wrote:
> >
> >> On 13 Jul 2010 15:01:35 GMT, Andreas Leitgeb
> >> <avl(a)gamma.logic.tuwien.ac.at> wrote, quoted or indirectly quoted
> >> someone who said :
> >>
> >>> It seems so basic that I can't believe such a feature wasn't in
> >>> the standard library:
> >>
> >> it is part of the common11 tools for JDK 1.1+
> >> http://mindprod.com/products1.html#COMMON11
> >>
> >> The method is called StringTools.rep
> >>
> >> /**
> >> * Produce a String of a given repeating character.
> >> *
> >> * @param c the character to repeat
> >> * @param count the number of times to repeat
> >> *
> >> * @return String, e.g. rep('*',4) returns "****"
> >> * @noinspection WeakerAccess,SameParameterValue
> >> */
> >> public static String rep( char c, int count )
> >> {
> >> if ( c == ' '&& count<= SOMESPACES.length() )
> >> {
> >> return SOMESPACES.substring( 0, count );
> >> }
> >> char[] s = new char[count];
> >> for ( int i = 0; i< count; i++ )
> >> {
> >> s[ i ] = c;
> >> }
> >> return new String( s ).intern();
> >> }
> >>
> >> /**
> >> * used to efficiently generate Strings of spaces of varying
> >> length
> >> */
> >> private static final String SOMESPACES = " ";
> >
> > Why use intern() on the second case? It's has always been undocumented
> > where the pool storage is and what the cost of using it is. The only
> > time I use that method is when generating keys for a Properties class.
> Why even use it there? I don't think I've ever seen a legitimate case
> for using intern(). The *closest* I've seen to a valid use is someone
> wanted to use it for synchronization based on a String key.

Sample code:

import java.io.IOException;
import java.io.StringReader;
import java.util.Map;
import java.util.Properties;

public class Foo
{
private static void runLookupTest (final Properties p)
{
int c= 0;
for (int i= 0; i < 10000000; ++i)
{
c+= (p.get("org.company.services.WidgetFactory.implementor") != null) ? 1 : 0;
c+= (p.get("com.company.util.Scheduler.useTimer") != null) ? 1 : 0;
c+= (p.get("com.company.imaging.ThumbRender.filter") != null) ? 1 : 0;
}
if (c != 30000000)
throw new RuntimeException ("Bad test: " + c);
}

private static void runTestCycle (boolean warmup) throws IOException
{
//Create Properties with string keys that are not internalized
final Properties p= new Properties();
p.load(new StringReader( "org.company.services.WidgetFactory.implementor=1000\n"
+ "com.company.util.Scheduler.useTimer=true\n"
+ "com.company.imaging.ThumbRender.filter=lanczos3\n"));

//Internalized lookup of non-internalized keys
final long start1= System.nanoTime();
runLookupTest(p);
final long end1= System.nanoTime();

//Run keys through String.intern()
final Properties temp= (Properties)p.clone();
p.clear(); //put() doesn't overwrite an existing key
for (Map.Entry<Object, Object> e : temp.entrySet())
p.put(String.valueOf(e.getKey()).intern(), e.getValue());

//Internalized lookup of internalized keys
final long start2= System.nanoTime();
runLookupTest(p);
final long end2= System.nanoTime();

if (warmup)
{
System.out.println("Warmup");
}
else
{
System.out.println("Not internalized: "
+ (end1 - start1)/1000000f + " ms");
System.out.println("Internalized: "
+ (end2 - start2)/1000000f + " ms");
}
System.out.println();
}

public static void main (final String args[]) throws Exception
{
runTestCycle(true);
runTestCycle(false);
runTestCycle(false);
runTestCycle(false);
}
}



==============================================
Warmup

Not internalized: 1725.81 ms
Internalized: 794.556 ms

Not internalized: 1725.5449 ms
Internalized: 795.296 ms

Not internalized: 1725.703 ms
Internalized: 794.618 ms
--
I won't see Google Groups replies because I must filter them as spam
From: Daniel Pitts on
On 7/15/2010 12:43 AM, Kevin McMurtrie wrote:
> In article<axp%n.70738$Lj2.7209(a)newsfe05.iad>,
> Daniel Pitts<newsgroup.spamfilter(a)virtualinfinity.net> wrote:
>
>> On 7/14/2010 9:42 AM, Kevin McMurtrie wrote:
>>> In article<sbnr36ta3l2bqkf0mt23pgg6g3k8nf2ud2(a)4ax.com>,
>>> Roedy Green<see_website(a)mindprod.com.invalid> wrote:
>>>
>>>> On 13 Jul 2010 15:01:35 GMT, Andreas Leitgeb
>>>> <avl(a)gamma.logic.tuwien.ac.at> wrote, quoted or indirectly quoted
>>>> someone who said :
>>>>
>>>>> It seems so basic that I can't believe such a feature wasn't in
>>>>> the standard library:
>>>>
>>>> it is part of the common11 tools for JDK 1.1+
>>>> http://mindprod.com/products1.html#COMMON11
>>>>
>>>> The method is called StringTools.rep
>>>>
>>>> /**
>>>> * Produce a String of a given repeating character.
>>>> *
>>>> * @param c the character to repeat
>>>> * @param count the number of times to repeat
>>>> *
>>>> * @return String, e.g. rep('*',4) returns "****"
>>>> * @noinspection WeakerAccess,SameParameterValue
>>>> */
>>>> public static String rep( char c, int count )
>>>> {
>>>> if ( c == ' '&& count<= SOMESPACES.length() )
>>>> {
>>>> return SOMESPACES.substring( 0, count );
>>>> }
>>>> char[] s = new char[count];
>>>> for ( int i = 0; i< count; i++ )
>>>> {
>>>> s[ i ] = c;
>>>> }
>>>> return new String( s ).intern();
>>>> }
>>>>
>>>> /**
>>>> * used to efficiently generate Strings of spaces of varying
>>>> length
>>>> */
>>>> private static final String SOMESPACES = " ";
>>>
>>> Why use intern() on the second case? It's has always been undocumented
>>> where the pool storage is and what the cost of using it is. The only
>>> time I use that method is when generating keys for a Properties class.
>> Why even use it there? I don't think I've ever seen a legitimate case
>> for using intern(). The *closest* I've seen to a valid use is someone
>> wanted to use it for synchronization based on a String key.
>
> Sample code:
>
> import java.io.IOException;
> import java.io.StringReader;
> import java.util.Map;
> import java.util.Properties;
>
> public class Foo
> {
> private static void runLookupTest (final Properties p)
> {
> int c= 0;
> for (int i= 0; i< 10000000; ++i)
> {
> c+= (p.get("org.company.services.WidgetFactory.implementor") != null) ? 1 : 0;
> c+= (p.get("com.company.util.Scheduler.useTimer") != null) ? 1 : 0;
> c+= (p.get("com.company.imaging.ThumbRender.filter") != null) ? 1 : 0;
> }
> if (c != 30000000)
> throw new RuntimeException ("Bad test: " + c);
> }
>
> private static void runTestCycle (boolean warmup) throws IOException
> {
> //Create Properties with string keys that are not internalized
> final Properties p= new Properties();
> p.load(new StringReader( "org.company.services.WidgetFactory.implementor=1000\n"
> + "com.company.util.Scheduler.useTimer=true\n"
> + "com.company.imaging.ThumbRender.filter=lanczos3\n"));
>
> //Internalized lookup of non-internalized keys
> final long start1= System.nanoTime();
> runLookupTest(p);
> final long end1= System.nanoTime();
>
> //Run keys through String.intern()
> final Properties temp= (Properties)p.clone();
> p.clear(); //put() doesn't overwrite an existing key
> for (Map.Entry<Object, Object> e : temp.entrySet())
> p.put(String.valueOf(e.getKey()).intern(), e.getValue());
>
> //Internalized lookup of internalized keys
> final long start2= System.nanoTime();
> runLookupTest(p);
> final long end2= System.nanoTime();
>
> if (warmup)
> {
> System.out.println("Warmup");
> }
> else
> {
> System.out.println("Not internalized: "
> + (end1 - start1)/1000000f + " ms");
> System.out.println("Internalized: "
> + (end2 - start2)/1000000f + " ms");
> }
> System.out.println();
> }
>
> public static void main (final String args[]) throws Exception
> {
> runTestCycle(true);
> runTestCycle(false);
> runTestCycle(false);
> runTestCycle(false);
> }
> }
>
>
>
> ==============================================
> Warmup
>
> Not internalized: 1725.81 ms
> Internalized: 794.556 ms
>
> Not internalized: 1725.5449 ms
> Internalized: 795.296 ms
>
> Not internalized: 1725.703 ms
> Internalized: 794.618 ms
So you save 1 second reading 10 million properties, when a program
probably reads fewer than 1000 properties. So, during the executions of
the program, you have saved some nanoseconds. Good for you.

--
Daniel Pitts' Tech Blog: <http://virtualinfinity.net/wordpress/>
From: markspace on
Roedy Green wrote:
>
> The question was which was faster. Kevin did a test and discovered
> intern was 54% faster,


But Daniel is still correct. What Kevin produced was a micro-benchmark,
not a full app. Optimize to the actual app, not to some idealized
version of a small part of it.
From: Kevin McMurtrie on
In article <i1oeug$ofv$1(a)news.eternal-september.org>,
markspace <nospam(a)nowhere.com> wrote:

> Roedy Green wrote:
> >
> > The question was which was faster. Kevin did a test and discovered
> > intern was 54% faster,
>
>
> But Daniel is still correct. What Kevin produced was a micro-benchmark,
> not a full app. Optimize to the actual app, not to some idealized
> version of a small part of it.

Wow, so much analysis of me and not the code! Somebody could have fired
up an IDE and figured it out in less than a minute. The code simply
demonstrates taking advantage of an optimized path in the Sun Map
implementations.

Properties loaded from a file or a stream have keys that are not
internalized. This is the common code path when calling get("Some
constant"):

String.hashCode ()
Indexed array read
hash comparison
object reference comparison
String.equals()


Rebuild the Properties with internalized keys. The common code path is
reduced to this:

String.hashCode ()
Indexed array read
hash comparison
object reference comparison

Most calls to String.equals() are eliminated because of reference
equality.

This works for all Sun Map classes but Properties are where the usage
conditions are most likely to make it work. Internalizing strings in
general is not productive.
--
I won't see Google Groups replies because I must filter them as spam