Sean's Note: 8月 2015

2015年8月18日 星期二

Writing DPI-Aware Desktop and Win32 Applications

在 Windows 上,依據 DPI 的設定可將應用程式分為三類:

Not DPI-aware Applications

沒有設定 DPI-aware 的應用程式,皆以 96 DPI 做 rendering。
系統的 Desktop Window Manager (DWM) 會自動縮放 (virtualizes and scales) 這些應用程式。


System-DPI Aware Application

從 Windows Vista 開始到 Windows 8,應用程式可以依據系統 DPI 的設定,自己去做最佳化,而不是透過 DWM 來做。但如果是在不同 DPI 的螢幕間移動,DWM 還是會自動縮放。 


Per Monitor-DPI Aware Applications

從 Windows 8.1 開始,多了這個類別。當使用者改變了 DPI 設定或在不同 DPI 的螢幕間移動時,這些應用程式將會動態縮放。DWM 同樣不會去自動縮放這些應用程式。

DPI Virtualization and Scaling 

從 Window Vista 開始,引進了新功能  DPI virtualization,這項功能會將沒有設定 DPI-aware 的應用程式,自動縮放其文字和其他 UI 元件。這樣應用程式的字在 high DPI 的螢幕上就不會看起來特別的小。而從 Window 8.1 開始,延展了 DPI virtualization 的功能,DPI 從系統層級變成螢幕層級。


Supporting Dynamic DPI Changes

那應用程式該做哪些事情來支援 DPI 的動態設定呢?
  1. Set the DPI Awareness Level
    可以透過 manifest 檔或 SetProcessDpiAwareness API 來做設定。
  2. Get the DPI for the current monitor
    呼叫 GetDPIForMonitor API 來取得值。
  3. Listen for DPI changes
    聆聽 WM_DPICHANGED 這個 windows message。
  4. Respond to DPI changes
    收到上述訊息後,改變視窗大小或縮放 UI 元件等等。

Ref : Writing DPI-Aware Desktop and Win32 Applications

2015年8月4日 星期二

[sqlite3] Auto-commit will be inefficient for multiple SQL statements.

我們通常會用下列的程式碼來建立 DB 的連線,並指明是 auto-commit 的。

# Set isolation_level=None to use auto-commit
conn = sqlite3.connect('example.db', isolation_level=None)

來實驗看看執行 10000 次 INSERT 的敘述,

for i in range(0, 10000):
    conn.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")

居然要 657 秒!! 
因為每一筆 INSERT 都是一筆 Transaction,太花時間了,
所以如果我們只建立一筆 Transaction,
然後把 Statements 都塞到同一個 Transaction 再執行:

conn.execute("BEGIN IMMEDIATE TRANSACTION");
# Insert a row of data
for i in range(0, 10000):
    conn.execute("INSERT INTO stocks VALUES ('2006-01-05','BUY','RHAT',100,35.14)")
conn.execute("COMMIT TRANSACTION");

結論: 發現只要 0.17 秒,差了快 400 倍啊!!