Ulf, this is a simple benchmark test case I was using for the singlebyte
stuff, you
can benchmark lots of things with simple tweak. It's a simple version
from Martin's
more complicated/sophisticated benchmark.
Sherman
Ulf Zibis wrote:
one more question, just for interest:
Can you see any performance difference between
sp != sl
and
sp < sl
?
-Ulf
Am 15.12.2008 23:19, Xueming Shen schrieb:
The gain from doing
int sr = src.remaining();
int dr = dst.remaining();
Ulf, thanks for looking into the changes.
It might not be a good idea to skip the temporary variable c in the
loop, I'm not sure
it's a good idea to put an "un-mappable" char into the output buffer
in case we have
a un-mappable though yes we don't not change the buffer position.
This actually is
all most all the gain come from in -server vm case when I run my
benchmark.
However in "client" vm case, interestingly I do see some performance
gain with
your proposed change, though I'm not sure why the loop gets faster
with a quick
look. So I have created a new Cr #6785335 to keep trace this issue.
Will consider
put this one into 7 later.
Thanks again!
Sherman
Ulf Zibis wrote:
Maybe:
for (int sl = sp + (sr <= dr ? sr : dr); sp != sl; sp++, dp++)
is little more faster than:
for (int sl = sp + (sr <= dr ? sr : dr); sp < sl; sp++, dp++)
-Ulf
Am 15.12.2008 21:56, Ulf Zibis schrieb:
Maybe little faster, especially for short strings:
private CoderResult decodeArrayLoop(ByteBuffer src,
CharBuffer dst) {
byte[] sa = src.array();
int sp = src.arrayOffset() + src.position();
int sr = src.remaining(); // faster than ...
src.arrayOffset() + src.limit()
char[] da = dst.array();
int dp = dst.arrayOffset() + dst.position();
int dr = dst.remaining(); // dl is never used
for (int sl = sp + (sr <= dr ? sr : dr); sp < sl; sp++,
dp++)
if ((da[dp] = decode(sa[sp])) == UNMAPPABLE_DECODING)
return
withResult(CoderResult.unmappableForLength(1), src, sp, dst, dp);
return withResult(sr <= dr ? CoderResult.UNDERFLOW :
CoderResult.OVERFLOW, src, sp, dst, dp);
}
Regards,
Ulf
/*
* Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
import java.util.*;
import java.nio.*;
import java.nio.charset.*;
import java.util.concurrent.*;
import java.util.regex.Pattern;
/**
* Usage: java StringCodingMicroBenchmark
* [-Diterations=N] [-Dsize=N] [-Dsubsize=N] [-Dmaxchar=N]
* [-Dfilter=REGEXP] [-DSecurityManager=true]
* [-Dverbose=true]
*/
public class NIOCodingMicroBenchmark {
public static class Job {
final String name;
final int itr;
final byte[] bb;
final char[] cc;
final Charset cs;
final boolean useDirect;
final boolean testDecode;
final ByteBuffer BBF;
final CharBuffer CBF;
final ByteBuffer BBF_D;
final CharBuffer CBF_D;
Job(String name, String csn, boolean testDecode, boolean useDirect,
int itr, byte[] bb, char[] cc)
{
this.cs = Charset.forName(csn);
this.testDecode = testDecode;
this.useDirect = useDirect;
this.itr = itr;
this.bb = bb;
this.cc = cc;
this.name = name + (useDirect?" (direct)":" ") + csn + " :";
this.BBF = ByteBuffer.allocate(bb.length);
this.CBF = CharBuffer.allocate(bb.length);
this.BBF_D = ByteBuffer.allocateDirect(bb.length);
this.CBF_D = ByteBuffer.allocateDirect(cc.length*2).asCharBuffer();
}
public String name() { return name; }
public void work() throws Throwable {
if (testDecode)
decode();
else
encode();
}
void decode() throws Throwable {
ByteBuffer bbf;
CharBuffer cbf;
if (useDirect) {
bbf = BBF_D;
cbf = CBF_D;
bbf.clear();
bbf.put(bb).rewind();
} else {
bbf = ByteBuffer.wrap(bb);
cbf = CBF;
}
CharsetDecoder dec = cs.newDecoder();
for (int i = 0; i < itr; i++) {
dec.reset();
bbf.rewind();
cbf.clear();
dec.decode(bbf, cbf, true);
}
}
void encode() throws Throwable {
ByteBuffer bbf;
CharBuffer cbf;
if (useDirect) {
bbf = BBF_D;
cbf = CBF_D;
cbf.clear();
cbf.put(cc).rewind();
} else {
bbf = BBF;
cbf = CharBuffer.wrap(cc);
}
CharsetEncoder enc = cs.newEncoder();
for (int i = 0; i < itr; i++) {
cbf.rewind();
bbf.clear();
enc.reset();
enc.encode(cbf, bbf, true);
}
}
}
private static void collectAllGarbage() {
final java.util.concurrent.CountDownLatch drained
= new java.util.concurrent.CountDownLatch(1);
try {
System.gc(); // enqueue finalizable objects
new Object() { protected void finalize() {
drained.countDown(); }};
System.gc(); // enqueue detector
drained.await(); // wait for finalizer queue to drain
System.gc(); // cleanup finalized objects
} catch (InterruptedException e) { throw new Error(e); }
}
/**
* Runs each job for long enough that all the runtime compilers
* have had plenty of time to warm up, i.e. get around to
* compiling everything worth compiling.
* Returns array of average times per job per run.
*/
public static long[] time0(Job ... jobs) throws Throwable {
//final long warmupNanos = 10L * 1000L * 1000L * 1000L;
final long warmupNanos = 100L * 100L;
long[] nanoss = new long[jobs.length];
for (int i = 0; i < jobs.length; i++) {
collectAllGarbage();
long t0 = System.nanoTime();
long t;
int j = 0;
do { jobs[i].work(); j++; }
while ((t = System.nanoTime() - t0) < warmupNanos);
nanoss[i] = t/j;
}
return nanoss;
}
public static void time(Job ... jobs) throws Throwable {
long[] warmup = time0(jobs); // Warm up run
long[] nanoss = time0(jobs); // Real timing run
long[] milliss = new long[jobs.length];
double[] ratios = new double[jobs.length];
final String nameHeader = "Method";
final String millisHeader = "Millis";
final String ratioHeader = "Ratio";
int nameWidth = nameHeader.length();
int millisWidth = millisHeader.length();
int ratioWidth = ratioHeader.length();
for (int i = 0; i < jobs.length; i++) {
nameWidth = Math.max(nameWidth, jobs[i].name().length());
milliss[i] = nanoss[i]/(1000L * 1000L);
millisWidth = Math.max(millisWidth,
String.format("%d", milliss[i]).length());
ratios[i] = (double) nanoss[i] / (double) nanoss[0];
ratioWidth = Math.max(ratioWidth,
String.format("%.3f", ratios[i]).length());
}
String format = String.format("%%-%ds %%%dd %%%d.3f%%n",
nameWidth, millisWidth, ratioWidth);
String headerFormat = String.format("%%-%ds %%%ds %%%ds%%n",
nameWidth, millisWidth, ratioWidth);
System.out.printf(headerFormat, "Method", "Millis", "Ratio");
// Print out absolute and relative times, calibrated against first job
for (int i = 0; i < jobs.length; i++)
System.out.printf(format, jobs[i].name(), milliss[i], ratios[i]);
}
public static Job[] filter(Pattern filter, Job[] jobs) {
if (filter == null) return jobs;
Job[] newJobs = new Job[jobs.length];
int n = 0;
for (Job job : jobs)
if (filter.matcher(job.name()).find())
newJobs[n++] = job;
// Arrays.copyOf not available in JDK 5
Job[] ret = new Job[n];
System.arraycopy(newJobs, 0, ret, 0, n);
return ret;
}
public static void main(String[] args) throws Throwable {
final int itrs = Integer.getInteger("iterations", 10000);
final int size = Integer.getInteger("size", 1024 * 8 );
final String regex = System.getProperty("filter");
final Pattern filter = (regex == null) ? null : Pattern.compile(regex);
char cp = 0;
char[] cc = new char[size];
for (int i = 0; i < size; i++) {
if (cp == 0x80)
cp = 0;
cc[i] = cp++;
}
byte[] bb = new String(cc).getBytes("cp1252");
System.out.println("**********************************************************");
String[] csns = new String[] { "cp1252" };
for (String csn: csns) {
Job[] jobs = {
//----------------------------------------------------------------
new Job("Decoding 1b", csn, true, false, itrs, bb, cc),
new Job("Decoding 1b", csn, true, true, itrs, bb, cc),
new Job("Encoding 1b", csn, false, false, itrs, bb, cc),
new Job("Encoding 1b", csn, false, true, itrs, bb, cc),
};
System.out.printf(" ------------------%s-----------------------------%n", csn);
time(filter(filter, jobs));
}
}
}