<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jjgod / blog &#187; Safari</title>
	<atom:link href="http://blog.jjgod.org/tag/safari/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.jjgod.org</link>
	<description>Random notes &#38; thoughts by Jiang Jiang.</description>
	<lastBuildDate>Mon, 16 Jan 2012 11:08:59 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.1</generator>
		<item>
		<title>Mac OS X 下与 SSD 相关的优化</title>
		<link>http://blog.jjgod.org/2010/04/17/macosx-ssd-tweaks/</link>
		<comments>http://blog.jjgod.org/2010/04/17/macosx-ssd-tweaks/#comments</comments>
		<pubDate>Sat, 17 Apr 2010 03:38:28 +0000</pubDate>
		<dc:creator>jjgod</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Miscs]]></category>
		<category><![CDATA[fstab]]></category>
		<category><![CDATA[noatime]]></category>
		<category><![CDATA[ramdisk]]></category>
		<category><![CDATA[Safari]]></category>
		<category><![CDATA[ssd]]></category>

		<guid isPermaLink="false">http://blog.jjgod.org/?p=608</guid>
		<description><![CDATA[最近刚入手一块 Intel X25-M G2 80G SSD，使用效果不错，于是整理了下面这些跟 SSD 有关的优化经验： 安装 因为 SSD 比较小，而有些数据又不是那么需要快速的访问，所以我保留了 MacBook Pro 里自带的 320G 7200 RPM 硬盘，做了如下改动： 买了一个光驱位硬盘托架，最有名，也是最贵的一种要 $99，但山寨版可以在淘宝找到，对于 Unibody 的机器来说，找 9.5mm 高的那种型号就行，比如 Fenvi 的，建议买 100 以内的。 把 MBP 拆开，SuperDrive 取下，把原来的硬盘取出，放入光驱位硬盘托架，把 SSD 接在原来的硬盘所接的 SATA 口，然后把硬盘托架安装回原来光驱的位置。这种搭配是为了保证用 SSD 做系统盘 (挂载在 / 上) 时系统能正确的让硬盘休眠。当然，如果你比较奢侈地买两块 SSD，也可以让他们组成 RAID0，这样性能就更夸张了。 给在 SSD 所在卷分区，只需要分一个区，安装系统。新的系统会把原来那块硬盘也列出来。这时修改 /etc/fstab，加入： /dev/disk1s2 /Users/jjgod/Downloads hfs rw 这个做法是把原来那块硬盘挂载在我自己这个用户的 Downloads [...]]]></description>
			<content:encoded><![CDATA[<p>最近刚入手一块 Intel X25-M G2 80G SSD，使用效果不错，于是整理了下面这些跟 SSD 有关的优化经验：</p>

<h4>安装</h4>

<p>因为 SSD 比较小，而有些数据又不是那么需要快速的访问，所以我保留了 MacBook Pro 里自带的 320G 7200 RPM 硬盘，做了如下改动：</p>

<ol>
<li><p>买了一个光驱位硬盘托架，最有名，也是最贵的一种要 $99，但山寨版可以在淘宝找到，对于 Unibody 的机器来说，找 9.5mm 高的那种型号就行，比如 Fenvi 的，建议买 100 以内的。</p></li>
<li><p>把 MBP 拆开，SuperDrive 取下，把原来的硬盘取出，放入光驱位硬盘托架，把 SSD 接在原来的硬盘所接的 SATA 口，然后把硬盘托架安装回原来光驱的位置。这种搭配是为了保证用 SSD 做系统盘 (挂载在 <code>/</code> 上) 时系统能正确的让硬盘休眠。当然，如果你比较奢侈地买两块 SSD，也可以让他们组成 RAID0，这样性能就更夸张了。</p></li>
<li><p>给在 SSD 所在卷分区，只需要分一个区，安装系统。新的系统会把原来那块硬盘也列出来。这时修改 <code>/etc/fstab</code>，加入：</p>

<pre><code>/dev/disk1s2 /Users/jjgod/Downloads hfs rw
</code></pre>

<p>这个做法是把原来那块硬盘挂载在我自己这个用户的 <code>Downloads</code> 目录，这样所有下载的内容都会放在这块比较大的硬盘上 (当然有用的我以后会转移到 SSD 上)，考虑到 Downloads 主要起的就是一个临时的缓冲作用，这样还是比较方便的。然后重启机器，就能发现这块硬盘只被挂载在上述目录下了。</p></li>
<li><p>除了下载内容，我还在这个目录放以下内容：</p>

<ul>
<li><p>VMware Fusion 的虚拟机文件，这是从别的机器复制过来的，直接放在这个卷的 <code>/Virtual Machines</code> 目录下，然后在 VMware Fusion 里打开就行了。需要注意的是以后 VMware 里创建新虚拟机的时候也得记住选择目录，别放在自己的 <code>$HOME/Documents</code> 下面了。</p></li>
<li><p>iTunes 媒体库，这个可以在 iTunes 的 Preferences -> Advanced -> iTunes Media folder location 选择。我是先在这里选好了，然后从原来的机器里导入以前的 iTunes 数据。</p></li>
<li><p>其他下载软件的默认下载位置，包括 uTorrent, Transmission 和 aMule。</p></li>
<li><p><a href="http://store.steampowered.com/">Steam</a> 的游戏目录，这个可以通过创建符号链接到 <code>$HOME/Documents/Steam Content</code> 实现。</p></li>
</ul></li>
</ol>

<h4>优化</h4>

<p>上述安装过程后，系统已经能保证数据各自放在比较合适的地方了，参考 <a href="http://blogs.nullvision.com/?p=275">Mac OS X SSD Tweaks</a> 这篇文章的介绍，我们还可以做如下优化：</p>

<ol>
<li><p>用 <code>noatime</code> 方式挂载系统盘，这样可以减少不必要的 I/O 次数，虽然 SSD 做这些操作非常快速，但考虑到<strong>最后访问时间</strong>这个属性其实很少用到，大家关心的一般都是最后修改时间和创建时间，所以完全可以关闭这个属性，这在 Unix/Linux 下是非常常见的文件系统优化选项。一个简单的方法是，修改 <code>/etc/fstab</code>，加入:</p>

<pre><code>/dev/disk0s2 / hfs rw,noatime
</code></pre>

<p>重启后，系统盘的挂载就带上 <code>noatime</code> 选项了:</p>

<pre><code>$ mount | grep " / "
/dev/disk0s2 on / (hfs, local, journaled, noatime)
</code></pre></li>
<li><p>禁用冬眠 (hibernate) 模式以节省空间。在 Mac 耗尽电池时，会进入“冬眠”模式，将内存中的所有内容写入磁盘，下次唤醒后从这些内容恢复状态。所以系统会在 <code>/var/vm</code> 维护一个和内存等大的 <code>sleepimage</code> 文件，考虑到 SSD 空间宝贵，而一般绝少会遇到耗尽电池的情况，可以禁用掉这个功能以节省空间：</p>

<pre><code>$ sudo pmset -a hibernatemode 0
$ sudo rm /var/vm/sleepimage
</code></pre></li>
<li><p>减少临时文件的读写。</p>

<ul>
<li><p>RAMDisk 是常见的性能优化手段，对于内存充足的机器，把频繁读写的内容放到一个用内存为存储的虚拟磁盘中，能大大加快速度。虽然 Macintosh Performance Guide <a href="http://macperformanceguide.com/OptimizingPhotoshop-RAMDisk.html">最近的一个研究</a>表明 RAMDisk 并不能很大地提升如 Photoshop 这类软件操作的性能，至少投入产出比不是很经济，但至少用它来保存一些本来就可以随意丢弃的数据是个很好的思路。<a href="http://blogs.nullvision.com/?p=275">Mac OS X SSD Tweaks</a> 提供了创建 RAMDisk 的脚本，他的做法是在系统启动时创建一个 256M 的 RAMDisk，挂载在 <code>/private/tmp</code> 上面。他还建议把 <code>~/Library/Caches</code> 也放到 RAMDisk 里。最大的问题是，如果你长期不重启 (我一般的重启周期是 80 ~ 100 天)，那有的临时文件，比如 <code>~/Library/Caches/com.apple.Safari/Webpage Previews/</code> 会增长到数百 M 甚至上 G。如果被它占满了 RAMDisk 的空间，那其他缓存数据就写不进去了。</p></li>
<li><p>考虑到 RAMDisk 是个比较有风险的优化手段，也可以用以下方法禁用掉 Safari 的 Webpage Previews 以减少临时文件读写。如果你像我一样从来不用 Safari 的“Top Sites”功能，一定会很讨厌它凭空占用大量的空间。</p>

<pre><code>$ defaults write com.apple.Safari DebugSnapshotsUpdatePolicy -int 2
</code></pre></li>
<li><p>关闭 Spotlight 索引也是一个有用的优化手段，如果你像我这样从来不用 Spotlight 的话。</p></li>
</ul></li>
</ol>

<h4>结语</h4>

<ul>
<li><p><a href="http://macperformanceguide.com/">Macintosh Performance Guide</a> 还提供了一些更奢侈的优化手段，这里不一一介绍了，因为我自己也没试过，有兴趣可以自己尝试。值得尝试的是它提供的 DiskTester 工具有一个 <a href="http://macperformanceguide.com/Software-DiskTester-UserManual-recondition.html">recondition</a> 功能，通过大量写空白块来优化长时间使用后的 SSD 性能。</p></li>
<li><p>“安装”部分感谢<a href="http://www.berrydigi.com">草莓数码</a>的 iBook 和 MacBook 的帮助。</p></li>
<li><p>“优化”部分大部分思路来自 <a href="http://blogs.nullvision.com/?p=275">Mac OS X SSD Tweaks</a>。</p></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.jjgod.org/2010/04/17/macosx-ssd-tweaks/feed/</wfw:commentRss>
		<slash:comments>11</slash:comments>
		</item>
		<item>
		<title>用来修正错误编码的文件名的 Safari 插件</title>
		<link>http://blog.jjgod.org/2009/03/04/safari-url-fix/</link>
		<comments>http://blog.jjgod.org/2009/03/04/safari-url-fix/#comments</comments>
		<pubDate>Wed, 04 Mar 2009 12:15:49 +0000</pubDate>
		<dc:creator>jjgod</dc:creator>
				<category><![CDATA[Browsers]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[Safari]]></category>
		<category><![CDATA[url]]></category>

		<guid isPermaLink="false">http://blog.jjgod.org/?p=375</guid>
		<description><![CDATA[我之前讨论过一次这种文件名的错误编码，为了在浏览器下载时的不必手工修正这个问题，这里提供一个 Safari 的 SIMBL 插件: SafariURLFix。 使用步骤如下： 如果没装过，先安装 SIMBL； 下载 SafariURLFix.zip，解压后，放到 ~/Library/Application Support/SIMBL/Plugins 目录 (如果没这个目录就自己创建)； 在 Terminal 中输入: defaults write com.apple.Safari JJURLsToFix -dict newsmth.net GBK 其中 newsmth.net 为你希望应用修正的网站域名。也可以打开 ~/Library/Preferences/com.apple.Safari.plist 文件自己编辑 JJURLsToFix 这个 Dictionary，自行添加新的，见附图。 重新启动 Safari，尝试下载这样的文件，看看文件名是否被正确纠正了。 如果还有什么问题，欢迎在下面提出。]]></description>
			<content:encoded><![CDATA[<p>我之前<a href="/2008/02/17/cocoa-nsstring-decoding-error/">讨论过</a>一次这种文件名的错误编码，为了在浏览器下载时的不必手工修正这个问题，这里提供一个 Safari 的 SIMBL 插件: SafariURLFix。</p>

<p>使用步骤如下：</p>

<ol>
<li><p>如果没装过，先<a href="http://www.culater.net/software/SIMBL/SIMBL.php">安装 SIMBL</a>；</p></li>
<li><p>下载 <a href="http://jjgod.org/program/SafariURLFix.zip">SafariURLFix.zip</a>，解压后，放到 <code>~/Library/Application Support/SIMBL/Plugins</code> 目录 (如果没这个目录就自己创建)；</p></li>
<li><p>在 Terminal 中输入:</p>

<p><code>defaults write com.apple.Safari JJURLsToFix -dict newsmth.net GBK</code></p>

<p>其中 newsmth.net 为你希望应用修正的网站域名。也可以打开 <code>~/Library/Preferences/com.apple.Safari.plist</code> 文件自己编辑 <code>JJURLsToFix</code> 这个 Dictionary，自行添加新的，见附图。<img src="http://blog.jjgod.org/wp-content/uploads/2009/03/picture-3.png" alt="Edit Safari Preferences Manually" title="Edit Safari Preferences Manually" class="alignnone wp-image-382 noline" width="95%" /></p></li>
<li><p>重新启动 Safari，尝试下载<a href="http://att.newsmth.net/att.php?p.719.275418.308.png">这样</a>的文件，看看文件名是否被正确纠正了。</p></li>
</ol>

<p>如果还有什么问题，欢迎在下面提出。</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jjgod.org/2009/03/04/safari-url-fix/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Cocoa 的 NSString 解码错误处理</title>
		<link>http://blog.jjgod.org/2008/02/17/cocoa-nsstring-decoding-error/</link>
		<comments>http://blog.jjgod.org/2008/02/17/cocoa-nsstring-decoding-error/#comments</comments>
		<pubDate>Sat, 16 Feb 2008 22:37:21 +0000</pubDate>
		<dc:creator>jjgod</dc:creator>
				<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>
		<category><![CDATA[ASCII]]></category>
		<category><![CDATA[cocoa]]></category>
		<category><![CDATA[NSString]]></category>
		<category><![CDATA[Safari]]></category>
		<category><![CDATA[UTF-8]]></category>

		<guid isPermaLink="false">http://blog.jjgod.org/2008/02/17/cocoa-nsstring-decoding-error/</guid>
		<description><![CDATA[在使用 Safari 的时候，我们会注意到一个很常见的乱码问题，如下图: 这是在打开 http://att.newsmth.net/att.php?p.719.214628.536.png 这样的图片链接时，Safari 错误的判断了这个图片文件的文件名造成的。而为什么会有这样的错误判断呢？ 其实 Safari 使用的是 Cocoa 框架 URL Loading 架构中的 NSURLResponse 类的 suggestedFilename 方法实现的。 而这个方法，其实就是解析 HTTP 首部中的 Content-Disposition 域里的 filename 部分完成的，比如下面这个首部: $ curl -I http://att.newsmth.net/att.php?p.719.214628.536.png HTTP/1.1 200 OK .... Content-Disposition: inline;filename=&#38;#892;&#38;#428;_6.png .... 显然这是乱码，可奇怪的是，这和我们在上面的图中看到的乱码又不一样，这是为什么呢？ 假如将它作为 GBK 来解码就清楚了: $ curl -I http://att.newsmth.net/att.php?p.719.214628.536.png &#124; iconv -f gbk -t utf-8 HTTP/1.1 200 OK .... [...]]]></description>
			<content:encoded><![CDATA[<p>在使用 <a href="http://www.apple.com/safari">Safari</a> 的时候，我们会注意到一个很常见的乱码问题，如下图:</p>

<p><img src="http://jjgod.org/document/images/safari-decode-error.png" alt="Safari Decode Error" /></p>

<p>这是在打开 <a href="">http://att.newsmth.net/att.php?p.719.214628.536.png</a> 这样的图片链接时，Safari 错误的判断了这个图片文件的文件名造成的。而为什么会有这样的错误判断呢？</p>

<p>其实 Safari 使用的是 <a href="http://developer.apple.com/cocoa">Cocoa</a> 框架 <a href="http://developer.apple.com/documentation/Cocoa/Conceptual/URLLoadingSystem/URLLoadingSystem.html">URL Loading</a> 架构中的 NSURLResponse 类的 <a href="http://developer.apple.com/documentation/Cocoa/Reference/Foundation/Classes/NSURLResponse_Class/Reference/Reference.html#//apple_ref/occ/instm/NSURLResponse/suggestedFilename">suggestedFilename</a> 方法实现的。</p>

<p>而这个方法，其实就是解析 HTTP 首部中的 <a href="http://www.ietf.org/rfc/rfc2183.txt">Content-Disposition</a> 域里的 filename 部分完成的，比如下面这个首部:</p>

<pre><code>$ curl -I http://att.newsmth.net/att.php?p.719.214628.536.png
HTTP/1.1 200 OK
....
Content-Disposition: inline;filename=&amp;#892;&amp;#428;_6.png
....
</code></pre>

<p>显然这是乱码，可奇怪的是，这和我们在上面的图中看到的乱码又不一样，这是为什么呢？</p>

<p>假如将它作为 GBK 来解码就清楚了:</p>

<pre><code>$ curl -I http://att.newsmth.net/att.php?p.719.214628.536.png | iconv -f gbk -t utf-8
HTTP/1.1 200 OK
....
Content-Disposition: inline;filename=图片_6.png
....
</code></pre>

<p>哦，原来是 GBK 编码的“图片_6.png”，可是这个文件名怎么会变成开头图片中那种形式的乱码呢？其实写一段 Cocoa 程序就可以发现:</p>

<pre><code>#import &lt;Foundation/Foundation.h&gt;

int main()
{
    const char *bytes = "图片_6.png";
    NSString *str = [[NSString alloc] initWithCString: bytes
                                             encoding: NSASCIIStringEncoding];
    NSLog(@"str: %@", str);
    [str release];

    return 0;
}
</code></pre>

<p>(用 GBK 编码保存) 这个程序的执行结果就是输出开头那段乱码，原来 NSURLResponse 把 Content-Disposition 中的 filename 当成 ASCII 处理了，怪不得会乱码。</p>

<p>可是也不能怪 NSURLResponse，毕竟服务器没有提供任何编码的信息，而 RFC 2183 中也明确说明，不应该在 filename 中使用任何 ASCII 以外的字符，用了就是后果自负了。</p>

<p>那假如我们要写一个自己的客户端 (或者尝试修正 Safari 的错误行为)，该怎么修正已经被按照 ASCII 错误解码的 NSString 呢？</p>

<p>因为 NSString 本身是按照 UTF-16 编码的，所以如果逐个字符地观察这个错误解码后的 NSString:</p>

<pre><code>int max = [str length];

int i;
for (i = 0; i &lt; max; i++)
{
    unichar ch = [str characterAtIndex: i];
    printf("%x ", ch);
}
</code></pre>

<p>我们可以得到:</p>

<pre><code>cd bc c6 ac 5f 36 2e 70 6e 67
</code></pre>

<p>这样一串输出，<code>5f 36 2e 70 6e 67</code> 就是 <code>_6.png</code>，比较好认，前面的 <code>cd bc c6 ac</code> 是什么呢？一查，原来是“图”和“片”这两个字的 GBK 编码。</p>

<p>这就好理解了：NSString 一开始把一段 GBK 编码的字节流<em>逐个字节地</em>按照 8bit-ASCII 处理了，原本 10 个字节对应的是 7 个字符，结果被错误地解码为了 10 个字符，所以我们要把它转换回去，首先是要还原回原来的那段字节流:</p>

<pre><code>int max = [str length];
char *nbytes = malloc(max + 1);

int i;
for (i = 0; i &lt; max; i++)
{
    unichar ch = [str characterAtIndex: i];
    nbytes[i] = (char) ch;
}
nbytes[i] = '\0';
</code></pre>

<p>然后再将这段字节流按照正确的编码 (GB18030) 处理:</p>

<pre><code>NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(
    kCFStringEncodingGB_18030_2000);

NSLog(@"nstr: %@", [NSString stringWithCString: nbytes
                                      encoding: enc]);
</code></pre>

<p>结果果然得到了正确的输出:</p>

<pre><code>2008-02-17 06:09:46.408 test[14095:10b] nstr: 图片_6.png
</code></pre>

<p>同样的逻辑可以用在很多类似的乱码情形中。完整的代码可以在这里下载: <a href="http://jjgod.org/code/test-str-encoding.m">test-str-encoding.m</a></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.jjgod.org/2008/02/17/cocoa-nsstring-decoding-error/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

