My friends, my life, my style - James S.F. Hsieh

12/24/2010

SQLIte Query Planning

SQL 語言隱藏了大部分演算法跟資料結構的細節, 這讓 SQL 變得有彈性與容易使用, 但付出的代價就是效率, 當你要做出高效的 query 時, 你就必須了解你的 query statement 是怎麼被分析與執行的, 如果你能夠了解這些, 你就可以利用以前演算法的複雜度分析來思考 query statement, 如此也能找到更好的 statement 跟 對應的 indexing. 這幾篇文章讓我獲益不少, 在此分享一下吧:)

The SQLite Query Planner http://www.sqlite.org/optoverview.html
EXPLAIN QUERY PLAN http://www.sqlite.org/eqp.html
Query Planning http://www.sqlite.org/queryplanner.html
Performance Tuning http://www.sqlite.org/cvstrac/wiki?p=PerformanceTuning
How do I improve the performance of SQLite? http://stackoverflow.com/questions/1711631/how-do-i-improve-the-performance-of-sqlite

Some SQLite 3.7 Benchmarks http://blog.quibb.org/2010/10/some-sqlite-3-7-benchmarks/
Fast Bulk Inserts into SQLite http://blog.quibb.org/2010/08/fast-bulk-inserts-into-sqlite/

12/19/2010

Wedding slideshow


Create your own video slideshow at animoto.com.

12/16/2010

Stella 與 James 的婚紗

12/14/2010

2010 12 11 北插二行

11/30/2010

Corel 的聖誕卡

我挺喜歡公司這張賀卡的風格 分享給大家看看嘍

10/31/2010

Stella 的一格漫畫

10/30/2010

2010 10 29 萬聖節變裝




10/26/2010

2010 10 24 磺溪溫泉

10/12/2010

2010 10 12 帛琉 Part 4 and HDR





10/11/2010

2010 10 11 帛琉 Part 3




10/10/2010

2010 10 10 帛琉 Part 2



10/09/2010

2010 10 09 帛琉 Part 1



10/06/2010

2010 10 05 五專死黨歡唱






9/21/2010

2010 08 29 新店天湖



8/20/2010

2010 08 15 老梅

8/04/2010

2010 08 01 菊島之旅













7/04/2010

2010 07 04 桶後溪 22km 健行


今天走了 22 公里的林道, 雖然並不陡峭但是在那艷陽下真的叫人吃不消, 爬一半的過程中我們家楊大還拿出溫度計來看山上的氣溫, 結果, 太陽下竟然有 37度.... 畢竟高度只有 400~500 公尺高

黃色是今天走的, 紫色是 2008 年的紀錄喔 下次希望能到礁溪

在較大的地圖上查看桶後溪 旅行紀錄

VM-based 的程式語言總是讓人又愛又恨

我想大家寫過 .NET Framework, Java 甚至是 Python 之後再回去開發 C/C++ 的程式碼應該多少都有一點 "卡卡" 的吧, 原因是因為, 對於 programmer 來說上述的三種語言都有著豐富且 "統一" 的 library 可以供大家使用, 所以寫起來也比較順手. 這些 VM-based 的程式語言還個重要的好處, 就是它與硬體平台並不相依, 所以基本上如果兩個平台有著相同的 "軟體抽象層" (包含 Programming model 跟 library), 用這些語言寫的程式是可以直接在上面跑的,  另一個共通的特點就是這些語言都提供 Garbage collection 的機制, 所以寫程式 "比較" 不用在意記憶體釋放的細節. 這些好處都可以快速的增加 programmer 的生產力, 但是, 付出的代價也是非常的多...

首先 VM-based 的程式語言都需要 VM (廢話), 在沒有支援 JIT 的情況下, 程式碼必須以 Byte-code 的形式在 VM 中執行 (Java 在 ARM CPU上有 Jazelle 可以直接執行) 速度與 Native-code 相比還是差了一點點, 如果是 JIT 的話那應該就差不了太多了, 不過, 就我的經驗 JIT 還是挺花時間與記憶體, 在 Mobile 或是 Embedded system 的世界中對於記憶體的要求可能就更嚴格了.

Garbage collection 是個很方便的技術真的大幅提升了開發的速度, 但是付出的代價就是 programmer 對於記憶體使用量的控制性降低了, 畢竟 GC 不可能隨時隨地都在做, 通常只有在記憶體比較不足或是系統比較有空的時候才會發生, 這對於程式來說有兩種影響 1. 記憶體的使用量比 Native-code 大而如果 programmer 需要精細的配置記憶體的使用量可能不大容易 2. GC 可能會影響系統執行的流暢度.

觀察現行的 Mobile platform 各式各樣的硬體 CPU 規格, 要使用非 VM-based 的語言來開發軟體在佈署與相容性上將會非常麻煩, 以下是各個平台的概況:
  • Windows CE 提供了 C/C++ SDK 與 .NET Framework Compact 供 programmer 發展, 但是似乎是比較傾向 Native code, 以 Windows CE 7 來說, 微軟提供了 Microsoft Silverlight for Windows Embedded 給 C++ (沒錯不是 C# 喔) 做為 UI Framework, 
  • Windows Phone 7 上則是主推 Silverlight,  XNA 與 .NET Framework Compact (我猜是想把 Windows Phone 7 變成遊戲平台吧 :P) 這兩個平台的發展方向目前有點不同!  這有篇相關的文章可以看看 "Microsoft's new pitch: 'Every .Net developer just became a Windows Phone developer"
  • Android 則是 Java 配上 Application Framework 與 NDK, NDK 相關的資訊還真的少得可憐, Google 則強烈建議大家用 Java 開發應用程式. 
  • iOS 提供的原生程式語言是 Objective-C, 基本上是 C-based 的程式語言, 所以速度上應該不是問題, 在加上 Apple 的硬體 model 單純所以沒有太多相容與移植的問題, 所以狀況比較單純, 但是還是有人對於  Objective-C 的速度有些意見:P "Android Dalvik VM performance is a threat to the iPhone" 另外 .NET CLI 也可以在 iPhone 跑ㄟ MonoTouch
  • MeeGo API 部分是使用 Qt Framework 做為 UI Framework, 主要是使用 C/C++, 感覺 MeeGo 比較像一般的 OS, 現行的 Mobile OS 都在 Application framework 還有跨硬體平台的部分有著特殊的設計, 但是 MeeGo 在這方面著墨比較少.
可以見得每個平台的選擇都還不少, 除了 Apple iOS 獨樹一格之外, 其它開放性的系統都會有硬體相容性與移植的問題, 要用 VM-based 的程式語言還是 Native 的程式語言好呢? 我想混用最好, 但是佈署可就要花點心思了.

6/25/2010

OS 與 programmer 的距離越來越遠...

為什麼我會說 "OS 離 programmer 越來越遠..." 呢? 還記得我以前一開始寫程式的時候常常會想, 物件導向不是很棒嗎? 為什麼 Windows 下的 API 都這麼難用, 雖然它還是有物件的觀念但使用起來跟真正的物件還是有些差異雖然 MFC 包裝了不少 Win32 API, 但總免不了跟 OS 打交道的機會. 後來有了 Java 跟 .NET Framework, 在他們的世界裡物件模型是一致並且可以擴充的, 這時終於讓我天真感受到 "我終於活在完整的物件導向世界中 :P" 儘管實際沒有那麼盡善盡美, 但可以確定的是在那樣的開發環境下 OS 離我越來越遠... 我想這一切都是從 Java 開始的吧...

最近開始學習與了解 Android 的軟體架構 (我好像動作都比別人慢...) 也稍微 study 了一下 iOS 的設計, 反觀現有的 Windows. 有個共通的特點就是這些開發廠商都想慢慢的隱藏 "OS 的細節與耦合程度", 以微軟來說 COM 與 .NET Framework 提供了遠多於 Windows 本身豐富的元件, 也將一些生澀的 Win32 API 包裝成好用的物件, 所以 programmer 在 .NET 的環境下使用 P/Invoke 打交道的機會就越來越少. Android 也是個有趣的例子, 大家都知道 Android 底層是 Linux kernel, Google 在 Linux kernel 建構了變形的 Java VM 稱 Android Runtime 與 Application Framework 來增加 programmer 的生產力, Application Framework 是一群 Java 的元件並且描繪出 Android 上為了 mobile 特性自有的 programming model, 有了這層 Runtime, programmer 就不需要顧慮他的軟體到底跑在哪一個硬體平台 ARM or x86..., Apple 的 iOS 與 MacOS 則是在 Linux/FreeBSD 上以 Objective-C 的方式提供了 Cocoa, Carbon 與 Java 等 Application Framework, 目的也是一樣加速軟體的開發. 

我想這就是近幾年 OS 的發展趨勢 "提供統一且豐富的元件加速軟體的開發", 以往的 OS 著重如何高效率的使用硬體, 而現經則是重視怎樣提升 OS 上軟體的開發速度. 畢竟一個 OS 的成功與否是取決於上面有多少 Application. 

6/22/2010

2010 06 19 加羅湖登山口之旅



6/01/2010

Media Library Engine 2.0


It is a file-based media content management service that provides query/access, management, and tracing APIs. Windows applications can search, manage, and sync content with MLE2. It includes a daemon which syncs metadata and thumbnails between database and file system in background. MLE2 database back-end is SQLite engine. Comparing to Google Picasa cataloging engine, MLE2 can handle more files (10K~100K files) than Picasa, and they have similar performance for cataloging and search. In addition, it provides a schema-free metadata system to store complex metadata. It supports multiple applications or instances to concurrently access library. MLE 2.0 also supports primary features such as:

 Support multiple libraries in concurrent.
 Support high performance query, full-text-search, grouping and paging; MLE can handle a query to search 100000 ~ 250000 files less than 1 sec (depends on HDD and CPU).
 Support bulk operation to modify library.
 Support file time and size stacking
 High throughput thumbnail system which supports three levels pixel, 96x96, 160x160, and 480x480.
 Support applications to trace change of files.
 Extensible metadata and tags model, applications can define customized metadata and tags for special purpose.
 Extensible fault-tolerable media parsing framework, applications can implement multiple media parsers to support customized file formats. MLE includes a default media parser which supports JPEG, PNG, and BMP format based on Microsoft Windows Imaging Component.
 An async message channel between MLE and all clients. MLE uses that to notify change notification, and applications can use it to communicate each other.

I designed and implemented whole engine.





5/02/2010

2010 05 02 巴拉卡亂拍




4/25/2010

2010 04 25 華山 Art Area



4/18/2010

2010 04 16 大甲媽遶境 第四年


4/11/2010

2010 04 10 哈盆露營






4/05/2010

領悟

領悟 就是 辛曉琪 的歌

3/28/2010

2010 03 28 淡水福佑宮






3/27/2010

2010 03 27 雲森瀑布






3/23/2010

COM Managing Memory Allocation

回憶一下吧~
Managing Memory Allocation
Memory Management Rules

3/06/2010

2010 03 06 迪化街


3/01/2010

2010 02 28 平溪天燈

2/19/2010

GANTZ 又回到了這房間...




軟體的藝術 trade off

今天看了篇文張 程式設計的兩個觀點:架構狂還是效率狂? 覺得十分有趣也心有所感, 以下是我的想法: 我也算是個架構狂, 比較執著於彈性與複用, 所以 dependency 與 role and responsibility 的設計就非常龜毛. 但最近面對的工作對效率比架構還有著較嚴苛的要求, 如此的要求下變的必須以效率為導向來決定整體的架構. 有著最佳的效率意味著整體都要互相配合, dependency 就變的比較強也比較無法複用, 但贏得的是效率的提升, 這也是我這一兩年來對於架構跟效率有著比較不同的體認, trade off 就是軟體的藝術, 對 效率 與 架構 也不例外 :)

2/18/2010

2010 02 14-18 Carcassonne


命運之輪是由小豬來轉動的....

2/12/2010

C++ Object Persistent for SQLite

上一篇文章我提到了 LiteSQL 的設計是利用 DB Schema (XML file) 來產生對應的 C++ Class, 而我的設計是從另一個角度出發 "設計 C++ 產生對應的 DB Schema" , 我設計了一系列的 Class, macro 跟  template function 來達到 Object Persistent 這個目的, 而 SQLite 接合的部份我選擇了 SQLite3++ 這個 SQLite3 backend library, 撰寫 Persistent Class 的時候只要利用這些東西就可以輕易的產生出可以 Persist 到 DB 的 class, 其中的功能包含簡易的 Reflection 跟 DB 對應的操作 function 諸如: CreateTable, InsertInto, UpdateAll, UpdateModified, SelectFromRow 等等... 以下是個使用的例子

Persistent class declaration

當我們利用 macro 寫出這個 Class 的時候, 這些 macro 讓我們描述了 class MLDBPersistSample 所對應的 DB Schema 跟 metadata , 因為繼承自 MLDBPersistBase class, 所以擁有了上述 DB 操作的能力, 使用的時候就不需要再去組合 SQL 字串了 :D 要建立 Table 只要呼叫 CreateTable 這個 static function


它就會根據我們所描述的 metadata 產生出以下的 SQL statement
CREATE TABLE MLDBPersistSample(Column1 TINYINT , Column2 SMALLINT , Column3 INTEGER PRIMARY KEY AUTOINCREMENT, Column4 BIGINT DEFAULT 0, Column5 TEXT , Column6 REAL NOT NULL, Column7 DATETIME , CHECK(Column1 >= 0 AND Column1 <= 5))
如果我們想要 insert 或是 update 一個 object 到 DB, 只要 (Column? 只是個例子, 實務上 Symbol 可以取得更有意義一點)


就能產生出以下的 SQL statement

INSERT INTO MLDBPersistSample (Column3) VALUES (?)
UPDATE MLDBPersistSample SET Column5 = ? WHERE Column3 = ?
 問號 ? 的部分, 會利用 data binding 的方式傳給 SQLite 的 API

Query 的部分, 我則是從 LiteSQL 例子中得到了一些啟發, 我實做了相對應的 query class 來產生對應的 SQL statement, 以下是個 C++ statement 與產生出 SQL statement 的結果

SELECT MLDBPersistSample.Column3,MLDBPersistSample.Column5 FROM MLDBPersistSample WHERE (MLDBPersistSample.Column3 >?) AND (MLDBPersistSample.Column5==?) ORDER BY MLDBPersistSample.Column1,MLDBPersistSample.Column2
我想這個部份是最有趣的, 也是 LiteSQL 最有創意的地方, 所以我也提供了這樣的使用方式, 利用這樣直覺得 C++ 操作可以產生出比較複雜一點點的 SQL query 真的是非常方便, 而且 C++ 的部分還會做 syntax checking, 而 10 跟 "hi" 的兩個 condition 會做 type checking, 並且兩個值會以 data binding 的方式傳給 SQLite API, 非常方便吧 :D

2/02/2010

LiteSQL - SQLite Object Persistent for C++

最近因為工作的原因需要用到 SQLite, Review 現有的 C++ Project, 我發覺我們現有 Project 在使用 SQLite 非常的不方便, 它使用最基本 (原始?!) 的方法自己組合 SQL statement 來操作 DB, 並建立一組 Class hierarchical 來 Modeling DB 的 Schema. 這樣設計的好處在於操作 DB 可以比較自主效能上也許會好些, Class hierarchical 也可以比較複雜. 壞處則是, 許多 DB 的操作 SQL statement 都有固定的 pattern 這個部份可以抽離出來, 但是 Class, statement 與 DB Schema 的對應關係需要人工來維護. 能夠盡量減少人力來維護是我的目標, 所以, 我們需要一個有彈性的 SQLite Object Persistent Library.

我 Survey 了一下現有的 C/C++ SQLite wrapper project, 有支援 Object Persistent 的似乎只有 LiteSQL 這個 open source project, 是用 LiteSQL 必須使用 XML 來定義 DB Schema, 並使用他們提供的 Code generator 來產生 C++ Modeling 的程式碼, 以下是官網上面的 example.

PersonDatabase db("sqlite3", "database=person.db");           
Person person(db);
person.name = "Bob"; // assign values to fields
person.age = 20;
person.update(); // writes a new record to database
我們可以輕易的操作 Person 物件來建立/改變 DB 中的 record, 該例子隱藏了 SQL statement 並且轉換成較我們較直覺得物件化操作, 對於 Relation 的部分, LiteSQL 可以建立 Relation-class 來 Modeling 兩個 Persistent Object 之間的關係, 這樣的設計在 C# 那種具有完整 Reflection 能力的語言中是非常容易實做, 但在 C/C++ 中則是非常困難.

除了Object Persistent 之外, LiteSQL 還提供了一下的 select 語句來方便查詢
PersonDatabase db("sqlite3", "database=person.db");
vector = select(db).all();
Person bob = select(db, Person::Name == "Bob").one();
這個 library 給我不少的啟發, 但我實際上試用它卻有不小的挫折, 原因在於我們使用的 DB Schema 似乎無法產生正確的 class, 畢竟這個計畫目前的狀態仍然是在 proof-of-concept implementation 的階段.

我遇到的另一個問題是, LiteSQL 是使用 Gen-Code 的方式來產生 Modeling Class, 所以, 如果 DB Schema 改變了, 程式碼應該有不小幅度的改變 (我想無法避免), 但是開發過程中 Schema 改變是免不了的, 所以我嘗試設計了一個以 class modeling 為主的方式來產生 DB Schema, 只要遵照一定的 class 設計方式, 就能夠利用類似 Reflection 的方式還產生 Schema 與 record 操作, 主要是配合 macro 跟 template 的方法來實現, 目前我還在設計中, 有機會再跟大家分享 :)

1/19/2010

ETW Scenario library and Real-time ETW Viewer

微軟在 Windows 2000 之後引入了 Performance Monitoring 機制 - Event Tracing for Windows ETW, 而在 Windows Vista 對於 ETW 有更多的改進, Vista 導入了 Unified event provider model 與新的 APIs 讓我們可以用一致的方式來處理 ETW event. 你不難發現微軟已經大量的整合 ETW event 到 CPU scheduler, File system, GPU Driver, Image Loader, .NET Framework JIT, GC, WPF render engine 等... 重要的模組中, 因為 ETW 是 Kernel build-in 等多種特性所以在使用上有較小的效能影響, 並且可以收集到 System-wide 的資訊. 微軟也為此提供豐富的 Tools 來支援軟體開發與 Performance tuning, 諸如  Microsoft Windows Performance Toolkit, Visual Profile, Logman, Reliability and Performance Monitor (RPM)...

但是, 如果我們要開發自己的 ETW event provider, 並且有圖形化的介面可以幫助我們了解效能上的問題有現成的 tool 嗎? 有的, Microsoft Windows Performance Toolkit 中的 Event Trace 或是 xperfview 都可以幫助我們圖型化我們自製的 ETW event, 但是, 它只能提供一般性的呈現方式, 原因很簡單, 因為這些 tool 並沒有足夠的 domain knowledge 來解釋這些 event, 所以他只能以 Generic event 的方式呈現, 如此我們只能以時間分佈的單一維度來觀察我們的 event, 其實這並不方便


xperfview - Generic event 只能看到事件發生的時間點

之前曾在微軟的 Blog 看到人家發問 "xperfview  是否能夠支援擴充" 不過到目前為止的答案是否定的, 其次 xperf 因為效率的考量所以只有提供 offline 的方式來分析 ETW event, 但對於有些特定的 use case 下將會非常麻煩, 我們總想知道使用者互動下效能與操作行為的相關性, real-time 的方式分析有時候比較快速與直覺, 有鑑於此我們就自己開發了簡單的 ETW Viewer 來幫助我們做到這些事情.

首先, 我們要定義比 Generic event 在豐富那麼一點點的語意來表達更多的資訊, 並且在 Client 的整合上可以更方便快速, 所以我們選擇一個 MSDN Code Gallery 上 ETW 相關的 Project - Scenario 來做為整合的目標, Scenario 是個 ETW event provider 的實做體, 它提供了 Native 與 Managed code 的兩種實做版本, 在 event 的格式部分, 因為 Scenario ETW Format 有定義了兩個值 Category (Unicode string) 與 Size (int64) 來讓我們描述 Client 想要描述的 "量" (你可以用來描述 FPS, cache miss rate 等等自訂的語意), 使用 Scenario 可以說非常的簡單, 我們只要埋入幾個特定的 check points: Begin, Step, End 在我們想觀察的 case 中, 並且將我們自訂的數值傳遞給 Scenario 就夠了. 就像:

// C#: Generate an ETW event (when enabled by an ETW controller)
using Scenario;
...
Scenario timer = new Scenario();
timer.Begin(); // checkpoint 1
// ...
// Code that you want to time
// ..
timer.Step(size// checkpoint 2
// ...
// Code that you want to time
// ..
timer.End(); // checkpoint 3

以上的程式為例, Scenario 就會幫我們把 3 個 checkpoint 的時間間隔量出來, 並且把我們自訂的 Size 值也跟著傳給 ETW consumer.

接下來我們的問題就是如何顯示這個收集到的 event , 我們使用了 C# 開發了一個簡單的 WinForm 程式, 這個程式包含了一個 ETW controller 跟 ETW consumer, ETW controller 有能力動態的 Enable 或 Disable 指定的 ETW event, 在配合 Scenario 的設計下當一個 ETW event 被 Disable 時我們所 monitor 的程式除了一些簡單的判斷式, 它將不會執行 ETW provider 相關的程式碼, 這樣能確保在 Disable 的狀況下只有很少的效能損失. 利用 ETW consumer 我們能即時且非同步的方式處理收到的 event, 並將其 Size 與 checkpoint 的時間顯示在 UI 的笛卡兒座標上, 這就是我們希望視覺化的部分. 此外, 這個程式也有能力將這些資訊寫進 SQLite 的 database 中, 這樣的好處是, 我們可以在將來更輕易的整合到 Auto testing 與 Build process 中. 以下就是  Real-time ETW Viewer 的 Snapshot!


ETW Realtime Scenario Viewer - timeline view


ETW Realtime Scenario Viewer - list view


Improve Debugging And Performance Tuning With ETW 是篇還蠻具體而微的文章, 對於這方面有興趣的人可以參考.

1/17/2010

2010 01 17 陽明山七星池

1/13/2010

什麼是好的軟體?



實務派的人說:
軟體是種高度特化的藝術品, 所以裡面怎麼做不重要, 只要整體的功能與效率符合需求並且執行的很好, 最好能夠用最低的成本來達到目標就是王道.
架構派的人說:
軟體是種有系統性的積木, 為了增加複用性與生產力, 降低擴充與維護的成本, 架構是軟體的靈魂.
產品派的人說:
軟體只要功能多成本低, 能快速生產能夠高度客製化, 在效能上有好的表現, 很少 BUG 就是好軟體.
使用者說:
軟體只要便宜 (最好不用錢), 好用, 快速就是好軟體.

軟體的特性還蠻複雜的, 它有著生產, 運作, 維護 時間長, 複製成本極低, 規格變動, 汰換率與人事變動成本高, 不易維護, 除錯與驗證等多種複雜特性. 要減少這些特性的缺點增加其優點是很明確的目標, 所以上面沒有一種人說錯, 軟體是在上述的多種衝突需求中找到一個最佳的平衡點就是好軟體. 但怎樣的平衡是正確的選擇就有很大的學問,

舉個例子: timing 就是市場的一切, 快速的做出產品可以爭取更多的機會來把握 timing, 然而好的架構會因為降低耦合增加彈性等多種考量而延長產品的開發時間, 有時候這些設計可能在當下會被視為 over design 而被捨棄或忽略, 某個層面這是對的. 如果這個產品賣得好而延長了程式與架構的生命週期, 接下來要面對的就是該產品的架構會因為未來的需求而受到考驗, 好的架構也可以降低維護的成本. 所以這個平衡的因子似乎因為生命週期而有不同的選擇, 儘管軟體的生命週期會因為市場的反應而難以評估, 有些軟體可能會沿用個 10 年, 有些則只會出一個版本.

再舉個例子: 架構的取捨有時候還得考量 programmer 的技術能力, 也許你會遇到一個窘境是你使用了一堆很棒的 design pattern 但你的同事卻一個也看不懂還是能存活下來. 你該用易懂直觀的架構還是稍微難懂但頗富彈性的架構呢?

再再舉個例子: 如果有個公司就是做 OEM 或是硬體驅動程式 BIOS 這類強烈需求導向的工作, 也許這個軟體一但 GM 就等於進了墳墓, reuse 對這類型的工作也許毫不重要, 也可能這些具有 reuse 特性的部分人家都已經做好了等著你用, 這樣的公司文化與工作特質下, 怎樣的選擇好呢?

什麼是好的軟體? 因為人, 因為時間, 因為佈署的方式, 因為舊有的包袱, 因為公司的文化與營運方式有著截然不同的答案. 連怎樣評估軟體是好是壞都是如此的複雜...

1/09/2010

幾個關於 .NET Framework 4 的幾個疑惑與希望...

.NET Framework 3.5 以來, 普及率一直不是很理想, 微軟也針對關鍵性的幾個因素做改善, 一下的幾點筆記是該去研究一下 :P
  1. 大家都知道 .NET 的 Application 的啟動時間可能會很慢, JIT 是個原因之一, 利用 NGEN 來改善 Startup Performance 是微軟提供的一種解決方法, 我們是該驗證一下這個方式, 有幾篇文章可以追一下: The Performance Benefits of NGenCLR Optimizations In .NET Framework 3.5 SP1Improvements to NGen in .NET Framework 4To NGen or Not to NGen?Improving WPF applications startup timeSplash Screen To Improve WPF Application Perceived Cold Startup Performance

    我驗證的結果, WPF 的 Cold/Cool Startup time 還是很久, 即使用了 NGen 速度還是沒辦法像 native code 一樣.

  2. WPF 與 Direct3D  的 footprint 差異有多大, WPF 的記憶體使用量一直為人所詬病 (相較於MFC), 不知道 4.0 是否有改善

  3. .NET Framework 的 installer size 一向不小, 所以微軟設計了.NET Framework 4 Client Profile 還有Web Bootstrapper, 文章上描述 .NET Framework 4 Client Profile 的安裝不一定需要 Reboot 並且可以 Parallel Download and Install, 這個也是需要追一下: What's up with the "Reboot" step? , The .NET Framework 4.0 Beta 2 Installer ImprovementsWhat’s new in .NET Framework 4 Client Profile Beta 2, .NET Framework Client Profile Deployment Guide

    Installer size 已經比以前小很多了, 但是 install size 還是一樣肥的嚇人, 以 x86 為例, installer 的大小大約是 30.9 MB, 但是解壓縮加上 JIT 之後的大小需要 850 MB 左右, 這真的讓人卻步, 不過我承認 installer 縮小有助於程式在網路上散佈. 不過如果我想寫個 WPF 小軟體卻要求使用者要有 850 MB 的空間來安裝我的軟體, 應該沒有幾個使用者能夠接受.

    今天在別人的電腦嘗試安裝 Client profile 結果 installer 還是要求重新開機, 仔細觀察 MsiInstaller 的 log 發現這台電腦必須重新開機有幾個原因:
    C:\WINDOWS\system32\dfshim.dll 正在被下列處理名稱所使用中: explorer 識別碼 1920
    C:\WINDOWS\system32\mscoree.dll 正在被下列處理名稱所使用中: explorer 識別碼 1920
    C:\WINDOWS\system32\mscoree.dll 正在被下列處理名稱所使用中: iexplore 識別碼 220
    C:\WINDOWS\system32\mscoree.dll 正在被下列處理名稱所使用中: iexplore
    識別碼 1764

    這台電腦的使用者算是個很基本的 End user 所以電腦安裝的軟體並沒有什麼特別之處但是還是被要求重新開機, 原因是 IE 跟 Shell 都佔住了 .NET Framework 的 runtime, 看來狀況並不明朗啊.. 然後查了一下 MSDN 發現, Client profile 的 installer 提供 command parameter




    /norestart: Setup doesn’t reboot automatically. The chaining application needs to capture the return code and process and handle reboot if this switch is used.
    但也只是暫時讓他不需要 reboot 罷了.

    根據 张羿的文章 ".NET中的幕后英雄MSCOREE.dll " 所描述, mscoree.dll 提供了 _CorExeMain 這個進入點做為 CLR 程式啟動之用, 重點是不管哪個版本的 .NET Framework 都是用這支 DLL 來啟動, 所以 mscoree.dll 在系統中只會有兩支 (32/64bit), 而 .NET Framework 4.0 似乎需要置換掉這個檔案, 所以重新開機也許在所難免. 除非類似 SxS 的方式使用私有的 mscoree.dll, 而 张羿 似乎有找到解決的方法不過還沒分享出來, 詳細可以參考 ".NET 4.0新功能:Mscoree.dll + Mscoreei.dll=更少的Reboot" 




1/08/2010

免費的 "IStream, IPropertyStorage" system-provided, stand-alone implementation COM



相信寫過 .NET C# 的人對於 System.IO.MemoryStream 這樣的物件都感到十分方便, 因為MemoryStream 會在需要的時候自己 ReAlloc 來改變大小, 並且由於 MemoryStream 繼承自 Stream 這個 class 所以用途十分廣泛. 其實 COM 也有相似的設計 (不如說 .NET Framework 學 COM 的) COM 有定義一個基本的 interface IStream, 概念上 IStream 就如同 .NET 中的 Stream 一樣, 不過它是 interface 而不是 abstract class, 在 COM 的世界裡 interface 是種 protocol, 所以任何人都可以實做 IStream 的 COM, 並且跟認得 IStream 的其它 COM 合作. 我之前就有寫過一個實做 IStream 的 COM, 它支援 non-buffering 的方式來 OpenFile. MSDN 就有一篇文章來教大家怎麼時做一個 FileStream - Default IStream Implementation.


COM 的定位並不是個 Framework 所以沒有那麼多現成的 class 可以使用, 而且系統提供的 COM implement 也少的可憐. 但是 OLE32.DLL 還是提供了類似 MemoryStream 這類好用的東西, 我們可以使用 CreateStreamOnHGlobal 來建立一個實做 IStream 的 COM instance, 而這個 instance 的功能就如同 MemoryStream 一樣會自動 ReAlloc.  當然 OLE32 也允許你從 IStream 拿到 HGlobal 的 HANDLE, 我們只要呼叫 GetHGlobalFromStream

HGLOBAL handle = NULL;
CComPtr spStream;
HRESULT hr = ::CreateStreamOnHGlobal(handle , FALSE, &spStream);
hr = ::GetHGlobalFromStream(spStream, handle);


一但有了這個類似 MemoryStream 的 IStream 實做體, 我們還可以利用更多 OLE32 提供的功能, 例如 IPropertyStorage, IPropertyStorage 這個 interface 的功能是個用來存放 property 的 container, property 可以是 PROPVARIANT 所支援的任何 type, WIC 就是用 PROPVARIANT 來記錄存放在 JPEG EXIF 中的 metadata 詳細可以參考 IWICEnumMetadataItem (說遠了), 為什麼要介紹 IPropertyStorage 呢, 因為 OLE32 又提供了一個 system-provided, stand-alone implementation 的實做體, 我們只要提供 IStream 或是 IStorage 給傳給 StgCreatePropStg 這個 API, 它就會送一個 IPropertyStorage 的 instance 給我們, 我想 property bag 這種東西的方變程度就不用說了. 有注意到嗎? 我們只要結合 CreateStreamOnHGlobal 和 StgCreatePropStg, 它就可以幫我們建立一個在記憶體中的 property bag, 這是何等的方便與容易呢?


延伸思考一下 IStream 能不能在 .NET 中使用呢? 當然可以啊因為 IStream 是 COM 呢, 連 .NET Framework 都有對應的 Interop interface System.Runtime.InteropServices.ComTypes.IStream 而 IPropertyStorage 則對應於 MS.Internal.IO.Packaging.CompoundFile.UnsafeNativeIPropertyStorage, 不過似乎沒有公開 ...
(後來查了一下 MSDN 發現 Microsoft.VisualStudio.OLE.Interop 有公開對應大部分 OLE32 的介面, 不過放在一個很怪的 DLL 中 microsoft.visualstudio.ole.interop.dll 而 IStream 與 Stream 的轉換則有 DataStreamFromComStream 與 ComStreamFromDataStream 兩個 wrapper class 可以使用, 不過都包在 System.Windows.Forms.UnsafeNativeMethods 這個 internal class 中, 微軟真的很小氣 = =. 不過 UnsafeNativeMethods 真的是大個誇張啊, 大家可以用 .NET Reflector 看一下就可以知道了. 


順帶一提 System.IO.UnmanagedMemoryStream 似乎是個不錯用的 class, 它可以 wrapper 一個 unmanaged 的 pointer 程為一個 Stream class, 雖然它是 unsafe 的 class 但是對於 performance 也許有不少幫助呢.

1/03/2010

2010 01 02-03 北插天山露營



這太白癡了 不得不貼出來 .....









1/01/2010

2010 01 01 跨年