Martin, Sherman, Dalibor,

I'm proud to present a new patch, which could dramatically improve the memory-footprint and instantiation performance of charsets usage, so Charset instances could directly be hold in cache.
The footprint of the code is again little smaller than before.

Provided patch fixes:
6862158 Make sun.nio.cs.* charset objects light-weight
6850361 Avoid 2-step lookup in sun.nio.cs charset providers
6790402 Speed-up FastCharsetProvider
6795536 No system start for file.encoding=x-SJIS_0213
6792535 NoClassDefFoundError after failed new StreamEncoder(out, lock, Charset.defaultCh
6850337 Hasher.java interprets given option value badly
6853677 Provide names of supported charsets -> now superfluous

Do you like to review and/or sponsor my CR ?

See:
https://bugs.openjdk.java.net/show_bug.cgi?id=100098

As the code of the new FastCharset is so tiny and flexible, I paste it here directly... Using it's De/Encoders in general would make interfaces ArrayDecoder ad ArrayEncoder superfluous. For charsets with huge mappings it is foreseen to split class Mapping for decoders and encoders.

Thanks,

Ulf



package sun.nio.cs;

import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.UnsupportedCharsetException;

class FastCharset extends Charset implements HistoricallyNamedCharset {

   private final String pkgName;
final String mappingClsName; // package private for ExternalCharsetProvider
   private transient Decoder decoder;
   private transient Encoder encoder;

   FastCharset(String className, String canonicalName, String... aliases) {
       super(canonicalName, aliases);
       pkgName = getClass().getPackage().getName();
       mappingClsName = className;
   }
FastCharset(String packageName, String className, String canonicalName, String[] aliases) {
       super(canonicalName, aliases);
       pkgName = packageName;
       mappingClsName = className;
   }

   public String historicalName() {
       return mapping().historicalName;
   }

   public boolean contains(Charset cs) {
       return cs.name().equals(name()) ||
               mapping().isASCII && cs.name().equals("US-ASCII");
   }

   public Decoder newDecoder() {
       return decoder().clone();
   }

   public Encoder newEncoder() {
       if (encoder == null)
           encoder = decoder().newEncoder();
       return encoder.clone();
   }

   private final Decoder decoder() {
       if (decoder == null)
           decoder = mapping().newDecoder(this);
       return decoder;
   }

   final Mapping mapping() {
       try {
           return ((Class<Mapping>) Class.forName(
               pkgName+'.'+mappingClsName)).newInstance();
       } catch (ClassNotFoundException ex) {
           throw new NoClassDefFoundError(ex.getMessage());
       } catch (ReflectiveOperationException ex) {
Error error = new InternalError("Can't instantiate class ["+pkgName+'.'+mappingClsName+"]");
           error.initCause(ex);
           throw error;
       }
   }


   static abstract class Decoder<M extends Mapping>
           extends CharsetDecoder implements Cloneable, ArrayDecoder {

       M mapping;

       Decoder(FastCharset cs, M mapping,
               float averageCharsPerByte, float maxCharsPerByte) {
           super(cs, 1.0f, 1.0f);
           this.mapping = mapping;
       }

       protected Decoder<M> clone() {
           try {
               return (Decoder<M>)super.clone();
           } catch (CloneNotSupportedException ex) {
               return null;
           }
       }

       Encoder<M> newEncoder() {
           return mapping.newEncoder(this);
       }
   }


   static abstract class Encoder<M extends Mapping>
           extends CharsetEncoder implements Cloneable, ArrayEncoder {

       M mapping;

       Encoder(Decoder<M> decoder,
                  float averageBytesPerChar, float maxBytesPerChar) {
           super(decoder.charset(), 1.0f, 1.0f);
           mapping = decoder.mapping;
           mapping.initEncoderMaps();
       }

       protected Encoder<M> clone() {
           try {
               return (Encoder<M>)super.clone();
           } catch (CloneNotSupportedException ex) {
               return null;
           }
       }
   }
}


Reply via email to