<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>cache | 伪架构师</title>
    <link>/tags/cache/</link>
      <atom:link href="/tags/cache/index.xml" rel="self" type="application/rss+xml" />
    <description>cache</description>
    <generator>Source Themes Academic (https://sourcethemes.com/academic/)</generator><language>zh</language><lastBuildDate>Wed, 14 Oct 2015 22:09:07 +0800</lastBuildDate>
    <image>
      <url>/img/logo-wide.png</url>
      <title>cache</title>
      <link>/tags/cache/</link>
    </image>
    
    <item>
      <title>Drupal 8 的动态页面缓存</title>
      <link>/post/page-cache-in-drupal-8/</link>
      <pubDate>Wed, 14 Oct 2015 22:09:07 +0800</pubDate>
      <guid>/post/page-cache-in-drupal-8/</guid>
      <description>

&lt;p&gt;Drupal 8 现在有了动态页面缓存。Page Cache 模块只对匿名用户生效，而 Dynamic Page Cache 模块则更进一步的为所有用户提供服务。&lt;/p&gt;

&lt;p&gt;4 月 8 日起，Drupal 8 &lt;a href=&#34;https://wimleers.com/blog/drupal-8-page-caching-enabled-by-default&#34; target=&#34;_blank&#34;&gt;缺省开启&lt;/a&gt;了页面缓存。刚好五个月以后也就是 9 月 8 日，Dynamic Page Cache 模块也加入了 Drupal 8，同样的也是缺省开启。&lt;/p&gt;

&lt;h2 id=&#34;动态页面缓存是什么&#34;&gt;动态页面缓存是什么？&lt;/h2&gt;

&lt;h3 id=&#34;page-cache-模块缓存的是完全渲染之后的-html-响应内容&#34;&gt;Page Cache 模块缓存的是完全渲染之后的 HTML 响应内容&lt;/h3&gt;

&lt;p&gt;他假设每个响应只有一种，这个假设只对匿名用户有效。相对于 Drupal 7，8 的创新是加入了 &lt;a href=&#34;https://www.drupal.org/developing/api/8/cache/tags&#34; target=&#34;_blank&#34;&gt;Cache Tags(缓存标记)&lt;/a&gt;，这就使得在使用页面缓存的时候，依然能够及时更新页面，不再呈现过期内容。&lt;/p&gt;

&lt;h3 id=&#34;dynamic-page-cache-模块缓存大部分渲染之后的-html-相应内容&#34;&gt;Dynamic Page Cache 模块缓存大部分渲染之后的 HTML 相应内容&lt;/h3&gt;

&lt;p&gt;现在不再认为只有一种响应了：这里要感谢 &lt;a href=&#34;https://www.drupal.org/developing/api/8/cache/contexts&#34; target=&#34;_blank&#34;&gt;cache contexts&lt;/a&gt;，他能够获取到页面各个部分的变体。在渲染过程中，&lt;a href=&#34;https://www.drupal.org/developing/api/8/render/arrays/cacheability/auto-placeholdering&#34; target=&#34;_blank&#34;&gt;自动占位&lt;/a&gt;会识别页面中的一部分不可缓存的内容，替换为占位符。这些占位符只在最后一刻进行渲染。动态页面缓存模块会在这些占位符被替换之前进行缓存。&lt;/p&gt;

&lt;p&gt;所以，概念上来说：&lt;strong&gt;Page Cache &amp;ndash;&amp;gt; Dynamic Page Cache&lt;/strong&gt;&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th align=&#34;left&#34;&gt;&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Key&lt;/th&gt;
&lt;th align=&#34;left&#34;&gt;Value&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Page Cache&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;code&gt;URL&lt;/code&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;code&gt;最终响应&lt;/code&gt; &lt;code&gt;缓存标记&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td align=&#34;left&#34;&gt;Dynamic Page Cache&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;code&gt;URL&lt;/code&gt; &lt;code&gt;cache contexts&lt;/code&gt;&lt;/td&gt;
&lt;td align=&#34;left&#34;&gt;&lt;code&gt;部分响应&lt;/code&gt; &lt;code&gt;占位符&lt;/code&gt; &lt;code&gt;缓存标记&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;p&gt;上表对比展示了二者的优劣：Page Cache 包含了最终响应，所以相对较快；而 Dynamic Page Cache 只包含了部分响应，但是因为这部分内容是没有经过个性化的，所以适用于各种用户。&lt;/p&gt;

&lt;p&gt;换句话说，动态页面缓存做的事情比较多，但是适用于更多场景。&lt;/p&gt;

&lt;h2 id=&#34;benchmark&#34;&gt;Benchmark&lt;/h2&gt;

&lt;p&gt;在开启页面缓存之后，Drupal 8 对匿名用户能够在常数时间内返回响应。&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;有了动态页面缓存之后，Drupal 8 的响应时间就是在之前的时间上再加上渲染占位符的时间。&lt;/strong&gt;这意味着，页面的绝大部分能够在固定时间里完成（跟内容多少无关）。最后的占位符渲染环节是最需要进行优化的，当然，最好没有这部分（可以延伸阅读一下 BigPipe 相关内容）。&lt;/p&gt;

&lt;p&gt;在我的机器上（&lt;code&gt;ab -c1 -n 1000&lt;/code&gt;, PHP 5.5.11，Intel Core i7 2.8 GHz 笔记本电脑，15 个带有一条留言的 Node，其中 10 个列在首页上）：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;没有动态页面缓存

&lt;ul&gt;
&lt;li&gt;首页：61.3 毫秒/请求（每秒 16 个请求）&lt;/li&gt;
&lt;li&gt;node/1：92.3 毫秒/请求（每秒 10.8 个请求）&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;li&gt;动态缓存开启

&lt;ul&gt;
&lt;li&gt;首页：38.3 毫秒/请求（每秒 26 个请求）&lt;/li&gt;
&lt;li&gt;node/1：73.8 毫秒/请求（每秒 13.5 个请求）&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&#34;分析&#34;&gt;分析&lt;/h2&gt;

&lt;p&gt;首页只有一个占位符（message），这使得首页是一个最低相应时间的指标：我的机器上大概 38 毫秒。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;大约 38 毫秒用于 bootstrap，路由，路由权限检查，从动态页面缓存中获取缓存内容。&lt;/li&gt;
&lt;li&gt;跟 node/1 比较：渲染占位符用掉了超过 35.5 毫秒的时间。这说明此处的渲染成本非常高——留言 Form。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;可以看到，动态页面缓存在开发期间也很有用，他暴露了无法缓存或者难于渲染的页面部分。&lt;/p&gt;

&lt;h3 id=&#34;在实际服务器上-十倍不止&#34;&gt;在实际服务器上，十倍不止&lt;/h3&gt;

&lt;p&gt;上面的测试只是一个并发，还可以参考&lt;a href=&#34;http://wimleers.com/blog/drupal-8-page-caching-enabled-by-default&#34; target=&#34;_blank&#34;&gt;Rasmus Lerdorf 的相关测试&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;多赢&#34;&gt;多赢&lt;/h2&gt;

&lt;p&gt;各种规模的站点都会受益：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;企业级站点得到了更高的可塑性，以及针对认证用户的反向代理/CDN方面能力的提升。&lt;/li&gt;
&lt;li&gt;小站点能够为认证用户提供更多更快的并发访问能力。&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;所以我的工作由 Acquia 赞助，但是大家都能从中获益。&lt;/p&gt;

&lt;p&gt;有人发表疑问， Drupal 8 会不会太复杂了，是不是已经不在意站点搭建者，而只考虑企业应用了之类的、我认为这就是个很好的反例 —— 缺省激活的页面缓存优于大多数的 Drupal 7 站点。&lt;/p&gt;

&lt;p&gt;我们的确在缓存标记上增加了复杂性，不过这只对开发者产生了影响，而且提供了&lt;a href=&#34;https://www.drupal.org/developing/api/8/render/arrays/cacheability&#34; target=&#34;_blank&#34;&gt;完善的文档&lt;/a&gt;。最重要的是，站点建设者不需要关心这些了，Drupal 8 开始不再需要手工清除缓存了！&lt;/p&gt;

&lt;p&gt;Drupal 很像乐高积木。直到 Drupal 8，如果你试用了太多的模块，站点会变慢，缓存的设置复杂到令人望而却步。现在这些组成部分必须自己声明缓存的元数据，这样 Drupal 就可以把大部分“加速”工作自动完成了。&lt;/p&gt;

&lt;h3 id=&#34;小站点-包括共享主机&#34;&gt;小站点（包括共享主机）&lt;/h3&gt;

&lt;p&gt;小站点能够处理更多的认证用户产生的并发访问，更快的生成页面。&lt;/p&gt;

&lt;p&gt;无需任何配置。&lt;/p&gt;

&lt;p&gt;无需任何搜索。&lt;/p&gt;

&lt;h3 id=&#34;企业站点-以及企业级托管&#34;&gt;企业站点（以及企业级托管）&lt;/h3&gt;

&lt;p&gt;企业站点有了更多调节的能力：如果倾向于利用足够的存储空间，而不是渲染占位符的话（空间换时间），那么只要覆盖缺省的&lt;a href=&#34;https://www.drupal.org/developing/api/8/render/arrays/cacheability/auto-placeholdering&#34; target=&#34;_blank&#34;&gt;自动占位符条件&lt;/a&gt;即可。&lt;/p&gt;

&lt;p&gt;这也是第一次我们有机会&lt;a href=&#34;http://wimleers.com/talk/caching-at-the-edge-cdns-for-everyone&#34; target=&#34;_blank&#34;&gt;利用CDN为认证用户提供响应内容&lt;/a&gt;。&lt;/p&gt;

&lt;h3 id=&#34;开发者&#34;&gt;开发者&lt;/h3&gt;

&lt;p&gt;在&lt;a href=&#34;https://www.drupal.org/developing/api/8/cache&#34; target=&#34;_blank&#34;&gt;缓存元数据&lt;/a&gt;（缓存标记，上下文和最大周期）之外，可以针对主机环境，性能和缓存方面做深入细致的调整。而之前，必须分析和调试一大坨代码，来判断为什么有些缓存没有在合适的时候过期。&lt;/p&gt;

&lt;p&gt;原因是，现在的整个过程被标准化了，我们可以使用&lt;a href=&#34;http://wimleers.com/blog/renderviz-prototype&#34; target=&#34;_blank&#34;&gt;更好的工具&lt;/a&gt;——甚至可以自动的检测类似问题：不合适的缓存上下文，过低的缓存生命周期，过于频繁的缓存失效。&lt;/p&gt;

&lt;p&gt;最后，这一切使得 &lt;a href=&#34;http://wimleers.com/talk/making-drupal-fly-fastest-drupal-ever-here&#34; target=&#34;_blank&#34;&gt;Drupal 8 成为最快的 Drupal&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&#34;drupal-8-的动态页面缓存-vs-drupal-7-的-authcache&#34;&gt;Drupal 8 的动态页面缓存 vs Drupal 7 的 Authcache&lt;/h2&gt;

&lt;p&gt;动态页面缓存在 Drupal 7 中最相近内容应该就是 &lt;a href=&#34;https://www.drupal.org/project/authcache&#34; target=&#34;_blank&#34;&gt;Authcache 模块&lt;/a&gt;了。在 Drupal 7 中使用 Authcache 也能获得非常好的性能，但是这需要大量的工作：所有的代码（第三方的和自行实现的）必须进行分析，以保证所有的输出过程中所有需要进行缓存验证的部分都对应到账号。所有的因素必须都传递给 Authcache，来进行缓存键的计算。“关键属性”的概念和 Drupal 8 的缓存上下文类似。然而，这个过程很容易漏掉一些因素。这是因为站点的所有者要负责识别所有的验证，这里包含所有的模块和页面。缺省情况下，Authcache 假设用站点的 base URL 和用户的角色来进行区分。所以除非你的站点非常简单（可能连多语言都不支持），否则就要进行很多的研究来用好 Authcache。&lt;/p&gt;

&lt;p&gt;（例如目前还在运行 Drupal 7 的 Drupal.org，几个月前推出了针对评论的渲染缓存功能。他的工作方式很像 Authcache：必须指定引起缓存校验的因素。有个因素（时区）被忽略了，结果导致了奇怪的输出结果。强如 Durpal.org 的团队，也发生了这种错误，我们如何能够寄希望于其他团队呢？）&lt;/p&gt;

&lt;p&gt;Drupal 8 中的动态页面缓存建立在缓存元数据概念之上。不需要自定义钩子，也无需用户参与。缓存行为现在是模块的责任，有理由相信，模块作者更知道模块的功能，因此也无需再次进行代码分析。动态缓存还支持缓存标记，所以跟 Drupal 7 的 Authcache 不同，动态页面缓存能够及时进行更新。&lt;/p&gt;

&lt;p&gt;在 Drupal 8.0.0 中，动态页面缓存在 bootstrap、路由、路由访问控制之后执行。而因为 Authcache 做了一些简单假设，他能够在完全执行完 bootstrap 之前执行，这样无疑是更快的。我们也正在一个 issue （&lt;a href=&#34;https://www.drupal.org/node/2541284&#34; target=&#34;_blank&#34;&gt;#2541284&lt;/a&gt;） 中提出这个问题，这一问题如果得以解决，能够得到巨大的性能提升，我们会在 Drupal 8 未来的某个版本中发布出来。&lt;/p&gt;

&lt;p&gt;最后因为 Drupal 8 中缺省就启用了动态页面缓存，所以他直接为所有的开发者和所有的站点产生巨大的影响。建议所有的 Drupal 开发者在代码中定制合适的缓存上下文。这样 Drupal 8 的模块就会被为数众多的网站所考验，遗失的缓存元数据也就可以迅速修正。所有用户一起来完成这一任务，而不是像 Authcache 用户那样单打独斗。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>Drupal静态缓存</title>
      <link>/post/drupal-static-cache/</link>
      <pubDate>Wed, 05 Aug 2015 10:32:19 +0800</pubDate>
      <guid>/post/drupal-static-cache/</guid>
      <description>&lt;p&gt;Drupal的伸缩性是存在的，而且非常强大。当我们问别人对Drupal的看法时候，多数时间得到的答案是：据说那东西很慢。在我的工作中见到过很多性能低下的Drupal站点，缓存是其中的重要原因。即使是基础的Drupal安装，其中也包含了一套针对数据表的多层缓存，不幸的是，这一缓存体系很容易被开发者破坏。&lt;/p&gt;

&lt;p&gt;阻碍缓存的最大原因可能就是在自定义模块中错过了利用缓存提升性能的机会。把计算后的结果保存在PHP变量中，接下来的调用过程可能会得到成百上千倍的性能提升。要使用这一技巧只需要很小成本：如果一个结果已经得出，就返回这一结果；否则，运算得到结果之后，首先保存结果，然后才返回。&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    function apachesolr_static_response_cache($searcher, $response = NULL) {
      $_response = &amp;amp;drupal_static(__FUNCTION__, array());

      if (is_object($response)) {
        $_response[$searcher] = clone $response;
      }
      if (!isset($_response[$searcher])) {
        $_response[$searcher] = NULL;
      }
      return $_response[$searcher];
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Apache Solr模块在很多地方使用了静态缓存，例如即使一个页面上存在多个搜索相关的Block，也保证每次请求只执行一个Solr搜索。&lt;/p&gt;

&lt;p&gt;和其他缓存方案一样，缓存命中时候的访问速度和缓存未命中时的差异决定了缓存的效益。耗时长、执行频繁并且经常返回重复值的函数，通过缓存能够获得最好的收益，这一标准非常清晰，Drupal很多代码符合这一要求。&lt;/p&gt;

&lt;p&gt;很多重负载的核心函数进行了静态缓存：&lt;code&gt;menu.module&lt;/code&gt;使用了一个树状的数据结构，这意味着需要做很多重复的递归工作。当页面上有多处使用菜单的情况下，有了静态缓存的帮助，处理时间得到了极大的缩减。类似的还有Drupal的分类系统——在列表或画廊页面中，分类词的处理可能要进行非常多的次数。在&lt;code&gt;taxonomy.module&lt;/code&gt;中的五个函数包含了对&lt;code&gt;drupal_static()&lt;/code&gt;的调用，用于加速重复工作。&lt;/p&gt;

&lt;p&gt;Drupal中还有一类函数，他们的执行非常快速，但是在很多位置调用，并且返回结果几乎不会变化。&lt;code&gt;drupal_is_front_page()&lt;/code&gt;以及&lt;code&gt;drupal_page_is_cacheable()&lt;/code&gt;只是简单的检查，一个更好的例子是&lt;code&gt;ip_address()&lt;/code&gt;。这个函数需要处理HTTP头中的&lt;code&gt;X-Forwarded-For&lt;/code&gt;，用于确定用户的真实IP地址，这需要字符串运算。相对其他操作来说，字符串解析需要更多的函数调用和内存访问。&lt;/p&gt;

&lt;p&gt;上面的文字听起来很不错，不过如果缓存值不再准确了会怎样？虽说静态缓存只在一次请求中有效，这其中仍然存在缓存过期的可能性。在缓存函数内部对缓存数据进行失效处理是很容易的，但是由于缓存变量的作用域限制，会阻止其他函数访问。这意味着，静态缓存的实现还是可能有引入其他问题。&lt;/p&gt;

&lt;p&gt;在Drupal 7之前，函数需要自行决定是否暴露失效缓存的途径。有些通过跟踪一个不太优雅的&amp;rsquo;失效缓存&amp;rsquo;的参数，不过多数连这个都没有。Druapl 7中加入&lt;code&gt;drupal_static&lt;/code&gt;，让函数可以暴露一个可以为其他函数所用的静态变量，这样就可以在函数作用域之外改变这一变量了。&lt;/p&gt;

&lt;p&gt;&lt;code&gt;ip_address()&lt;/code&gt;函数是个静态缓存的好例子。很多站点具有地理相关的功能（例如把用户重定向到缺省语言或者展示本地内容），这种功能的测试也明显的比较麻烦。Smart IP模块实现了一个测试，用一个IP伪造的Form来测试用户权限和debug变量：&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;    if (user_access(&#39;administer smart_ip&#39;) &amp;amp;&amp;amp; variable_get(&#39;smart_ip_debug&#39;, FALSE)) {

        $ip = variable_get(&#39;smart_ip_test_ip_address&#39;, ip_address());

        $location = smart_ip_get_location($ip);
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;如何对这个内容进行自动化测试呢？测试账号需要访问权限（阻止匿名用户访问测试函数），IP 地址的变化也会影响到管理员用户。更糟糕的是，每次对测试IP地址的修改都会导致一次variable表的写入，这会拖慢整个站点。&lt;/p&gt;

&lt;p&gt;因为&lt;code&gt;ip_address()&lt;/code&gt;使用&lt;code&gt;drupal_static()&lt;/code&gt;暴露了他的静态缓存，所以就可以修改他的返回值了。这样测试过程就可以测试所有IP相关的函数，而不需要用户账号、权限或者对variable表的访问。要切换回普通的IP Address功能只要调用一次&lt;code&gt;drupal_static_reset()&lt;/code&gt;，这将导致&lt;code&gt;ip_address()&lt;/code&gt;的下次调用会像初次调用一样。&lt;/p&gt;

&lt;p&gt;Drupal.org列出了Drupal 7核心中的180次对&lt;code&gt;drupal_statc()&lt;/code&gt;的调用，drupalcontrib.org中报告了563此。并不是每次&lt;code&gt;drupal_static()&lt;/code&gt;调用都是静态缓存，也不是每个静态缓存都用&lt;code&gt;drupal_static&lt;/code&gt;实现，不过这仍然给我们以灵感，如何通过静态缓存来提高Drupal的性能。&lt;/p&gt;
</description>
    </item>
    
    <item>
      <title>清空主题缓存</title>
      <link>/post/drupal-clean-theme-cache/</link>
      <pubDate>Sat, 05 Jul 2014 01:21:46 +0800</pubDate>
      <guid>/post/drupal-clean-theme-cache/</guid>
      <description>&lt;p&gt;原文：&lt;a href=&#34;https://www.drupal.org/docs/7/theming/clearing-the-theme-cache&#34; target=&#34;_blank&#34;&gt;Clearing the theme cache&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;info 文件被缓存在数据库中（不一定是数据库，反正是缓存了——译者注），所以对这个文件的变更，Drupal 是没有感知的。如果你新增了 tpl.php 文件，或者覆盖了新的主题方法，那么你需要清空主题缓存才能让这些变更生效。&lt;/p&gt;

&lt;p&gt;不要把这个缓存和&lt;a href=&#34;https://www.drupal.org/node/173880#theme-registry&#34; target=&#34;_blank&#34;&gt;主题注册表&lt;/a&gt;混淆了。要清理缓存，按照如下步骤进行：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;点击Performance页面里的“Clear all caches”按钮。注意这个按钮会清空&lt;strong&gt;所有&lt;/strong&gt;的缓存，其中不只是主题缓存。如果你的站点有很多页面或者很大流量，你可能希望用下面的&lt;strong&gt;其他&lt;/strong&gt;办法只清除主题缓存。&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Drupal 7&lt;/strong&gt;  &amp;ldquo;Administration &amp;gt; Configuration &amp;gt; Development &amp;gt; Performance&amp;rdquo;（admin/config/development/performance）。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;strong&gt;Drupal 6&lt;/strong&gt;  &amp;ldquo;Administer &amp;gt; Site configuration &amp;gt; Performance&amp;rdquo; （admin/settings/performance）。&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;其他办法：&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://drupal.org/project/admin_menu&#34; target=&#34;_blank&#34;&gt;Admin menu&lt;/a&gt;在Home图标下面有一个清空缓存的按钮。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://drupal.org/project/devel&#34; target=&#34;_blank&#34;&gt;Devel project&lt;/a&gt;中的Devel Block模块提供了一个&amp;rdquo;Empty cache&amp;rdquo;的连接。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;D7中的&lt;a href=&#34;http://api.drupal.org/api/function/drupal_theme_rebuild/7&#34; target=&#34;_blank&#34;&gt;drupal_theme_rebuild&lt;/a&gt;或者D6中的&lt;a href=&#34;http://api.drupal.org/api/drupal/includes!theme.inc/function/drupal_rebuild_theme_registry/6&#34; target=&#34;_blank&#34;&gt;drupal_rebuild_theme_registry&lt;/a&gt; API 函数。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;有些主题（Zen, Fusion等）在每个页面提供了一个复选框来重建主题缓存，带有漂亮的警告来提示你不要忘记关闭这东西。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;http://drupal.org/project/drush&#34; target=&#34;_blank&#34;&gt;Drush&lt;/a&gt;提供了一个命令：drush cc theme-registry.&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;&lt;a href=&#34;https://drupal.org/project/magic&#34; target=&#34;_blank&#34;&gt;The Magic Module&lt;/a&gt;有一个设置&amp;rdquo;Rebuild Theme Registry on Page Reload&amp;rdquo;（在页面重新载入时重建主题注册表）可以用于任何主题。&lt;/p&gt;&lt;/li&gt;

&lt;li&gt;&lt;p&gt;浏览主题选择页也会清空.info文件缓存&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;如果上面的办法都失败了，还可以尝试&lt;a href=&#34;http://drupal.org/node/42055&#34; target=&#34;_blank&#34;&gt;清空全部缓存&lt;/a&gt;。&lt;/p&gt;
</description>
    </item>
    
  </channel>
</rss>
