Re: debug output problem in ObjectInputStream

2002-04-02 Thread Bryce McKinlay

Per Bothner wrote:

> Having dumpElement[ln] as separate
> methods has the advantage that it could over overridden, but
> it seems like poinles generality.  So if we want to keep the
> debugging printout, I suggest:
>
>   if (Configuration.DEBUG && dump)
> for (int i=0, len=Array.getLength(array); i < len; i++)
>   System.out.println("  ELEMENT[" + i + "]=" + Array.get(array, i));
>
> This makes it possible for a compiler to do the optimization to
> multiple print calls that my patch does. 


I was originally hoping that the dumpElement() methods would get inlined 
and the compiler would figure out that the code could be removed, but 
you're right in that even if inlining worked properly the arguments 
would still have to be evaluated unless it could also figure out that 
the StringBuffer methods etc had no side-effects.

I agree that we should put the "if (Configuration.DEBUG ..." at the call 
site to fix this. However, fixing this doesn't really help our extremely 
crap serialization performance. eg the attached test runs more than 45X 
slower with GCJ than JDK 1.4! Serialization needs some work...

regards

Bryce.



import java.util.*;
import java.io.*;

public class SerTest3
{
  static void showUsage()
  {
System.err.println("Usage: SerTest3 ");
System.exit(1);  
  }
  
  public static void main(String[] args) 
throws IOException, FileNotFoundException, ClassNotFoundException
  {
if (args.length == 0)
  showUsage();

HashMap hm = null;
long start = System.currentTimeMillis();

if (args[0].equals("write"))
  {
hm = makeHugeHashMap();
System.out.println ("map created, writing it out...");
ObjectOutputStream out = 
  new ObjectOutputStream(new FileOutputStream("test.ser"));

out.writeObject(hm);
out.close();
  }
else if (args[0].equals("read"))
  {  
ObjectInputStream in = 
  new ObjectInputStream(new FileInputStream("test.ser"));

hm = (HashMap) in.readObject();
  }
else
  showUsage();
  
System.out.println(hm.hashCode());
System.out.println(System.currentTimeMillis() - start + "ms elapsed.");
  }
  
  static HashMap makeHugeHashMap()
  {
HashMap hm = new HashMap();
for (int i=0; i < 200; i++)
{
  ArrayList al = new ArrayList();
  for (int j=0; j < 1000; j++)
  {
al.add (Integer.toString(i - j));
  }
  Integer integer = new Integer(i);
  hm.put(integer, al);
}
return hm;
  }
}



Re: debug output problem in ObjectInputStream

2002-04-02 Thread Tom Tromey

> "Per" == Per Bothner <[EMAIL PROTECTED]> writes:

Per> So if we want to keep the debugging printout, I suggest:

Per>if (Configuration.DEBUG && dump)
Per>  for (int i=0, len=Array.getLength(array); i < len; i++)
Per>System.out.println("  ELEMENT[" + i + "]=" + Array.get(array, i));

As I recall, Warren wrote all the debugging code.  He's probably in
the best position to say how useful it really is.  I've CC'd him.
(Warren, I'll forward you Per's note separately.)

Tom

___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath



debug output problem in ObjectInputStream

2002-04-02 Thread Per Bothner

(This problem was reported to me by L. Peter Deutsch.)

The class java/io/ObjectInputStream.java contains a lot
of calls to dumpElement and dumpElementln, which prints
the argument is debugging is enabled. By default the
DEBUG flag is false, so debugging is disabled.  Ideally
a compiler will be able to inline and eliminate the
calls to dumpElement[ln].

The problem is that the argument to dumpElement[ln] is
still evaluated, even when DEBUG is false.  In many cases
these arguments are non-trivial string concatenation expressions,
so we will get a temporary StringBuffer allocated, appended
to and thrown away.  A smart compiler might be able to
figure out that the result of the concatenation is unused,
and so avoid it.  Even worse though is that it calls
toString for each element of an array (and also for exceptions).
Since toString of an unknown class can do anything, the
compiler can't eliminate the call to toString.  It is even
possible that toString for a large (or cyclic) data structure
could do a large(or even an infinite) amount of work.

I've appended one fix, but I'm not sure what the best approach is.
The simplest would be to just rip out all the dumpElement code.
Next simplest is to move all the Configuration.DEBUG && dump
tests out of dumpElement[ln] and to the call sites.  One could
even do what my patches does, and convert the string concatenations
to multiple print calls.  Having dumpElement[ln] as separate
methods has the advantage that it could over overridden, but
it seems like poinles generality.  So if we want to keep the
debugging printout, I suggest:

   if (Configuration.DEBUG && dump)
 for (int i=0, len=Array.getLength(array); i < len; i++)
   System.out.println("  ELEMENT[" + i + "]=" + Array.get(array, i));

This makes it possible for a compiler to do the optimization to
multiple print calls that my patch does.

Alteratively, I suggest just removing all the dumpElement calls.
-- 
--Per Bothner
[EMAIL PROTECTED]   http://www.bothner.com/per/


Index: ObjectInputStream.java
===
RCS file: /cvs/gcc/gcc/libjava/java/io/ObjectInputStream.java,v
retrieving revision 1.11
diff -u -r1.11 ObjectInputStream.java
--- ObjectInputStream.java  2002/01/22 22:40:14 1.11
+++ ObjectInputStream.java  2002/04/02 20:45:49
@@ -243,8 +243,16 @@
Object array = Array.newInstance (componentType, length);
int handle = assignNewHandle (array);
readArrayElements (array, componentType);
-   for (int i=0, len=Array.getLength(array); i < len; i++)
- dumpElementln ("  ELEMENT[" + i + "]=" + Array.get(array, i).toString());
+   if (Configuration.DEBUG && dump)
+ {
+   for (int i=0, len=Array.getLength(array); i < len; i++)
+ {
+   System.out.print("  ELEMENT[");
+   System.out.print(i);
+   System.out.print("]=");
+   System.out.println(Array.get(array, i));
+ }
+ }
ret_val = processResolution (array, handle);
break;
   }



Re: [Kissme-general] SystemClassLoader fix

2002-04-02 Thread Eric Blake

John Leuner wrote:
> 
> > I cleaned your patch up a bit, and once I get it to compile, I'm
> > committing it. Thanks for the catch - I documented that the class
> > specified by java.system.class.loader must now have a constructor which
> > accepts a parent class loader.
> 
> It wasn't really a patch, just a demonstration of the problem.
> 
> Any reason why it wouldn't compile?

Yes - the patch as it appeared in my reply to your email was hastily
written and untested (ie. I wrote the patch and replied to your email
before starting the time-consuming compilation and regression testing
process).  I think the only change I had to make before committing it,
however, was adding an import statement.  And it has been in CVS for
nearly a week now.

-- 
This signature intentionally left boring.

Eric Blake [EMAIL PROTECTED]
  BYU student, free software programmer

___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath



Re: [Kissme-general] SystemClassLoader fix

2002-04-02 Thread John Leuner

> I cleaned your patch up a bit, and once I get it to compile, I'm
> committing it. Thanks for the catch - I documented that the class
> specified by java.system.class.loader must now have a constructor which
> accepts a parent class loader.

It wasn't really a patch, just a demonstration of the problem. 

Any reason why it wouldn't compile?

John Leuner


> John Leuner wrote:
> > 
> > I tracked this down to the ClassLoader class.
> > 
> > 
> > Otherwise getSystemClassLoader gets in an infinite loop where the Constructor for 
>SystemClassLoader calls the ClassLoader() constructor which tries to use the system 
>class loader as the parent classloader and round and round it goes ...
> > 
> > John Leuner
> > 
> 
> 2002-03-28  John Leuner  <[EMAIL PROTECTED]>
> 
>   * java/lang/ClassLoader.java (getSystemClassLoader): Break
>   infinite loop by specifying parent classloader.
>   * gnu/java/lang/SystemClassLoader.java (SystemClassLoader): Add
>   proper constructor.
> 
> -- 
> This signature intentionally left boring.
> 
> Eric Blake [EMAIL PROTECTED]
>   BYU student, free software programmer
> Index: gnu/java/lang/SystemClassLoader.java
> ===
> RCS file: /cvsroot/classpath/classpath/gnu/java/lang/SystemClassLoader.java,v
> retrieving revision 1.1
> diff -u -r1.1 SystemClassLoader.java
> --- gnu/java/lang/SystemClassLoader.java  22 Mar 2002 21:25:20 -  1.1
> +++ gnu/java/lang/SystemClassLoader.java  28 Mar 2002 21:36:04 -
> @@ -64,6 +64,17 @@
>  
>/** Flag to avoid infinite loops. */
>private static boolean is_trying;
> +
> +  /**
> +   * Creates a class loader. Note that the parent may be null, when this is
> +   * created as the system class loader by ClassLoader.getSystemClassLoader.
> +   *
> +   * @param parent the parent class loader
> +   */
> +  public SystemClassLoader(ClassLoader parent)
> +  {
> +super(parent);
> +  }
>  
>/**
> * Get the URL to a resource.
> Index: java/lang/ClassLoader.java
> ===
> RCS file: /cvsroot/classpath/classpath/java/lang/ClassLoader.java,v
> retrieving revision 1.16
> diff -u -r1.16 ClassLoader.java
> --- java/lang/ClassLoader.java22 Mar 2002 21:25:20 -  1.16
> +++ java/lang/ClassLoader.java28 Mar 2002 21:36:05 -
> @@ -48,6 +48,7 @@
>  import java.util.Enumeration;
>  import java.util.HashMap;
>  import java.util.Map;
> +import gnu.java.lang.SystemClassLoader;
>  import gnu.java.util.DoubleEnumeration;
>  import gnu.java.util.EmptyEnumeration;
>  
> @@ -685,7 +686,8 @@
> * property java.class.path. This is set as the context
> * class loader for a thread. The system property
> * java.system.class.loader, if defined, is taken to be the
> -   * name of the class to use as the system class loader, otherwise this
> +   * name of the class to use as the system class loader, which must have
> +   * a public constructor which takes a ClassLoader as a parent; otherwise this
> * uses gnu.java.lang.SystemClassLoader.
> *
> * Note that this is different from the bootstrap classloader that
> @@ -713,12 +715,28 @@
> "gnu.java.lang.SystemClassLoader");
>  try
>{
> -return (ClassLoader) Class.forName(loader).newInstance();
> +// Give the new system class loader a null parent.
> +Constructor c = Class.forName(loader).getConstructor
> +  ( new Class[] { ClassLoader.class } );
> +return (ClassLoader) c.newInstance(new Object[1]);
>}
>  catch (Exception e)
>{
> -throw (Error) new InternalError
> -  ("System class loader could not be found: " + e).initCause(e);
> +try
> +  {
> +System.err.println("Requested system classloader "
> +   + loader + " failed, trying "
> +   + "gnu.java.lang.SystemClassLoader");
> +e.printStackTrace();
> +// Fallback to gnu.java.lang.SystemClassLoader.
> +return new SystemClassLoader(null);
> +  }
> +catch (Exception e1)
> +  {
> +throw (Error) new InternalError
> +  ("System class loader could not be found: " + e)
> +  .initCause(e);
> +  }
>}
>}
>  // Check if we may return the system classloader


___
Classpath mailing list
[EMAIL PROTECTED]
http://mail.gnu.org/mailman/listinfo/classpath