顯示具有 System 標籤的文章。 顯示所有文章
顯示具有 System 標籤的文章。 顯示所有文章

2011年1月8日 星期六

撰寫資料庫相關程式的心得

我是用 MySQL + Django,處理的資料量有小有大。資料量大的情況下,通常有上萬筆,甚至會到上億筆。相關心得大概分成四類,依實務經驗記錄一下心得。

是否應該使用 ORM?

我是使用 Django ORM,以下指的 ORM 問題可能不適用全部 ORM framework,但我猜大部份應該是半斤八兩。

剛開始不熟 SQL 時,很喜歡用 ORM,ORM 有些學習門檻,不過習慣後用起來相當順,也容易閱讀程式。但是在好寫好讀的背後,卻犠牲掉極大的效率。原因有幾點:

  • 需要大概了解 ORM 產生的 SQL,才知道如何寫出有效率的操作。比方說用到 foreign key 時,可以在取物件時順便 join。若沒特別處理,預設行為是參考到關聯物件才取資料,於是取一萬個物件並讀取它們的關聯欄位,就會多下一萬次 SQL。
  • 即使了解 ORM 各項操作避免一些地雷寫法,ORM 不見得能產生最快的操作方式。明顯的缺點是讀寫 N 個物件時,很可能會轉成 N 次 SQL,而不是一次。
  • ORM 為了提供一致的抽象介面,沒有支援各家 DBMS 完整的語法,減少一些最佳化的機會。如缺少批次操作,以及使用 force index、決定 join order、技巧性地用 IN 不用 range query 等。
  • 即使 SQL 沒有問題,產生 object 的時間成本比自己執行 SQL 取資料來得高 (見這篇),資料量大的時候會變成瓶頸。

我一開始寫的專案全用 ORM。第二個寫的大部份用 ORM 但遇到一堆難解的效率問題。第三個寫的開始刻意減少 ORM 操作。最後則是全面禁用 ORM。原因很簡單,弄懂 ORM 操作並做最佳化的時間,比直接寫函式封裝 SQL 操作多,而且最後達成的效率又較差。除此之外,複雜的 ORM 操作可能有 bug 或是令人誤會,導致取出不對的資料,看 ORM 產生的 SQL 才明白問題出在那。

愈懂 MySQL 後,愈覺得 ORM 不順手,最後就改成寫模組封裝 SQL 操作。結論是,若有意願硬啃 DBMS 相關知識的話,將時間投資在所用的 DBMS 上,會比學習 ORM 操作和理解背後運作方式划算。

也許有人會質疑不用 ORM 會增加換 DBMS 的成本,我沒這樣的經驗不清楚用了 ORM 能省下多少成本,相較於前述的問題,整體來說是否划算。至少我會選擇先專精一個 DBMS,還有自己寫模組隔離應用層邏輯和資料庫操作,減低轉換 DBMS 的成本。

Database migration tool

雖然我上面將 Django ORM 說得很慘,但是用 Django ORM 搭配 South 到是滿不錯的。South 是 Django 的 migration tool,提供一個框架維護資料庫的變動,並且可以偵測 Django model 的變化,產生對應改變 schema 的操作。在說明 South 的優點前,要先談談為何需要用 database migration tool。

使用 database migration tool 有兩個好處:

  • 記錄目前這版程式用的 database schema。既然程式碼需要版本記錄,database schema 當然也要一併記錄,才能確保每版都能正常運作。
  • 方便其他組員更新資料庫。更新程式碼後執行 database migration,就能擁有和其他人同步的資料庫。

當然,有很多方式可以達成以上目的,像是每次更新 schema 就 dump schema,並存成一個 SQL 檔存在 VCS 裡。我沒這樣做過,不知會有什麼大問題。目前只想到幾個小問題:不方便多人同時修改 schema,之後要 merge schema 可能會比較麻煩,特別是改到同一 table 時。不方便追踪 schema 各步的轉換,像是加入 table A、B、C 以支援功能 X。但是回頭翻 VCS log 似乎也能滿足這個需求。唯一無解的大概是有些情境拆開 schema 執行會比較有效率。像是先建好 table、填完實體資料後,再建 covering index。

若改成維護多個 SQL 檔,第一個起始 SQL 產生基本 table,後面的 SQL 都是「schema diff」,則方便多人同時開發。但要人工產生 schema diff 有點辛苦,沒記好每個操作,手動改完 table 後,要回頭比對差別才能寫出 schema diff,容易出錯並增加確認的成本。

除了滿足基本需求外,South 另外提供下列功能:

  • 提供單線前進的 migration 方式。能在各版本之間前進、後退。
  • migration 分成 schema migration 和 data migration。並且提供偵測 Django model 變化自動產生 schema migration 的程式碼。data migration 只是空殼,由工程師自己填程式碼。
  • 提供修改 schema 的 API,像是加減欄位、加減 index。

使用 South 的額外好處是,可以避開 Django model 的限制,像是不支援多欄 index、不支援使用不同的 MySQL Engine。用 South 的話,只要自己在 schema migration 裡用 alter table 修改即可。

不清楚別家 database migration tool 怎麼運做的,感覺這方面的工具有很大的發揮空間,值得了解一下各家工具提供的功能。目前遇到的最大困擾是,無法明確看出那些 migration 有相依關係,更新資料或程式時,不方便只執行有影響到的範圍,若更新在很前期的 migration,就得回溯到前面再重跑。

包工具箱

將資料庫操作和應用層邏輯分離的好處應該不用多說,使用統一的介面有其它好處,目前覺得最實用的是可以寫 try catch 自動記下所有出錯的 SQL,再依參數決定要吃掉 exception 或丟回應用層。由於出錯的 SQL 都有被 log,程式出錯時可以馬上找到有問題的 SQL,縮短除錯時間。

單元測試

我原本是用 Django 內建的方式重建測試資料庫,但是最近開始用 multiple database 後,遇到一些問題。由於我在 South 裡做了一些不合 Django 規定的操作,不想花時間理解 Django model 和 test 詳細的運作方式,最後決定自己寫簡單的模組來建置測試環境,速度也會比較快。還在小規模的試用中,看看之後能不能投多點時間打穩這塊,再來寫心得。

2010年2月10日 星期三

觀察實驗資料和畫圖表的小技巧

之前在《減少操作實驗浪費的時間》提到一些做實驗的小技巧,方便自動化重覆實驗、觀察結果和產生圖表。最近實驗做得比以前更多,意外發覺更好用的方式 。有需求就會進步,這是工程師的宿命啊!

主要的改變有三點:

  • 用 Python 寫程式執行實驗。Python 功能比 shell script 強上不少,也方便維護和增加功能。「Can I use Python as a bash replacement?」提到這樣做的好處和簡單的實施要點。什麼?你看了上篇文章發現我好像用 Ruby 較多?這...總之我跳槽了。男子漢做事,有時是不需要理由的!
  • 改用 SQLite 當資料庫。使用 local database 至少有兩個好處:每次實驗都重建一個新資料庫,方便保留不同實驗結果;少掉煩人的設定,可以更彈性地使用。實驗後可以用 sqlite3 看內容,或另寫程式下 SQL 彙整結果。若有架 Wiki,直接將結果輸出成 Wiki code 也不壞,容易加上顏色、粗體和表格。
  • matplotlib 畫圖。matplotlib 是一套 Python 繪圖函式庫,能畫長方圖、折線圖、直方圖等多種類型圖片。更重要的是,它畫得還挺不賴的 (見官網範例)!既可以在 matplotlib 內建的應用程式裡看結果,也能存成 PNG 檔。依我個人過去用 gnuplot 的經驗,matplotlib 好用許多。不過這可能取決於使用者有多熟悉 Python。若你也喜歡用 Python,matplotlib 無疑是最好的選擇。「Tools I use: matplotlib」提出相似的見解,有興趣的人可以參考看看。

不論是 SQLite 還是 matplotlib 都有嚇死人詳細的文件,配合範例程式學起來挺輕鬆的。目前唯一的不便之處是,當實驗數據更多時,有時只想看部份東西,再一步步看不同層面。若一口氣把全部資料畫成圖表,不容易閱讀。有空時想來研究看看 Django (殺雞用牛刀嗎?),看能不能寫個簡單網頁,做為互動呈現數據的介面。反正資料存在 SQLite 裡,容易用各種方式存取資料。

2009年4月22日 星期三

強化 Python 在 Vim 裡的顏色

我習慣用 putty 連 Unix server 開 screen,再用 vim 寫 Python。這篇記錄如何改善 Python 的顏色。

啟動 256 色 terminal

首先將可用的色彩數增加為 256 色,先確定 putty 為新版 ( 舊版 putty 沒支援 256 色)。接著參照《讓 Vim、Screen 支援 256 色》將 Screen 和 Vim 設好,記得先用文末提到的 Colortest 測試是否有符合 256 色,成功的話,數字 0 ~ 15 為原本的 16 色,16 ~ 231 為新的顏色 (6 x 6 x 6),232 ~ 255 為新的灰階色。可配合 Colortest 看到數字值和顏色。

這裡備忘該篇提到的步驟:

  • 在 ~/.vimrc 加入:
    1
    
    set t_Co=256
  • 在 ~/.screenrc 加入:
    1
    
    termcapinfo xterm 'Co#256:AB=\E[48;5;%dm:AF=\E[38;5;%dm'

更新 Python script 偵測的格式

更新 syntax/python.vim,讓 Vim 偵測出更多種格式,像是行末多的空白,或是空白行有含空格都會被偵測出來。做法如下:

  1. 下載最新的 python.vim 並放到 ~/.vim/syntax/ 下。
  2. 編輯 ~/.vimrc,加入
    1
    
    let python_highlight_all = 1

    以顯示所有 python.vim 有偵測的格式。參照 python.vim 開頭的註解,了解細部選項。

替換顯示的顏色

  1. 下載 Vim color scheme: Wombat256.vim,並放到 ~/.vim/colors/ 下。
  2. 在 ~/.vimrc 裡加入
    1
    
    colorscheme wombat256

如此一來就有漂亮的顏色啦,wombat256 的 screenshot 見這裡

備註

這個網站有提供許多不同的 color scheme screenshot,可惜沒附 Python 的 screenshot。

2009年3月8日 星期日

裝了 ScribeFire Blog Editor

由於 Windows Live Editor 對 WordPress 的支援不夠完整,這篇改用 Scribefire 試看看。

Scribefire 也有很炫的預覽功能,而且多了可以將網頁的標題和連結取出加入編輯內容內,挺方便的。Category 部份到是有支援一半,可點選要加入那些目錄,但沒有顯示出原本目錄的階層關係。唯一的缺點是不能加入<!–more–>。或許之後可以改用 ScribeFire 看看。

Update

ScribeFire 也加了部份討厭的 tag,像是 <br> 和 <div>,這樣日後要回頭手動編輯時,文章內容挺醜的。

裝了 Windows Live Writer

剛才不小心關掉網頁而遺失了正在寫的文章,一怒之下就裝了 Windows Live Writer。現在這篇就是用它來試寫。

初步用起來還挺方便的,不過每打一個字畫面就閃一下,感覺挺怪的。還有不能插入 WordPress 專用的一些 tag,得自己切到 Source mode 輸入(例如<!—more—>)。 Preview mode 看起來挺屌的,可以直接看到文章送出後,在自己的 Blog theme 下看起來是什麼樣子。

Update

Windows Live Writer 竟然加了多餘的 tag,像是 <p>,而且不能用<!—more—>,發文章時找不到選 category 的地方,只有看到加 tag。改來試用別套好了。

2009年1月11日 星期日

知識管理工具 (3)

( 前兩篇見這裡:第一篇第二篇。)

最近的使用習慣變成 Google Notebook + Dokuwiki + BBS + Plurk。。

我對工具的基本要求是在任何地方都可以存取以及容易備份,再來是考量輸入和閱讀的便利性,以及資訊的流通性。這四項工具中,Google Notebook 和 DokuWiki 是方便個人維護知識,但流通性差,不易和其他人互動,自然也難以得到回饋;後兩者則相反。下面各別簡介我的用法:

  • Google Notebook 操作超方便的,記錄條列式訊息比 Wiki 還方便,會自動存檔,按 Tab/Shift+Tab 可以 加深/減少 條列項目的層級,可以輕易地管理權限和分享給限定的人士。用來存暫時用到的資料,如待看書單、未整理清楚的隨手筆記、todo list。
  • 自己架的 DokuWiki 則是存技術性文章(像是架 server、Unix commands、programming language 筆記),供日後方便索引。Wiki 的好處是版面排列彈性極大,可視需求附加功能,方便貼 code,並含 syntax color。DokuWiki 的預設顯示和編輯介面,可說是我用過的系統裡最棒的(其它用過的有 Google SitePmWikiTWiki)!不需做任何更動即有 section editing、code syntax、以及簡單好用的編輯介面。加上是 text file db,把整個目錄 tar 起來就能備份。
  • 我一直覺得 BBS 是個很怪的平台,相當不適合儲存資訊,但它的極快操作和極簡單的閱讀介面卻是 Web 目前無法取代的。我用 BBS 存粗糙的心得,日後也能回頭索引,還有能和其他人分享及得到回饋。
  • Plurk 是最近剛開始玩的,真是理想的碎碎念平台,輕易地和分散各地的朋友串起來。類似 IRC 的感覺,不過是每人各自形成一個聊天室,使用者可同時看到所有訂閱的「聊天室」內的訊息匯入自己看的頁面。加上簡單易用的介面,輕楚的時間軸表示,比 IRC 親切多了。好處是當有疑問想請問朋友,卻不知問誰時,可以輕易地和所有人待上線。目前似乎沒有搜尋訊息的功能,有的話就方便存片段資訊了。

至於以上沒提的 Blog,仍然用來做為整理長期整合的心得,或是記錄人生的片段。除非極有分享的必要(例如網路上很少這類資訊),或是較適合文章形式的表現,才會寫在這裡吧。而 bookmark 部份,我已很少用 delicious 了,原因是存取不夠迅速,我覺得 bookmark 應該要像本機 browser 存取一般才適用。目前暫時改用 Google Bookmarks ,裝 Google Toolbar 後就可取存,介面雖然簡單,操作卻相當快速。由於我很少會回頭點 bookmark,反而較常點存在 Google Notebook 和 Wiki 裡的超鏈結,暫時還不確定怎麼維護 bookmarks 較適當。

2008年3月16日 星期日

Google File System

最近 Google 在推 MapReduce 這個平行計算 framework,讀完 paper 後,覺得滿有意思的,若有些 network programming 和 functional language 的基礎,讀起來應該滿輕鬆的。除了好奇之外,一方面也是想讀點技術性的論文,看看和平常讀的 data mining、information retrieval 論文有什麼差,又找了 GFS 的 paper 來讀,結果還滿有趣的。

先提個技術無關的事,這篇的 Acknowledgments 最後一句寫著:

Many of our colleagues at Google bravely trusted their data to a new file system and gave us useful feedback.

令人會心一笑。

這篇論文一開始先說明作者的需求。依他們的使用環境,提了些使用上的假設,像是硬碟常壞掉、設備不可靠,可是 file system 的可靠度是首要目標;random write 少、append 多;還有 small random read、large sequential read。接著依這些操作特性,自訂需要的 file system,對我這類看重實務面的人來說,這種開頭很合我的喜好,有些學術性論文討論的是尚未存在的需求,較難接受作者的假設。描述整篇論文太累了,這裡摘要一些我認為有趣的設計:

  • GFS 是架在 Linux file system 之上的 file system,這樣做的好處是善用Linux既有開發,簡省開發時間。雖然作者也提到因為Linux kernel bug,使得系統有些不穩,逼迫他們自行改 Linux kernel,整體來說,作者認為這個決定是正確的。我原本還以為GFS會自己重弄一個file system。
  • GFS的主要目的是穩定和處理大量資料,所以分散式系統是理所當然的設計。但有趣的是,GFS 採用 single master server,理由是設計簡單
  • GFS由 one master、many chunkservers、many GFS clients組成。
  • 為了達到single master,整體設計做了許多對應措施,如盡可能減少master的負擔,GFS client直接和chukserver拿資料;要寫入資料時,也是chunkserver之間互傳,master只記meta data。
  • 為了讓 meta data能全塞入memory,metadata格式很簡單,並有做 file path 的 prefix compression。實驗部份指出上百TB的data,meta data只占數十MB
  • 沒有「目錄」的存在,所有檔案的是用絕對路徑表示,這樣做的好處有:省下目錄的資料結構;可以同時多個client新增同一目錄下的檔案,沒有目錄,自然不需要對目錄要write lock(但「目錄」仍然有 read/write lock,用在別的場合)。
  • 整體採用duplicate data確保availability,chunkserver有存各個data block的checksum,送出資料時有先確認沒有損毀,確保reliability。
  • 不同檔案可以有不同的replication factor,預設值為3;常被使用的執行檔可以設為上百,避免同時多個application client用到而造成bottleneck。
  • 寫入檔案時,為確保各個replication一致,做起來不簡單;master會指派一個chunkserver負責資料更新。值得注意的是,由於寫入動作的複雜度,有時會先等一會,再批次處理對同一檔案的不同寫入。
  • 更新資料分兩部份:資料流會依chunkserver相對位置傳,並把資料切成數小塊,行成一直線的pipeline傳資料,減少傳輸的lantency
  • 接著由master指派的chunkserver指示所有有關的chunkserver用同一順序寫入資料,確保即使同時有多種寫入同一資料的操作,寫入完後同一份資料在不同chunkserver上仍然一致。
  • replicate data時,不止要考慮放在不同chunkserver,還要放在不同rack,使得swtich壞了或某機房停電時,仍能保證資料的存取。
  • master待load較輕時,會在background簡查metadata的正確性、data replication是否有達到正確的數量,並依確少的程度補救,比方只剩一份replication的優先性比剩兩份大很多。
  • master若掛了,外部的monitor會發現,重新開一個master (一分鐘內即能完成)
  • 為了確保master掛了也沒問題,所有master的操作都是先將log寫入disk後,才正式執行。加上log很精簡,master重新啟動載入log不需多少時間。
  • 事實上,不管是master還是chunkserver,都沒有「停止」的指令,直接kill即可。它們都是設計成可以隨時掛掉,隨時快速複活
  • 刪除檔案即在master內將檔名改為特殊名稱並隱藏起來,仍可讀取和復原;待一段時間(三天)後,master會在background執行的garbage collection中正式清掉標記為刪除的檔案,好處是減少master短時間的high load,還有避免使用者犯錯,壞處是disk space可能實際上夠卻無法拿來使用。
  • chunkserver若發現檔案無法在master內查到meta data,即表示檔案已被砍了,減少master和chunkserver互相sync meta data的問題。master則是在新啟動時,向所有chunkserver要資料,減少master記錄的負擔。
  • 雖然GFS沒實作POSIX,卻有另外提供特殊功能:append record和snapshot
  • append record常用在 many-to-one producer-consumer queues。append可以同時對同一檔案操作,write則需要指定offset,不能同時執行。
  • snapshot指複製某個namespace下的所有檔案 (e.g. /home/www ),snapshot採用類似 copy-on-write 的設計,沒被寫入的data chunk不會被複製
  • chunk有reference count,當chunkserver發現reference count > 1又被寫入時,就會先複製一個新chunk,再把reference拆開,並更新各自的reference count。透過reference count達成copy-on-write的設計很漂亮,為了避免snapshot途中檔案有變(e.g. 多了新檔案),執行snapshot時會要求該namespace下的write lock。
  • shadow master以慢一點點的時間達到和master一樣的狀態,當作 read-only master,減輕master負擔。

整體來說,這篇論文相當有意思,許多設計都是簡單易懂,概念看來也很實用。唯一奇怪的是,實驗部份的表現看來不太好,還有我看不懂部份實驗說明,概念和設計細節都懂,反而是實驗看不懂,這到是很少碰到的情況,怪哉。

2008年1月25日 星期五

減少操作實驗浪費的時間

分享一下之前做實驗時發展出的小技巧,我這裡指的是跑程式的實驗。花點時間研究一些工具,可以剩下不少重覆執行的動作。

首先,畫圖方面 gnuplot 是最好的選擇,用法很簡單,google一下學個基本,之後要用什麼特殊指令,去 Demos and Screenshots 裡找符合的圖,將範例code抓下來試一試,改一改就會用了。看到常用的指令或參數,就到 DocumentsIndex 裡找詳細說明(比方查 xrange 的用法),減少試誤的時間。

gnuplot 最大的好處在於批次處理,初期費些工夫寫出滿意格式的 gnuplot code,接著就可以把所有圖表套用一樣的格式,想變更格式時,比方加格線或放大字型,只要改一份 code,所有圖表可以一同更新,這是 Excel 難以做到的,也許 VBScript可以,但學習代價應該會比 gnuplot 高。若會寫 shell script或scripting language如Perl、Python、Ruby、PHP,可以配合script和寫好的gnuplot code,執行一個程式讀入不同的資料檔,即可重畫所有圖表,這點 Excel 更不方便達成。配合 script 還可以自動轉成 LaTeX 用的圖檔格式。若不滿意 gnuplot 預設 EPS 的風格,像我較喜歡預設 PNG 的話,可以配合圖檔轉檔軟體,可以輕易地批次處理,像 Linux、FreeBSD上可以用 convert。做實驗時常要重畫圖表,很少能一次搞定,初期投資些時間在 gnuplot 和批次處理程式上,絕對會回本的。

若想再進一步自動化的話,可以將實驗結果存到資料庫裡,不要存到普通檔案裡。花點時間研究如何用 scripting language 或自己慣用的程式語言操作DBMS(如MySQL),看要在實驗結束時程式直接將結果寫入資料庫,或是先寫入暫存檔再另用別的語言 (例如直接用 MySQL script)將結果寫入資料庫。於是,透過 DBMS 網頁介面的軟體(如phpMyAdmin),可以輕易地觀察實驗結果,像是依時間排序資料、依數據大小排序,或要算平均、標準差等,都輕而易舉;要輸出成 gnuplot 或其它程式的輸入格式,也是非常容易。

最後,跑實驗的程式最好寫成從命令列讀參數,或讀一個設定檔設定參數,減少重新編譯的動作,也方便批次實驗不同參數。

總結一下,我自己的做法是:

  1. 實驗用的程式從命令列讀參數。
  2. 其中一個參數決定要將實驗結果直接輸出(STDOUT) 或寫入 MySQL。有時候做些小更動想看看實驗有什麼差別,不想塞太多資料進資料庫弄亂原有資料,可以下參數讓程式不要寫入資料庫。
  3. 用 shell script 寫好測試用的批次檔,會輸入不同參數給實驗用的程式,產生所有要的結果。
  4. 裝 phpMyAdmin,方便分析實驗情形,以及輸出 gnuplot 要求的輸入格式(用TAB分隔)。
  5. 寫好 gnuplot 的 code,我不知道怎麼在 gnuplot 裡使用變數,讓它能配合shell script對畫圖作細部調整(如更改輸出檔檔名),所以我改用笨一點的做法,將gnuplot code存成字串,用Ruby配合不同變數產生有點不同的 gnuplot code 到文字檔裡,再執行 gnuplot 讀入新產生的 code 以符合細部調整。
  6. 寫個簡單網頁顯示 gnuplot 輸出的 PNG 檔,方便用圖形觀察各組數據的差異。再寫個 script 利用 convert 把所有 PNG 檔轉成 EPS,確保論文裡的圖檔和我想要的樣子一致,但會犠牲向量圖檔任意放大的優點。

上述的方式我試過幾次,幫我省下不少時間,第一次試用時間投資就有回本,更不用說第二次之後的收益了。舉例來說,我其中一個實驗要求是記錄演算法各段落執行的時間,想配合各種不同資料量,判斷演算法的子項目平均時間差多少。但用 profiler 會拖慢執行速度,我只想記錄幾個主要步驟而已。這時輸入到 MySQL 變得相當順手,執行一次批次檔,上床睡覺,隔天早上下個 SQL 做平均,就可以看出差異。找出關鍵的部份後,再下 SQL 選出關鍵資料的細項,看看資料分佈的情況,有助於了解情況。想想看,若不用自動化實驗和資料庫來呈現數據,前述動作有多麼冗長無味,你會想重覆幾次這樣的事?更不用說集中精神分析結果和思考改進方式了。

2007年9月24日 星期一

VIM-LaTeX

官網:http://vim-latex.sourceforge.net/

下載和安裝說明:抓下壓縮檔、解開到~/.vim下(Un*x)或~/vimfiles(Windows),就這麼簡單。

這玩意兒真是太強了,之前自己key那堆符號是key心酸的。place holder的概念真不錯,打完該打的字後,按個Ctrl+j就能跳到下個位置,像插入Figure時感受特別明顯,打個EFI後,就能一路填完檔名、標題、索引名稱等。還有以 ` (反單引號)開始的縮寫字,像是 `/ 會變成分數用的 \frac{}{}, `* 變成乘法 \cdot,省不少工。愛惜手指,才能用更久啊!

其它像插入reference也是超方便,會先列出各節內的label,游標移上去按個ENTER就自動加進去了。若要發揮更完整的力量GVIM才是王道啊,開始考慮要不要移回Windows環境用LaTeX,之前習慣在Un*x server上做事,自然地也在上面用LaTeX了。

2007年7月20日 星期五

MySQL偽memory leak問題

Problem

我用的server是Debian 64bit (AMD64), DB server是 5.0.32,有8G memory,但MySQL使用一陣子後,用top和free會看到8G的memory都被吃掉,但沒有任何process用到這麼多memory,而且swap沒有被用到,關掉MySQL daemon後memory的用量也沒改變。

Solution

查到兩篇類似的苦主:

從第二篇裡找到解法:

Despite the fact that “top”, “/proc/meminfor”, “free” show me that 98% of all memory on server is used that memory is not really used by MySQL nor kernel (as I can see from /proc/slabinfo).

I wrote simple C app. which tries to allocate as much memory as possible calling malloc() in a loop I found how much free memory _really_ available. Looks like it is Linux reporting problem, but same time this _only_ happen to me with memory previously used by MySQL server. I can see memory returned back to free memory pool as soon as other applications exit.

上面說是top和free報錯數據,MySQL query結束後,query用掉的memory有還回去,但top和free的統計數據裡卻沒有減少。

我也寫了個 C app來試,如他所言一般,程式結束後memory回來了,但查了半天找不到單一process的maximum memory usage定義在那,有人說在limits.h裡,INT_MAX就是maximum memory,但顯然是錯的,我設到比它大的值,anyway,下面是我「要回」memory的 code,因為設到15*會超出上限被killed,只好設12*並同時跑多個,但想想這個數字也不太對,它比8G大,但跑起來大概只用了2G吧,不知道process到底怎麼跑的

#include <stdio.h> #include <stdlib.h> enum { MAX = 12000000000 }; char s[MAX]; int main(void) { int i; for (i=0; i<MAX; i++) s[i] = i; sleep(10); return 0; }

另外聽小豬說在Debian的MySQL 5.1上沒這問題,也許是已修正的bug吧。

備註:query cache相關指令

http://dev.mysql.com/doc/refman/5.0/en/flush.html
http://dev.mysql.com/doc/refman/5.0/en/query-cache-status-and-maintenance.html

The RESET QUERY CACHE statement removes all query results from the query cache. The FLUSH TABLES statement also does this.

還有可以用SHOW VARIABLES查環境設定,像是myisam_max_sort_file_size、max_binlog_cache_size。

2007年5月2日 星期三

知識管理:bbs, wiki, blog, bookmark (2)

上篇為《知識管理:bbs, wiki, blog, bookmark》,前陣子有學弟開始用Wiki,於是來分享近來的使用心得。

這篇重點在寫文章和工具的用法,一樣工具,隨著目的不同,用法會不同,寫文章(筆記)前要先決定讀者為何,這點明確定位後,工具用起來就會很順,反之,定位不清,寫起來只會綁手綁腳。

我目前的心得是bbs,wiki,blog,bookmark都會用到,我的心得不是工具的功能有多強,而是我對這些工具的定位更清楚了,下面描述的都是我的用法,不代表它們就是這麼用的。

使用工具前要先確保兩個重要功能:
1. 全文搜尋
2. 多重分類 (or tag)

再來的議題有:
1. 流通性 (傳播能力,有RSS者較佳)
2. 備份的便利度

比方Blog上述條件全符合,bbs完全不行,wiki的流通性不及Blog。

wiki是寫給自己看的,寫起來快速有組織即可,wiki適合條列編修,反覆修改,內文交互參照,很適合寫筆記和想法暫存,而且像DokuWiki有section editing和folding(plugin),以及headline的sidebar,在wiki page成長後仍保有top-down的可讀性。

lab合作時有用wiki當公告欄放想法,個人想法暫記再從公告頁內開子頁面寫,避免大家頻繁改wiki時造成衝突,試用的結果挺微妙的,似乎有點亂,但滿有用的 ( wiki的特性是可以翻頁面修改記錄,可得知何時誰做了那些改變 )。

blog的流通性最高,用來寫給大家看,寫起來最累,因為對象廣,文章要有組織性,要有背景說明 / 出處參照 / 相關探討 / 文章分類,寫blog有助於組織想法,這種組織和wiki不同,wiki寫給自己看,加上便於修改,組織性比較隨性,blog則有一定受限,像我寫blog摸索一陣子後,就很少開新分類,開一個分類表示我有心在那分類產生後續文章,我在寫blog時的自我要求比較多,像是盡量避免笑臉符號,盡量用通順文章的格式,加強正式表達能力。

bbs則是介於blog和wiki之間的用途,由於看bbs的大多為已認識的朋友,要feedback比較快,而且寫起來比較快,不像寫blog會很在意文章架構,在意語句和段落間的連接性。

bookmark網站的用法還在摸索中,目前只是當URL暫記,說來諷刺,我的研究方向是針對bookmark,但用的頻率最少。

以上不管那一種用法,都有滿多實驗空間,像是讀書心得,在寫成blog前可以放在wiki上暫記,累積到一定的量再集合成文章,但不知怎麼,就是覺得寫在bbs上較順,順便期待在寫成blog前能不能先得到feedback。

另外我覺得開不同的wiki站感覺也不錯,我目前有三個wiki,lab的PmWiki記研究想法,個人的PmWiki暫存舊的,短期間的東西,不在意資訊的組織性,個人的DokuWiki記新的想法,逐漸將wiki架構弄得更明確,最近看《資訊架構學》和《隨意搜尋》有些心得,覺得wiki可以有更多可能,再摸索看看。

另外配合GMail的label + filter可以做到不錯的合作溝通媒介,人多時可以考慮用Google Newsgroup,大家再用GMail訂閱,依我目前的試用情形,三人使用mail溝通很有效率,確保大家都能即時看到資料,重點是要用label + filter將信件自動分類。

如果溝通時需要有行程表之類的長時間記錄,可以考慮用newsgroup或wiki記下來,我傾向用wiki記。

2007年4月16日 星期一

gnuplot:顯示時間軸

xdata有些參數可設,下面的code會以timeformat表示 X 軸,不然光以數字表示 X 軸,200612的下一格不會是200701,資料無法連續表示。

set xdata time set timefmt "%b-%d-%H:%M:%S" set xrange ["Mar-25-00:00:00":"Mar-26-00:00:00"]

timefmt的參數和strftime一樣,可以隨意更改,xrange和輸入的data和timefmt一致即可。

2007年3月31日 星期六

修課心得和對數位系統的心得

修課心得

po 這篇是給大學生參考,另外給自己重新體認學習的方法。我到大學快畢業時才發現自己一舉多得的做事習慣有意料之外的功效,像是把相似概念的課一起修,不僅是簡省時間,而且會加強概念的印證。

建議大家有機會的話,可以把類似概念的課一起修,或一年內連續修完,比方圖學和3D Game Programming、Compiler和Formal Language、OS和網路程式設計、AI + 演化計算 + Data Mining + 類神經網路。雖然會超累的,但效果絕對比分開修更好,可以從實務面和理論面互補不足,當然掛也是一起掛啦。另一修課重點是遊說強者一起修,每們課有個強者互相討論,各門課都會輕鬆一點,有室友一起修也很方便,就近討論效果很好。

數位系統的心得

( 這篇心得寫於 2004/03/20 ,現在我完全不懂這些東西 XD ,用進廢退啊。 )
在大二下時感受特別深,另外,最近終於弄清楚交大資工的定位,我想這有必要另開一篇文章寫出來,以供日後學弟妺們參考。以大二下必修課表來看 組語 / 數位系統導論 / 數位系統實驗 / 電子實驗 / 電子學 雖然有五門必修,是緊湊了些,但彼此配合得真的很好。

電子學講數位電路在物理上運作的原理,為什麼都用NAND? 為什麼用CMOS實作gate? 加上許騰尹老師在講時,會加重提到學這個和資工相關在那裡,學起來很實用。

承接大二上數位電路的課,電子實驗以市售IC在麵包板上直接接線,感受較真實實作的感覺,多少能體會實際用IC時和理論上操作的差異,比方寫布林代數時不會管用了幾個gate(比方not根本是隨便用),也不需考慮線路要怎麼佈置才妥當,實際操作上完全不是這麼回事。

數位系統實驗從另一個角度切入,以模擬軟體操作來設計電路,較接近業界的作法,主題和電子實驗和上學期的數位電路呼應。

數位系統導論,再深一層地介紹數位電路的理論,比方簡單的CPU架構在hardware circuit以什麼形式表現,在寫組語時更有所體會。

組語裡有許多jump指令,需要自行check status flag來決定流程,而不是直觀的if - else (雖然MASM有提供.IF,.WHILE,不過是用巨集作的) 從數位系統導論裡可以了解,為什麼組語會這樣設計,這些指令的意義和低階hardware circuit吻合,從hardware circuit的觀點去看,可以理解組語的運作原理,比方不能”mov MEMORY MEMORY”的原因。

總之,從理論到實際操作,high level到low level,統統一把抓,交互印證,比起單修某幾門課,更是事半功倍。

還有後半學期的課還沒修到,相信陸續會有更多體會,不知道上述的心得,對於接觸過一點點數位邏輯的人,是否能夠理解呢?。

2007年3月11日 星期日

tcsh/bash在command line下用VI編輯

昨天去找Scott(俗稱老光頭)聊Python和Ruby的比較,昨天的談話引起我學Python的興致,等再學一陣子Ruby和Python後再來po心得。

Scott習慣在bash、ipython下都用VI編輯,跟著試用一下,好像也有好處,最近把工作環境也改過來,用一陣子看看會不會較方便。

bash下要設~/.inputrc:

set editing-mode vi # Select vi bindings
set editing-mode emacs # Select emacs bindings (default)

tcsh下直接設~/.tcshrc:

bindkey -v # Select vi bindings
bindkey -e # Select emacs bindings (default)

2007年3月6日 星期二

為什麼要先學C和個體經濟學

這篇是以《給資訊科系學生的建議》為主幹,讀過幾篇Joel文章後的心得,我沒學過個體經濟學,之後找時間來看看。文內都是中譯版的link。

給資訊科系學生的建議

詳見《給資訊科系學生的建議》,快速看看就好,廢話太多。

在畢業前學會寫作

這因人而異吧,不見得要做,我則是挺喜歡的。引用文內的正反例證:

重點是能夠和他人溝通自己的想法。偉大的程式師藉由說服他人而得到影響力。他們撰寫清楚明白的意見和技術規格,讓其他程式師瞭解他們的程式,因此別人可以運用這些程式而不是重寫。如果少了這一點,他們的程式碼就毫無價值可言。他們為使用者撰寫清楚易懂的技術文件,讓大家能瞭解他們程式的作用,這是唯一能讓使用者理解其程式價值的方法。SourceForge (http://sourceforge.net) 裡埋藏了很多神奇有用卻沒有人用的程式。只因為程式的作者寫不出好文章

在畢業前學會C

詳見《回歸原點》,仔得細讀的好文,說明要有底層的概念和分析能力,才能寫出好軟體,而不是用巨型工具寫出一堆搖搖欲墮的高樓。

先學Java這類高階語言,只會嘗太多甜頭而無法往下鑽,由奢入檢難啊!

在畢業前學會個體經濟學

懂商業基礎的程式師會是個更有價值的程式師。事情就是這樣。有些程式師的點子從程式的立場來看有道理,但由資本主義來看完全不通。

可以參閱《策略書之五》直接了解作者想說明的觀念。像是替代物品和互補物品為何,它們的商業運作模式,《策略書之五》後面的例子有點牽強,看完前半概念和一些例子就夠了。

《策略書之五》摘要:

  • 替代物品是首選商品太貴時會改買的另一種東西。雞肉就是牛肉的代替物品。
  • 互補物品是通常會和其他產品一起購買的產品。車和汽油是互補物品。
  • 當商品的價格下降時互補物品的需求就會增加。
  • 即使沒有實際付錢,還是有機會成本和時間成本。

XBox和遊戲片是不錯的例子,即使MS賣一台賠一台,仍可藉搶下遊戲市場後,對遊戲公司的抽成費大撈一筆。藉此思考顧問公司、軟體、硬體之間的關係。

總結

Joel的文章滿值得看的,文筆幽默又擅舉例,但很花時間,英文版更花時間。另外如他自己講的,有時不要太相信他說的,總會有錯,但我想這是讀者沒善盡思考的問題。

2007年2月22日 星期四

在VIM內直接執行script language

很久以前就很羨慕Emacs和script language的結合,沒想到VIM也可以輕易做到。

從《Programming Ruby》ch13 Editor Support看來的,只要script language屬於one pass interpreter,像是Ruby、Python,就可以把code直接導給interpreter。在VIM裡,以Ruby為例的做法如下:

:% w !ruby

  • 第一個欄位表示範圍,’%'是全文的意思
  • 第二個欄位是指令,’w'表示存檔
  • 第三個欄位是參數,’!'是執行外部程式,’!ruby’表示執行ruby

換句話說,”:% w !ruby”相當於在shell下這麼寫:

# cat my_script.rb | ruby

配合autocmd在~/.vimrc裡加上巨集,按F10就會執行檔案內的script:

autocmd BufRead,BufNewFile *.rb map <F10> :% w !ruby<CR>
autocmd BufRead,BufNewFile *.py map <F10> :% w !python<CR>

VIM的範圍操作用很強,也可以先用’V'(大寫V)選好範圍,再按’:'進ex mode,打 “w !ruby”就能只執行選取的部份。

:’< ,'> w !ruby # 執行選取範圍
:1,10 w !ruby # 執行1 - 10行的code

指令裡不含 ‘w’ 的話,執行完的結果會直接取代原本的內容。

2007年2月21日 星期三

Ruby + Rails + TextMate的demo影片和Ruby + VIM

眼見為憑,這裡這裡有些demo影片,似乎移動滑鼠讓人有罪惡感似的。學會這些工具後,確實如Brooks在《人月神話》裡的《再論沒有銀彈》所說一般,沒有萬能的方法或工具,但當我們把多個方法和工具合在一起時,軟體開發仍有可能達到數量級的提升。初看感到驚喜,接著讓我感到噁心,為什麼我要學這些東西?看來我有些工程師的屬性,但不適合走這條路。

看了幾個demo影片後,個人推薦“Inserting HTML Tags”,可惜只有Mac有TextMate,而且處理中文仍有問題。VIM應該有類似的補tag、補Ruby code的功能才對,不過我目前連Ruby在VIM內的indent都沒弄好,愈來愈懶得弄工作環境了。

Updated

打入def後,看到沒有end出來,忍不住找了一下VIM相關plugin。

  • Vim/Ruby Configuration Files:懶人包,把一堆plugin和doc合在一起,我沒試。
  • rubycomplete.vim :ruby omni-completion。看起來強的樣子,打Ctrl+X Ctrl+O會有選單,但要VIM7.0 + ruby interface(?),我只會在ports下打make install裝VIM,沒法試。
  • ruby-macros.vim:macros for the ruby language。至少打def後會有end了,當然if、for也有,單雙引號之類沒寫好,反而難用,我把這部份的設定註解掉。
  • rails.vim: Ruby on Rails: easy file navigation, enhanced syntax highlighting, and more。看起來頗強的,前兩項在insert mode用,這在ex mode用,用自訂的命令可以在VIM內做些shell下的事,像是rake、ri。附加些強大指令,像是extract view內幾行,另存成subview檔(_XXX.rhtml),並且附有詳細文件。但我懶得學這些指示,還是IDE較方便。

結論:至少打def後會有end了。

PHP:Fatal error: Allowed memory size of 8388608 bytes exhausted

剛才try說留言時有錯誤訊息,應該是指這個:

Fatal error: Allowed memory size of 8388608 bytes exhausted (tried to allocate 137 bytes) in …

我是因為用了af-extended-live-archive吃掉太多記憶體而發生,Spam Karma2有時也會出現這個錯誤訊息,參照這篇的解法,memory limit提高就解決了(預設8M)。

在PHP script開頭這麼寫

ini_set(”memory_limit”,”12M”);

或是改/usr/local/etc/php.ini

memory_limit = 12M

2007年2月5日 星期一

Ruby on Rails + Apache2 on FreeBSD

Rails是Ruby開發Web的超強framework,簡稱為RoR,國內用RoR最有名的站是HEMiDEMi,RoR的強大之處可以參閱這則新聞:"網站開發快10倍-探索Ruby on Rails的高速魔法"

google “ruby on rails”可以找到官方網站,有WEBrick的安裝和使用教學,入門文件可以參閱:" Rolling with Ruby on Rails",相當容易,用WEBrick玩RoR後,覺得RoR很有潛力,若對Ruby有疑慮,可以改用CakePHP - 用PHP寫成的RoR。

RoR也可以搭配apache使用,文件很多,這篇是我安裝完寫的筆記:“Ruby on Rails + Apache2 on FreeBSD”

原本只是想用RoR,卻把apache2、php5、php5-externsion、phpMyAdmin、CGI、FastCGI、RoR的安裝和運作流程都摸了一下,這就是玩系統的悲哀啊。

2007年1月12日 星期五

談JVM跨平台,卻不談scripting language跨平台的原因

這篇的看法可能有錯,參照大三上計算機組織報告JVM的心得,重寫這篇說明,但我這方面的知識卻是不進反退 XD 。當時鍾伯伯聽完報告後,說內容有些錯誤,但沒說錯在那,我就繼續不求甚解下去啦。

點此下載報告用的slide

談到跨平台時,不知道為何大家只提JVM,卻不談scripting language也跨平台,也許是scripting language跨平台是天經地義的事吧。深入一點來分析,JVM有別於scripting language的差異為:

  • Java要用compiler轉成bytecode,再用Virtual Machine讀bytecode,而不是直接用Interpreter讀source code,少了parsing syntax的時間,效率較好。但這點在scripting language引入compiler後,不構成主要差異
  • 除了VM外,沒有廣大的library,無法流行起來,但廣大的library要都能跨平台,要下許多苦工,Java的做法是建立強大的圍牆,全部自己來,讓OS相依的功能減到最小。這種土法練剛的精神,不是想做就辦得到的。
  • bytecode是真正的instruction set,理論上可以依此做出CPU,用硬體直接執行;實際上也有這樣的CPU,只是一直沒成主流。要做到可支援硬體實作,不是隨便訂訂compiler的輸出就好,有別於單純地定義compiler的輸入輸出。
  • instruction set最主要的差異在於JVM是stack architecture,它沒有register file,因此不被單一register size和register數量所限制,效率有所犠牲,彈性卻大幅提升
  • Just-in-Time(JIT)的編譯技巧,提高JVM執行效率(正確來說,是減少效率的損失)