PHP大型Web應用入門(三) php
接上一篇:仍是鬱字符長度的限制。
早期版本的PHPWIND論壇的cache機制是不好的,雖然它很快,可是很脆弱,一旦cache文件損壞或丟失,它不會本身去建立它,而是直接致使程序沒法運行,這種只能叫作臨時文件,而不能叫cache。我不知道如今的PHPWIND什麼樣,由於我一直沒興趣去看它……
下面的部分是mSession的實現,它只是模擬了session的存取過程,並對系統session進行了改進。它用了Hash目錄。它的缺點是在程序結束部分還要Rewrite一下,把數據更新到session文件裏,固然這個很容易被改進。
< ? php class BsmSession { var $ sid ; var $ sess_file ; function mSession_Start ( ) { // Special Function...session_start() global $ cookie_sess_id_varname , $ cookie_path , $ sess_liftime , $ mSession ; $ sid = $ _COOKIE [ $ cookie_sess_id_varname ] ? $ _COOKIE [ $ cookie_sess_id_varname ] : $ this - > _Gen_Sid( ) ; setcookie ( $ cookie_sess_id_varname , $ sid , $ sess_liftime , $ cookie_path ) ; $ sess_file = $ this - > _Hash_Dir( $ sid ) . 'sess_' . $ sid ; if ( file_exists ( $ sess_file ) ) { if ( ! @ $ fp = fopen ( $ sess_file , 'rb' ) ) { // Debug Info...No Log. fatal_error ( 'Session Error...' ) ; } if ( 0 = = ( $ fl = filesize ( $ sess_file ) ) ) $ sess_content = '' ; else $ sess_content = fread ( $ fp , $ fl ) ; } else { if ( ! @ $ fp = fopen ( $ sess_file , 'wb' ) ) { // Debug Info...No Log. fatal_error ( 'Session Error...' ) ; } $ sess_content = '' ; } fclose ( $ fp ) ; $ this - > sid = $ sid ; $ this - > sess_file = $ sess_file ; $ mSession = unserialize ( $ sess_content ) or $ mSession = array ( ) ; } function mSession_Destroy ( ) { global $ mSession ; $ mSession = array ( ) ; return @ unlink ( $ this - > sess_file) ; } function mSession_Rewrite ( ) { // Restore Session Data into Session File global $ mSession ; $ sess_content = serialize ( $ mSession ) ; if ( ! @ $ fp = fopen ( $ this - > sess_file, 'wb' ) ) { // Debug Info...No Log. fatal_error ( 'Session Error...' ) ; } fwrite ( $ fp , $ sess_content ) ; fclose ( $ fp ) ; return ; } function _Hash_Dir ( $ sid ) { // Hash the Session file Dir global $ user_sess_base_dir ; $ sess_dir = $ user_sess_base_dir . substr ( $ sid , 0, 1) . '/' . substr ( $ sid , 16, 1) . '/' ; return $ sess_dir ; } function _Gen_Sid ( ) { // Gen an Unique Session ID $ key_1 = rand ( 32768, 65535) ; $ key_2 = microtime ( ) ; $ key_3 = sha1 ( time ( ) ) ; $ sid = md5 ( $ key_1 . $ key_3 . $ key_2 ) ; return $ sid ; } function _Get_Sid ( ) { // Get Current Session ID global $ cookie_sess_id_varname ; $ sid = $ _COOKIE [ $ cookie_sess_id_varname ] ? $ _COOKIE [ $ cookie_sess_id_varname ] : FALSE ; return $ sid ; } } ? > html |
Hash目錄是一種優化文件存儲性能的方法。不管是Windows仍是Linux,不管是NTFS仍是ext3,每一個目錄下所能容納的項目數是有限的。並非不能保存,而是當項目數量過大的時候,會下降文件索引速度,因此權衡一個目錄下應該保存多少文件是很必要的。保存得多了會影響性能,保存得少了會形成目錄太多和空間浪費。因此當保存大批文件的時候,須要有一種算法能將文件比較均勻地「打散」在不一樣的子目錄下以提升每一級的索引速度,這種算法就是 Hash。一般用的MD五、sha1等均可以用來作Hash目錄,個人mSession裏也一樣使用了MD5,取得sessionID的第一位和第九位,這就構成了兩級Hash路徑,也就是說,系統把全部的Session文件分散到了16×16=256個子目錄下。假設Linux每一個目錄下保存1000個文件能夠得到最好的空間性能比,那麼系統在理想狀況下能夠同時有256000個session文件在被使用。
Hash目錄還被普遍應用在備份、圖庫、電子郵件、靜態頁生成等文件密集型應用上。
再來點一下個人模板類,我很懶地保留了Discuz模板函數的全部標籤。一方面是我確實很懶,另外一方面是我曾經試圖修改Discuz,把它改爲一個專用的版本,不過這是一個類,它的使用方法和Discuz函數沒什麼兩樣,都是include一個parse結果返回的文件名。
所不一樣的是在處理{template}標籤的時候。Discuz的處理方式是把{template}替換成再次調用模板解析函數去解析另外一個模板文件,這樣,模板函數可能會被調用屢次,編譯的結果裏也會有不少include另外一個模板文件Parse結果的地方。這裏涉及另外一個優化點——儘可能少地 include文件。過多地include會帶來更多的IO開銷和CPU處理開銷,因此我把{template}改爲直接讀入文件內容,而後再 parse。這樣一個模板文件即便有1000個{template},編譯的結果也只有一個文件。
這個模板類用起來是如此地簡單方便,更重要的是,它確實很快~~呵呵,我歷來不否定我有時候也會作一些比較有用的事,哈哈: 算法
閱讀全文>>cookie