發表文章

目前顯示的是 二月, 2011的文章

設定 apache2 和 django 壓縮輸出內容

Google Page Speed 分析後, 發現 javascript 和 css 可以壓個七八成, 實在滿可觀的, 就試著來設壓縮。官網 mod_deflate 看看就會設了, 下面的範例是壓縮 css 和 javascript:
AddOutputFilterByType DEFLATE text/css text/javascript application/javascript application/x-javascript 可以查 MIME 列表, 看要壓那些類型的檔案。或是先設全部都有, 再加條件不壓圖。

比較擾人的是, 早期的一些瀏覽器不能正確處理壓縮文件, 官網教學說要這麼設:
BrowserMatch ^Mozilla/4 gzip-only-text/html BrowserMatch ^Mozilla/4\.0[678] no-gzip BrowserMatch \bMSIE !no-gzip !gzip-only-text/html 說明如下:
The third BrowserMatch directive fixes the guessed identity of the user agent, because the Microsoft Internet Explorer identifies itself also as "Mozilla/4" but is actually able to handle requested compression. Therefore we match against the additional string "MSIE" (\b means "word boundary") in the User-Agent Header and turn off the restrictions defined before.

剛看始看看不懂, 後來看到 Internet Explorer User Agent Strings 才知道 IE 會自稱 Mozilla/4, 但它可以處理壓縮, 所以要再加第三行取消前兩行的限制。How To: Optimize Your Apache Site with Mod Deflate
文末提到 IE6 聽說…

MySQL 將資料塞到 memory 的作法

要加快取資料的速度, 沒有別的方法, 不是先將常用的資料塞到記憶體裡等待查詢, 就是準備好 cache 並先查詢常用的 query, 將結果存在 cache 裡 (俗稱 warm up), 之後再查就會快了。query cache 是 MySQL 能如此快速的原因之一, MySQL 執行 query 前會先查 query cache, SQL 內容一字不差的話, 就直接取值來用。

事先將資料塞入記憶體的作法有幾種, 目前最常用的兩招是:
資料不大的話, 就開個 table 用 MEMORY engine 存, 記得將 max_heap_table_size 設大一點。若嫌 MySQL 重開後要重填資料很麻煩, 可以先將資料存在 my_table_on_disk, 照以下步驟產生資料, 三個 SQL 而已:CREATE TABLE my_table_in_memory LIKE my_table_on_disk;ALTER TABLE my_table_in_memory ENGINE = MEMORY;INSERT INTO my_table_in_memory SELECT * FROM my_table;若資料很大或是某些欄位無法存到記憶體裡, 就改對常用的幾個欄位建 covering index。若 engine 能用 MyISAM 的話, 就能用「LOAD INDEX INTO CACHE my_table_on_disk」事先載入 index 到記憶體裡。使用 MEMORY engine 的注意事項: 注意 varchar / char 的長度限制, MEMORY engine 沒有 varchar, 會自動轉成 char, 沒設好可是很揮霍的。用 MEMORY engine 時, 沒指定 index type 的話, 預設用 HASH 而不是 B-Tree。用 = 或 IN 查詢時應該會比用 B-TREE 快, 不過重點是用 HASH 比較省空間, 不管欄位大小為何, hash 後都是一樣大的。但是 HASH 不支援 range query。用 covering index 的注意事項: load index into cache 不是永久性的, 資料有可能被其它 table 的 index 擠走。在意的話, 最好設多個不同的 key cache, 將不希望…

讓 vim 的複製貼上和其它 terminal 以及 Windows 共用 clipboard

今天從同事 P 那學到的。

目的是用 Windows 開 putty 連 Linux 工作站時, 可以在 screen 內跨 window 共用 clipboard, 也可以和 Windows 共用。比方說將程式碼貼到 Windows 下的 Gmail 時, 原本要先關掉 vsplit 並 set nonu, 才能用滑鼠正確選出要的內容, 接著貼到 Gmail。若能共享 clipboard 的話, 就能在 Linux 的 vim 內按個 20yy 複製, 回到 Gmail 裡按 ctrl+V 貼上 20 行內容。

作法如下:
Windows 下要安裝 Xming X Server for Windows。裝好啟動後, 功能表旁會有個 X 的小圖示。設定 putty: connections -> SSH -> X11 -> Enable X11 forwarding。在 bash 下執行 xterm 測試看看, 成功的話會在 Windows 跑出一個 xterm。重開新的 screen, 這時應該可以透過 "+ 複製貼上了。也就是說, "+yy 後, 可以到別的 screen 下其它 window 下用 "+p 貼上。也能在 Windows 下用 ctrl+c / ctrl+v 互通。若要省掉 "+ 的步驟, 要將 clipboard 和 vim 預設 register 設成一樣的, 設法是 :set clipboard=unnamed另外, 可以用 :reg 或 :di 顯示目前所有 register 裡存的東西, 搜 vim register 可看到一些相關介紹。

2011/02/18 更新

補充 Vim tip: Accessing the system clipboard
2011/07/13 更新

注意: vim 編譯時要支援 +clipboard 才行, 可用以下的方法檢查:
$ vim --version | grep clipboard 若有看到 +clipboard 表示有支援, -clipboard 表示沒有。Ubuntu 下要裝 vim-gui-common 才會支援, 光裝 vim-common 不會包含 +clipboard。或是 :set showcmd 時, 看看按了 "+ …

Python 取 attribute 的規則以及 descriptor

這其實頗複雜的, 還有一些細節摸清楚後應該很有意思, 先記下目前理解的程度。

基本認知: 在 Python 的世界裡, everything is object, 包含 type (class) 也是 object, 一些基本型別如整數、浮點數、字串也是 object (我個人對於這點頗感冒的, 效率變差卻不會方便多少)。Python 2.2 後採用 new style class, 也就是所有 class 都要繼承 object, 像是寫成 "class NewStyle(object):", 而寫成 "class OldStyle:" 就是舊式寫法 。 Python 3 裡則是只有 new style class, 寫成 "class A:" 等同於 "class A(object):"。new style class 才能使用 descriptor, 以下討論的行為都是 new style class。
物件實際取用 attribute 的順序對於物件 x 來說, x.a 實際取到的物件, 會依下列順序執行, 直到成功取得物件為止:
取得 x 的 data descriptor a取得 x 自身物件的屬性 (即 x.__dict__['a'], __dict__ 是 dict)取得 x 的 non-data descriptorraise AttributeErrordata descriptor 是一個有實作 __get__, __set__ 的類別產生的物件。另有 __del__ 可以實作, 這三者分表在這三種情況被呼叫:
x.ax.a = ...del x.anon-data descriptor 只有實作 __get__, 可以被 x.a = ... 取代掉。

Python 找 descriptor 的順序是
type(x).__dict__['a']往 type(x) 的父類別找...property、method、classmethod、staticmethodproperty 是產生 descriptor 的 helper function。method 是 non-data descriptor 的一種例子, 換句話說, 物件的 metho…

Python 移掉 unicode 裡的 control code

先貼 code 再說:
ctrl_ords = range(32) # 取得所有不能顯示的字元和 '\n' 以及 TAB ctrl_ords.remove(ord('\t')) # 去掉 TAB ctrl_char_map = dict.fromkeys(ctrl_ords, None) # 建立對照表 line = line.decode('utf8').translate(ctrl_char_map) # 用 translate 移掉對照表裡的字元 str 和 unicode 的 translate 用法不同, 學 unicode 應該就夠了。unicode 版的 translate 要求傳入一個 dict, key 必須是 unicode ordinals, 沒注意到 "ordinals", 一直試都沒效果。value 可以是  unicode ordinals, strings 或 None, None 表示要刪掉該字元。

相關參考資料:
ASCII Table and Descriptionstr.translateord

用 XOR 檢查加法後是否有溢位

看 Python intobject.c 時看到的:
// intobject.c static PyObject * int_add(PyIntObject *v, PyIntObject *w) { register long a, b, x; CONVERT_TO_LONG(v, a); CONVERT_TO_LONG(w, b); x = a + b; if ((x^a) >= 0 || (x^b) >= 0) return PyInt_FromLong(x); return PyLong_Type.tp_as_number->nb_add((PyObject *)v, (PyObject *)w); } 上面這段的
if ((x^a) >= 0 || (x^b) >= 0) 是在檢查是否有溢位, 看一陣子才想通, 概念如下:
兩個正數相加變成負數表示溢位兩個負數相加變成正數也表示溢位除了這兩者外沒有其它情況綜合上述的條件, 可以簡化成: 兩數相加後的正負號和原本兩者都不同 <---> 溢位目前 CPU 都採用二補數系統, 最高 bit 可看作是 sign bitXOR 剛好可以滿足簡化的條件, 其它 bit 無關緊要, 運算完看 sign bit 即可位元運算的世界真神奇啊, 可以省下不少工。