解惑

解己之惑,解人之惑

标签:缓存

Google面试题解说性能之七:缓存中间结果

上次已经说了fn的实现不能用来查找符合条件的n,因为这样做比前面的第一个例子中的性能比较差的那个还要差,原因就是有太多的重复计算,如果只是计算一个指定的数的结果,那么那个实现是无与匹敌的。但是我们是讲的性能优化,所以,我们就用它来做,放慢速度,然后使用其它的技巧来提高性能,这次的方法就是简单的使用缓存:
public class GoogleFn {
private static final int MAX = 2600002;

private static long start = System.currentTimeMillis();

private static int[] bases = new int[15];

private static int[] values = new int[15];

private static int fn(int number) {
if (number < 10) {
return number > 0 ? 1 : 0;
}
String s = number + “”;
int length = s.length();
int end = Integer.parseInt(s.substring(1, length));
int x = s.charAt(0) – ‘0’;
int result = 0;
if (x == 1) {
result = values[length – 1] + fn(end) + (end + 1);
} else {
result = values[length – 1] * x + bases[length – 1] + fn(end);
}
return result;
}

阅读全文

浏览器缓存

相信有不少人会遇到浏览器缓存的问题,因为IE默认会缓存访问过的网页,特别是URL的参数是固定的,但是很可能内容会变化。
大部分都知道的可能是在head中增加meta信息:
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
而有文章指出这个依然有问题,如果网页内容超过32K,那么那个设置就实效了,所以要把它放到网页的最后:
            <BODY>
网页内容。。。
</BODY>
<HEAD>
<META HTTP-EQUIV="PRAGMA" CONTENT="NO-CACHE">
</HEAD>
</HTML>

现在AJAX很流行,而AJAX返回的内容很可能不再是一个完整的网页,那么就不能使用上述的方法,有另外的文章说到可以使用服务器端的HTTP头控制,我试验的结果是无效
    response.setHeader("Cache-Control","no-cache");
    response.setHeader("Cache-Control","no-store");
    response.setHeader("Cache-Control","must-revalidate");

最后采取的方法就是在使用AJAX发送请求的时候附加一个时间戳:
var xmlhttp = createrequest();
xmlhttp.open("GET",appendTimestamp(url),true);

  function appendTimestamp(url)
  {
      if (url.indexOf("?")>0)
      {
          return url+"&ajax_time="+new Date().getTime();
      } else
      {
          return url+"?ajax_time="+new Date().getTime();
      }
  }

当然这个方法也只能解决部分问题,如果URL太长也不行。

更新:
对于AJAX的情况,也可以使用
xmlhttp.setRequestHeader("Cache-Control","no-cache");

推荐另外一个日志:再论怎么有效利用浏览器缓存之怎么避免浏览器缓存静态文件

2007年2月28日更新:
使用服务器端控制AJAX页面缓存:
    response.setHeader( "Pragma", "no-cache" );
    response.addHeader( "Cache-Control", "must-revalidate" );
    response.addHeader( "Cache-Control", "no-cache" );
    response.addHeader( "Cache-Control", "no-store" );
    response.setDateHeader("Expires", 0);
单纯的使用 xmlhttp.setRequestHeader("Cache-Control","no-cache")无效。

完成轮子的第二个部分-缓存

昨天晚上花了一个多小时完成了我的大轮子的第二部分:缓存
今天中午利用休息时间写了测试用例,还算很顺利的,哈哈。

代码如下:
阅读全文

条条大路通罗马

今天在写测试的用例的时候发现框架的一个Bug,CMP在初始化Entity Bean的时候会自动初始化相关的Entity Bean,但是如果是在一对多的情况下,首先使用的如果是一那端的情况下,不会自动的初始化多那一端的Entity Bean,后来添加了代码修正这个问题后,发现原来只要2分钟运行的所有的测试用例要15分钟才能运行完了,跟踪了一下发现是其中一个测试用例所使用的Entity Bean会连带初始化其他十几个Entity Bean,而且其中有几个Entity Bean的初始数据非常的多,每一个都有300条数据,这样要初始化好需要3分钟,而每个test方法都会来这么一次初始化。后来想着加Cache,Entity Bean填充好以后就缓存起来,后面的test方法再需要初始化的时候就直接进行对象拷贝就可以了,但是Entity Bean在使用的时候会修改一些值,这样如果发生变化的话应该从Cache里面清除,而且需要连带清除所有的Entity Bean。原来缓存的是MockEJB动态创建的Proxy对象,所以要进行对象复制不容易,看了MockEJB的源代码本来想自己也创建一个新的Proxy对象进行复制保存,但是工作量比较大,后来想到的解决的办法就是把对象的属性都复制到一个Map里面,主键是属性的名字,值就是对象值,如果值是集合类型,那么要创建一个同样的集合类并发那个集合里面的全部值加进去。

上面是我在公司的时候的解决方案,在写这篇日志的时候,又想到可能的其他方法,例如初始化Entity Bean的时候不初始化相关的其他的Entity Bean,只有在需要的时候才初始化(增加一个BaseGetterAspect,就像其他的Aspect一样);另外就是在发布Entity Bean的时候不初始化所有的Entity Bean实例,只有在需要使用到那个实例的时候再初始化。当然这两个也不是那么简单就可以实现的,明天还要再好好的考虑下哪种最保险最简单。

在遇到一个问题的时候,解决方案是多种多样的,只要你敢想。:)

© 2024 解惑

本主题由Anders Noren提供向上 ↑