“滚蛋杯”足球赛,今天我们班的最后一场小组赛。很多人去复试了,人手不够,我也被赶鸭子上架去踢后卫。有惊无险,最后已4:2胜出^_^,下一场就是半决赛了。想想自己,已经有很久没踢球了。想当年初中的时候是每天都要踢的,高中是一周一次,大学是一学期也没踢什么球,现在是完全跑不动了。早上去买了双球鞋,在场上撑了90分钟,还好没出啥丑。^_^
大一的新生杯踢地很憋屈,这次既是冲着冠军来的,也是复仇之战。还剩两场球赛,真希望还能有上场的机会,很期待拿个冠军。
“滚蛋杯”足球赛,今天我们班的最后一场小组赛。很多人去复试了,人手不够,我也被赶鸭子上架去踢后卫。有惊无险,最后已4:2胜出^_^,下一场就是半决赛了。想想自己,已经有很久没踢球了。想当年初中的时候是每天都要踢的,高中是一周一次,大学是一学期也没踢什么球,现在是完全跑不动了。早上去买了双球鞋,在场上撑了90分钟,还好没出啥丑。^_^
大一的新生杯踢地很憋屈,这次既是冲着冠军来的,也是复仇之战。还剩两场球赛,真希望还能有上场的机会,很期待拿个冠军。
这几天不在学校,于是没怎么上网。今天回来一看,有一个网站居然被google给K了,灰常的伤心。这可是偶做站最大的成果,也是网站收入的主要来源(虽然也很少),而网站流量的主要来源也是google。一下子被K了,真可以说是一夜回到解放前了。前段时间做了一个翻/墙技术的网站,开始有效果之后虽然没被K站,但是被qiang了,灰常的杯具,还有点搞笑。
看来站长和google真的走不远,如何才能让蜜月期更长一点呢?
很久以前开通了新浪微博,不过仅限于开通,后面就没用过了。老得上网站感觉没意思,还是有客户端的方便。不过新浪出微博客户端的话(不知道有没有)我也不会用了,电脑上开了太多这种东西。QQ是必用的,现在beta3版本已经集成了微博,不过QQ也长胖了不少,还没看顺眼。
我的微博,要人肉我的就来吧: http://t.qq.com/doggod999
CrazyDo
浏览器解释HTML时最耗时的部分是Reflow(回流),而当JS操作DOM的时候就会引发浏览器的Reflow,因此减少操作DOM的次数可以提高性能。
当需要操作DOM时,比如在一个div中添加n个div,我们可能这样操作:
var ctrl = document.getElementById("mainContainer");
for (var i = 0; i < 100; i++) {
var child = document.createElement("div");
ctrl.appendChild(child);
}
或者
var ctrl = document.getElementById("mainContainer");
var inner = ""
for (var i = 0; i < 100; i++) {
inner += "<div></div>";
}
ctrl.innerHTML = inner;
乍一看,第一种方法直接操作DOM,省去了HTML->DOM的Parse过程,但是每次执行appendChild,就要Reflow一次,而第二种方法,相当于一次性操作DOM,只有一次Reflow,而且目前大部分浏览器对于Parse的过程都有优化,因此性能开销十分小。实测添加10000个div,第一种方法在160ms左右,第二中方法只要50ms左右。
———————————————–
spllot:如果我没记错的话,使用innerHTML,有些情况下是不怎么好的.能不能分析下使用innerHTML的好处与坏处
———————————————-
joehust:更复杂的情况呢?我比较喜欢用innerHTML直接设置,不过有人提醒过我说有一部分我写的代码太慢了,换成了分步的dom操作,
是否在所有情况下都是直接修改innerHTML更快呢?
———————————————
CrazyDo:一般来说,如果innerHTML里面嵌套关系过于复杂的时候建议先createElement创建儿子节点,然后在其中appendChild加入孙子节点,以此类推,最后将儿子节点加入父亲节点,这样在Firefox下也是一次Reflow,但是IE下似乎还是多次Reflow。
———————————————
joehust:很多时候再构造页面的时候其实是先将内容拼好,再append到某个节点下面去,在拼接过程中应该是不会有reflow的,这个时候用dom语句去构造就会省去parse html的过程,速度应当快些,如果是对已经呈现出来的页面进行修改的话可以考虑先将其hide,或者移除,等修改完成后再添加回去,这样可以避免修改的过程中发生reflow,从而提高效
率吧
henix
在很多地方都会用到 JVM 参数,比如你运行 ant check-style,跑挂了,抛了个OutOfMemory 错误。这时你上网搜索,他们会告诉你,应该修改 ANT_OPTS 环境变量,加上“-Xmx512m”。
再比如 JBoss 或 tomcat 都有启动脚本(startup.bat等),里面也用到 JVM 参数。还有Eclipse 的 eclipse.ini 中也可以加入 JVM 参数。灵活使用这些 JVM 参数可以使我们的 Java 程序获得更好的性能。
=== 常用参数 ===
-server
一定要作为第一个参数,会使JVM启动速度变慢,但会显著提升JVM性能
-Xms64m
设置初始 Heap 大小,使用的最小内存
-Xmx1024m
设置最大 Heap 大小
-Xss256k
设置每个线程的 Stack 大小
-XX:MaxPermSize=128M
设置最大永久区大小,永久保存区用于存放Class信息和元信息
=== GC(垃圾回收)参数 ===
Sun HotSpot JVM 通常使用的 GC 算法是分代回收。即把对象按生命周期不同分为年轻代和年老代。新的对象会先生成在Young Area,在几次 GC 以后,如果没有收集到,就会逐渐升级到Tenured Area。
Sun JVM 默认的回收器称为 serial collector ,即串行回收,我们也可以使用多线程并发回收来提高效率。需要注意的是,在单核的机器上,使用默认的回收器可能会更好。
-XX:+UseParNewGC
为年轻代对象使用并发回收,会缩短年轻代对象的回收时间
-XX:+UseConcMarkSweepGC
为年老代使用并发回收
-XX:+UseParallelGC
该收集器和 UseConcMarkSweepGC 是互相排斥的,为新生代使用并行清除,年老代使用单线程Mark-Sweep-Compact的垃圾收集器。
=== 其他参数 ===
-XX:CompileThreshold=100
该值表示编译之前必须调用方法的次数。HotSpot JVM 使用 JIT(Just-In-Time Compilation, http://en.wikipedia.org/wiki/Just-in-time_compilation) 技术将字节码编译成本地码,默认值为1000,即一个方法被调用了 1000 次之后 JVM 会编译它。降低这个值可能会使程序的性能得到提升,但会使启动速度变慢。
-XX:+DoEscapeAnalysis
启用逃逸分析,这个选项只能用于 Java 1.6。原理参见:http://kenwublog.com/jvm-optimization-escape-analysis
=== JVM参数的设置 ===
可以直接在java命令后面附加,比如:java -Xmx512m -XX:+UseParNewGC Test
还可以在环境变量中设置,如 JAVA_OPTS 和 ANT_OPTS 。还可以在eclipse.ini中设置,需要写在 -vmargs 一行的后面
=== 参考资料 ===
* Java 6 JVM参数选项大全(中文版):http://kenwublog.com/docs/java6-jvm-options-chinese-edition.htm
* Garbage Collection – Frequently Asked Questions:http://java.sun.com/docs/hotspot/gc1.4.2/faq.html
* 调整 JVM 开关以获得最佳性能:http://gceclub.sun.com.cn/NetBeans/tutorials/tuning/index.html
转自Dian团队内部技术讨论。
Google今天被墙的一塌糊涂,虽然能搜索,但是搜索结果怎么也打不开。也不清楚是不是我自己的原因。
感冒还没好,明天要去体检了,不知道会不会有影响。困了,想睡觉。。。。
NIO即new io.主要是采用通道机制来提高文件读取速度。以下为一个简单的读取文本文
件的例子:
public String readTxtFile(String path) throws IOException {
long start = System.currentTimeMillis();
//设置缓冲区的大小
final int BUFFER_SIZE = 0x900000;
String content = "";
// 创建一个文件输入流
FileInputStream fis = new FileInputStream(path);
// 获得该输入流的通道
FileChannel fc = fis.getChannel();
// 创建一个字节缓冲区
ByteBuffer bb = ByteBuffer.allocate(BUFFER_SIZE);
// 将字节序列从此通道读入给定的缓冲区
fc.read(bb);
// 反转此缓冲区。首先将限制设置为当前位置,然后将位置设置为 0
bb.flip();
// 获得缓冲区中剩余元素数,并创建相应的字节数组
byte[] bytes = new byte[bb.remaining()];
// 将缓冲区中的字节序列存放在字节数组里
bb.get(bytes);
// 将字节数组中的内容转换成字符串
content = new String(bytes);
long end = System.currentTimeMillis();
System.out.println(end - start);
return content;
}
我做了一个简单的测试,对于一般几K到几十K的文本文件,只需要几毫秒到20几毫秒
,对于一个好几M的文本文件,只需要200多个毫秒。希望有兴趣的同学可以进一步的研
究,共同探讨相关话题。
另外推荐一篇关于流的文章:http://www.ibm.com/developerworks/cn/java/j-io1/
———————————————————
henix: 那跟FileInputStream再套上BufferedInputStream有什么区别?
———————————————————
spllot:
我觉得一个很重要的区别是,NIO中的做法更灵活,操作起来比较简单.我写的小例子只是
其中的一角,还有像MappedByteBuffer等缓冲区,这些缓冲区都有清除、反转和重绕方法
,用以标记当前位置,以及将当前位置重置为前一个标记处.并且还定义了一系列用于将
数据移出或移入缓冲区的 get 和 put 方法,用于压缩、复制 和切片 缓冲区的方法,
以及用于分配新缓冲区和将现有数组包装到缓冲区中.
对于我写的那个小程序,确实给人的感觉是空间换时间.
就我写的那个程序来说,对于一个小的文件,缓冲区设置小一点是没有什么问题的,但是如
果是一个好几个M的文件,如果缓冲区设置的过小的话,会出现读出来的内容不完全的情况
.所以为了简单的引进NIO,我仅仅是做了一个示例.
对于文件比较大的情况,如果将缓冲区设置比较小的话,也是可以解决的,分块来读就行了
.NIO是按块来读的,从这点来看,就比传统的IO读起来会快很多.另外NIO是无阻塞的,传统
的IO读文件的时候,需要将数据读到缓冲区后,再等待处理,会浪费很多时间,但NIO则不需
要,通过通道来传输,减少了等待的时间,从而提高了读取速度.
P.S 我的毕业设计是桌面搜索引擎,其中会涉及到文件的读取,有可能文件是比较大的,并
且数量是比较多的,所以如何减少读取时间,提高索引速度是很重要的,因此我考虑到使用
NIO.有兴趣的同学可以和我一起研究.
—————————————————
转自Dian团队内部技术讨论。
居然感冒了,浑身难受,真不爽。每次感冒的时候都觉得没胃口,不想吃饭,可是一旦吃起饭来又特别多,真搞不懂是怎么回事。
最近做网站推广做累了,又开始学Java,也该开始为毕设准备准备了。想学一下Java单元测试的编写,于是借了本《测试驱动开发》,很薄的一本,160页左右。网评说这本书很不错,不过我没这感觉。估计英文原版是一本很不错的书,不过翻译过来就完全变了味道了,没看完就看不下去了。于是想去买本《Junit in action》中文版,结果翻遍了全校的书店都没找到,对学校的书店那是相当的失望。晚上干脆跑去图书馆看,看了两章,书很不错,翻译的也不错,至少有兴趣继续看下去。收藏纸质版的是没机会了,电子版的《Junit in action》中文版质量很差,干脆看英文原版的,电子书免费又清晰,建议各位想看的也看英文版。
Java的String类有个方法叫trim(),说是去除字符串中的空格用的,其实这样的表述并不正确,正确的表述应该是去除字符串首尾的ASCII码小于等于空格的字符,对于字符串中的空格并没有效果。有点纠结,不过看一下trim()的实现代码就明白了。
public String trim() {
int len = count;
int st = 0;
int off = offset; /* avoid getfield opcode */
char[] val = value; /* avoid getfield opcode */
while ((st < len) && (val[off + st] <= ' ')) {
st++;
}
while ((st < len) && (val[off + len - 1] <= ' ')) {
len--;
}
return ((st > 0) || (len < count)) ? substring(st, len) : this;
}
第一个while循环去除字符串前面的空格,后一个循环去除字符串后面的空格。
示例:
public static void main(String[] args) {
String a=" \n www ooobj.com\n";
String b="www ooobj.com";
System.out.println(b.equals(a));
a = a.trim();
System.out.println(b.equals(a));
System.out.println(a);
}
输出:
false true www ooobj.com
另外,trim方法并不对传入的字符串进行空值检查,有需要可以再写一个检查空值的:
private static String trim(String src) {
if (src == null) {
return null;
}
return src.trim();
}
对于java的日志工具,以前一直只用过log4j,只听说过commons-logging。这两天在研究周导写的代码,发现工程中不仅用了log4j,还用上了commons-logging。觉得很奇怪,一个工程干嘛要用两个日志工具?
原来,Apache为了让众多的日志工具有一个相同操作方式,还实现做了一个通用日志工具包commons-logging。commons-logging是为那些需要建立在不同环境下使用不同日志架构的组件或库的开发者创建的,其中包括 Apache Log4j以及Java log的日志架构。commons-logging在运行时会自行决定使用哪种日志架构,如果发现classpath中是否有Log4j的包,则自动使用Log4j作为日志实现类,如果其他的日志工具一个也没有,则使用commons-logging自己提供的一个简单的日志实现类SimpleLog。
写了个小小的测试代码,发现commos-logging真的很强大。
package com.ooobj.log;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class LogTest {
private static Log log = LogFactory.getLog(LogTest.class);
public void test() {
log.debug("111");
log.info("222");
log.warn("333");
log.error("444");
log.fatal("555");
}
public static void main(String[] args) {
LogTest logTest = new LogTest();
logTest.test();
}
}
classpath中无log4j包的输出:
2010-4-8 14:12:37 com.ooobj.log.LogTest test
信息: 222
2010-4-8 14:12:37 com.ooobj.log.LogTest test
警告: 333
2010-4-8 14:12:37 com.ooobj.log.LogTest test
严重: 444
2010-4-8 14:12:37 com.ooobj.log.LogTest test
严重: 555
classpath中放入log4j包的输出:
[main] DEBUG com.ooobj.log.LogTest – 111
[main] INFO com.ooobj.log.LogTest – 222
[main] WARN com.ooobj.log.LogTest – 333
[main] ERROR com.ooobj.log.LogTest – 444
[main] FATAL com.ooobj.log.LogTest – 555
log4j.properties文件:
#设置级别和多个目的地 log4j.rootLogger=debug,appender1,appender2 #输出到控制台 log4j.appender.appender1=org.apache.log4j.ConsoleAppender #设置输出样式 log4j.appender.appender1.layout=org.apache.log4j.TTCCLayout #输出到文件(这里默认为追加方式) log4j.appender.appender2=org.apache.log4j.FileAppender #设置文件输出路径 #【1】文本文件 #log4j.appender.appender2.File=D:/workspace3.3/test/Log4JDemo02.log #【2】HTML文件 log4j.appender.appender2.File=D:/workspace3.3/test/Log4JDemo02.html #设置文件输出样式 #log4j.appender.appender2.layout=org.apache.log4j.TTCCLayout log4j.appender.appender2.layout=org.apache.log4j.HTMLLayout
Recent Comments