马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
你通过从书的数量和开发周期及运行速度来证明:net网页编程和ruby要比java简单。String对我们来讲太熟习了,由于它无处不在,更由于用String能够形貌这个天下几近一切的工具,乃至于为了形貌准确的数值都必要String出马(由于盘算机眼中的二进制和人类眼中的十进制间总有那末点隔阂)。由于熟习而变得复杂,也简单被疏忽。明天纪录一下关于String的简单被疏忽的两个成绩。
由于字符串太多,假如可以重用则可以节俭很年夜的内存。起首看上面一个例子:
Stringstring1=“HELLOHELLO”;
Stringstring2=“HELLO”+“HELLO”;
下面创立了几个字符串?1or2?后者是静态创立的,不外信任JVM能够对其间接优化的,由于编译时已晓得内容了,推测是一个instance,即统一个char数组。Heapdump出来后察看公然是一个。
Stringstring3=args[0]+args[1];
输出参数HELLO HELLO? 字符串酿成几个?没错啊,是两个HELLOHELLO了。Dumpheap后察看,公然是两个了。(实在不必dumphealp,debug也能够看出来,string1和string3中的char[]指向地点是纷歧样的)。
依此延长,能够而知由java反序列化而来的那些string也是纷歧样的。实比方下;
publicfinalstaticvoidmain(String[]args)throwsException{
newStringDeserialized().testDescirialized();
}
publicvoidtestDescirialized()throwsException{
StringtestString=“HELLOHELLO”;
ObjectOutputStreamdataOutStream=newObjectOutputStream(newFileOutputStream(“./stringdeserialized.data”));
for(inti=0;i<1000;i++)
dataOutStream.writeObject(testString);
dataOutStream.close();
List<String>readAgainList=newArrayList<String>(100);
for(inti=0;i<100;i++){
ObjectInputStreamdataInputStream=newObjectInputStream(newFileInputStream(“./stringdeserialized.data”));
readAgainList.add((String)dataInputStream.readObject());
dataInputStream.close();
}
Thread.sleep(Integer.MAX_VALUE);
}
<br>
截图是heapdump出来的,有HELLOHELLO的个数有101个,占用的size>8080。关于JVM的内存利用可参考http://www.javamex.com/tutorials/memory/object_memory_usage.shtml
成绩来了,体系保护的数据年夜多是字符串信息,好比configserver,而良多的信息都是统一个字符串,那末重复的从收集序列化而来,占用多的Heap。固然本人能够写一个weakhashmap来保护,重用这些字符串。人人晓得JVM中有StringPool,利用它无疑最好不外。查找String源码,发明intern()的正文以下:
*Whentheinternmethodisinvoked,ifthepoolalreadycontainsa
*stringequaltothis<code>String</code>objectasdeterminedby
*the{@link#equals(Object)}method,thenthestringfromthepoolis
*returned.Otherwise,this<code>String</code>objectisaddedtothe
*poolandareferencetothis<code>String</code>objectisreturned.
因而改动下面一行代码为:
readAgainList.add(((String)dataInputStream.readObject()).intern());
再次Heapdump剖析以下,别的能够看出一个包括10个字符的String占用的Heap是80byte:
<br>
今朝CS处置为了撑持所谓的恣意范例数据,CS接纳了一个技能,用Swizzle来保留java序列化后的byte范例,Server端无需反序列化就可以保留恣意范例的data;如许的害处有两个:通用的Java序列化效力不高;协定欠亨用,对其他言语撑持不可。由于今朝的数据信息基础都是String范例,而对对String数据的专门处置,能够经由过程String外部的byte数组(UTF-8)类暗示,如许也便于其他言语剖析。能够思索增添对publish(String)的撑持。因而做了以下测试来对照对String分歧serialize/deserialize的速度和巨细。
了局是writeUTF最小最快,关于100char的String,差异是数目级的相称分明,固然Swizzle利用了一个技能,当对统一个swizzleinstance屡次传输时,无需反复的序列化。
PS:Swizzle复杂的说就是把信息包装起来,然后把序列化的byte流缓存起来,如许假如一样的一个信息要推送/发送N次,就能干削减N-1次的序列化工夫。
publicclassCompareSerialization{
publicStringgenerateTestData(intstringLength){
Randomrandom=newRandom();
StringBuilderbuilder=newStringBuilder(stringLength);
for(intj=0;j<stringLength;j++){
builder.append((char)random.nextInt(127));
}
returnbuilder.toString();
}
publicinttestJavaDefault(Stringdata)throwsException{
ObjectOutputStreamoutputStream=null;
ObjectInputStreaminputStream=null;
try{
ByteArrayOutputStreambyteArray=newByteArrayOutputStream();
outputStream=newObjectOutputStream(byteArray);
outputStream.writeObject(data);
outputStream.flush();
inputStream=newObjectInputStream(newByteArrayInputStream(byteArray.toByteArray()));
inputStream.readObject();
returnbyteArray.size();
}
finally{
outputStream.close();
inputStream.close();
}
}
publicinttestJavaDefaultBytes(Stringdata)throwsException{
ObjectOutputStreamoutputStream=null;
ObjectInputStreaminputStream=null;
try{
ByteArrayOutputStreambyteArray=newByteArrayOutputStream();
outputStream=newObjectOutputStream(byteArray);
outputStream.writeBytes(data);
outputStream.flush();
inputStream=newObjectInputStream(newByteArrayInputStream(byteArray.toByteArray()));
byte[]bytes=newbyte[byteArray.size()];
inputStream.read(newbyte[byteArray.size()]);
newString(bytes);
returnbyteArray.size();
}
finally{
outputStream.close();
inputStream.close();
}
}
publicinttestSwizzle(Swizzledata)throwsException{
ObjectOutputStreamoutputStream=null;
ObjectInputStreaminputStream=null;
try{
ByteArrayOutputStreambyteArray=newByteArrayOutputStream();
outputStream=newObjectOutputStream(byteArray);
outputStream.writeObject(data);
outputStream.flush();
inputStream=newObjectInputStream(newByteArrayInputStream(byteArray.toByteArray()));
inputStream.readObject();
returnbyteArray.size();
}
finally{
outputStream.close();
inputStream.close();
}
}
publicinttestStringUTF(Stringdata)throwsException{
ObjectOutputStreamoutputStream=null;
ObjectInputStreaminputStream=null;
try{
ByteArrayOutputStreambyteArray=newByteArrayOutputStream();
outputStream=newObjectOutputStream(byteArray);
outputStream.writeUTF(data);
outputStream.flush();
inputStream=newObjectInputStream(newByteArrayInputStream(byteArray.toByteArray()));
inputStream.readUTF();
returnbyteArray.size();
}
finally{
outputStream.close();
inputStream.close();
}
}
publicfinalstaticvoidmain(String[]args)throwsException{
CompareSerializationcompare=newCompareSerialization();
Stringdata=compare.generateTestData(Integer.parseInt(args[0]));
Swizzleswizzle=newSwizzle(data);
System.out.println(“testJavaDefaultsizeonnetworking:”+compare.testJavaDefault(data));
System.out.println(“testJavaDefaultBytessizeonnetworking:”+compare.testJavaDefaultBytes(data));
System.out.println(“testStringUTFsizeonnetworking:”+compare.testStringUTF(data));
System.out.println(“testSwizzlesizeonnetworking:”+compare.testSwizzle(swizzle));
//warmup
for(inti=0;i<100;i++){
compare.testJavaDefault(data);
compare.testJavaDefaultBytes(data);
compare.testStringUTF(data);
compare.testSwizzle(swizzle);
}
longstartTime=System.currentTimeMillis();
for(inti=0;i<10000;i++){
compare.testJavaDefault(data);
}
longendTime=System.currentTimeMillis();
System.out.println(“testJavaDefaultusingtime:”+(endTime–startTime));
startTime=System.currentTimeMillis();
for(inti=0;i<10000;i++){
compare.testJavaDefaultBytes(data);
}
endTime=System.currentTimeMillis();
System.out.println(“testJavaDefaultBytesusingtime:”+(endTime–startTime));
startTime=System.currentTimeMillis();
for(inti=0;i<10000;i++){
compare.testStringUTF(data);
}
endTime=System.currentTimeMillis();
System.out.println(“testStringUTFusingtime:”+(endTime–startTime));
startTime=System.currentTimeMillis();
for(inti=0;i<10000;i++){
compare.testSwizzle(swizzle);
}
endTime=System.currentTimeMillis();
System.out.println(“testSwizzleusingtime:”+(endTime–startTime));
}
}
java比较简单,没有C++的烦琐,但学习时最好有C++为基础.与JSP和SQL起应用,功能强大. |