2010年2月28日 星期日

程式設計(Windows API) - 磁碟I/O的效能測試

今天花了不少時間, 把 Q9400 那台機器的 Host 及 Guest 建立起來, 也留下了部份安裝過程式的圖片, 等有空的時候再整理成安裝教學.

在這邊要談的是, 效能測試 的部份. 現在已經有不少應用軟體, 會用種種方式幫系統效能評分, 可是我們身為資訊人, 當然也要多了解一點實作的方法, 不能只看軟體跑出來的數字.

對磁碟效能, 最直覺的想法, 就是實際產生一個檔案, 然後讀取內容, 計算花費的時間就可以得到寫入的效能, 讀出的效能. 不過在 Windows 系統中, 為了加強效能, 所以大量的運用 Cache 和 Prefetch 的技巧, 所以在寫檔時, 可能檔案還在記憶體的 Cache 中, Windows 就已經回傳寫入完成給程式了, 讀取時更有可能因為剛才寫入的東西還留在 Cache 中, 跟本就沒有到檔案系統中讀取檔案, 而是直接從 Cache中傳回檔案內容. 這樣會造成檔案系統效能很好的錯覺, 或是運氣不好, 讀寫的過程中正好碰到 Cache 要將大量的資料寫回檔案系統, 造成系統效能降低的錯覺.

那麼要如何避免 Cache 的干擾, 而確實測試檔案系統的讀寫效能呢? 查了一下資料, 發現在 Windows API 中, 就有提供這樣的參數可用. 但要注意必需要能直接調用 Windows API 才能使用這些參數, 若使用程式語言內, 包裝過的 函數 去開啟檔案, 那就會用 Windows 的預設方式, 即透過 Cache 進行讀寫.

使用上其實很簡單, 只在要 Windows API 的 CreateFile 中, 設定參數值即可, CreateFile 的語法格式如下

Syntax (C++)

HANDLE WINAPI CreateFile(
  __in LPCTSTR lpFileName,
  __in DWORD dwDesiredAccess,
  __in DWORD dwShareMode,
  __in_opt LPSECURITY_ATTRIBUTES lpSecurityAttributes,
  __in DWORD dwCreationDisposition,
  __in DWORD dwFlagsAndAttributes,
  __in_opt HANDLE hTemplateFile
  );


詳細的參數請參考 MSDN 中的說明, 我要說重點是在參數 dwFlagsAndAttributes.

dwFlagsAndAttributes是 DWORD 類型參數, 每一個 Bit 代表不同的旗標(選項). 這邊主要針對 CACHE 相關的 2 個參數介紹

FILE_FLAG_WRITE_THROUGH (0x80000000) 此旗標會使任何對該控制代碼所做直接寫入檔案而不被緩衝的寫入,  但仍會寫入 Cache 中. 在設計上一般是運用在網路或外接裝置的寫出, 例如隨身碟的檔案寫入, 若未加入此參數, 在寫一個檔案到隨身碟, 不要退出硬體就直接拔出隨身碟, 你會發現剛才寫入的檔案居然不見了. 因為系統在傳回寫入成功後, 只是寫到 Cache 中, 還沒真的寫到外接裝置上.


FILE_FLAG_NO_BUFFERING (0x20000000) 此旗標是代表系統會排除所有緩衝先期讀取檔案和磁碟快取, 同時也使所有讀取都保證從 "檔案" 中取得, 不能從任何系統緩衝區或磁碟快取之中讀取. 不過有些特例, 像透過網路芳鄰讀取遠端的檔案, 系統會忽略此參數, 會先試著從 Cache 中讀取檔案內容.

這 2 個 Flag 可以分開設定, 也可以合併使用, 在設計檔案系統的讀寫效能測試時, 就可以下這 2個Flag, 先將檔案寫入到檔案系統中後, 再讀取該檔案的內容即可. 很簡單, 不是嗎?

2010年2月26日 星期五

在 VirtualBox 中的網路卡模式設定

名詞定義
vbox --> VirtualBox 的簡稱
Host --> 執行 vbox 的電腦, 一般來說是一台真實的電腦, 除非你是在虛擬電腦上再安裝一次 vbox 並產生虛擬電腦中的虛擬電腦. (很饒舌吧!)
Guest --> 透過 vbox 產生出來的虛擬電腦.


虛擬機器的運用上, 有很大的部份都會運用到網路功能, 在網路的設定上, vbox 提供了 5 種不同的模式, 分別說明如下(以 vbox 3.x 為例):

1. 未掛附 (Not Attached)
會在 Guest 環境中出現一張網卡, 但是就像沒有插網路線一樣. 這和未勾選 "啟用網路卡" 不同, 沒有啟用網路卡時, 就好像在電腦上沒有安裝網卡, 而 未掛附是指未接網路線, 在測試程式時, 各軟體的執行行為些差異.

2. NAT(Network Address Translation) --> vbox的預設值
就像在 Guest 和 Host 之間有一道防火牆, Guest 可以透過這道防火牆連線到外部, 但外部不能連進來. 這個設定對 Guest 來說基本上不需什麼額外的設定, IP 的取得也都由 vbox 內建的 dhcpserver 提供. 當然相對也有一些限制, 像外部電腦廣播的 UDP封包就會收不到, 所以不能瀏覽網芳的電腦列表, 外部不能直接連線所以不能建立像 Web Server, FTP server 等服務. 還有一些細節, 可參考 vbox 的說明檔.

3. 橋接網路(Bridged Adapter)
vbox 會在 host 虛擬一張網卡, 過濾並綁定在 Host 上的其中一張網卡上的封包, 這樣可以讓 Guest 就好像一台實體的機器一樣, 取得一個實體的IP, 不管從 Host 或是 Guest 來看, 就好像各自擁有一張獨立的網卡, 並可任意連線到任一台機器(只要原本實體網卡可連線). 對 Host 以外的機器, 也可以認得 Guest的IP 並進行存取.

4. 內部網路(Internal Adapter)
和 橋接網路 很像, Guest 可以直接和外部的電腦進行溝通, 不過有一個限制就是 "外部的電腦" 僅限定由 vbox 產生的 Guest 虛擬電腦. 在 內部網路 可以達成的功能, 實際上皆可用 橋接網路取得, 但內部網路有 2 個額外的好處. 第一是速度, 因為只在 Guest 中溝通, 實際上並不一定需要透過實體的網路卡處理封包, 而是由 vbox 的虛擬網卡直接傳送資料, 效能較佳. 第二是安全性, 非 Guest 環境不能存取, 可減少被外部攻擊的機率.

5. 主機網路(Host-Only Adapter)
和 內部網路 很像, 但可連線的範圍更小, 只限定在同一台主機的 Guest 才能連線. 一般可以用在內部測試時使用, 不需和外部進行連線, 例如測試 Client/Server 程式, 即可在 Host 上建立2個 Guest 設定成 Host-Only 即可開始測試.

在上述的5種模式中, NAT 預設一定會啟動 DHCP 分配IP, Bridge 則和你的實體網卡一樣, 依實際環境決定是否需手動設定 IP. 而在 內部網路 和 主機網路 , 因為不能存取外部的 DHCP server, 所以想自動取得 IP, 就需啟動虛擬網卡的 DHCP 功能, 在 vbox 的 檔案 / 偏好設定 / 網路 / Host-Only networks 中可以選取虛擬網卡並啟動 DHCP server, 這樣你的電腦上各個 Guest 就都可以自動取得 IP 了.

 附上一張以 Windows XP 為 Host, Ubuntu (Linux) 為 Guest , 設定 橋接網路 開啟網芳目錄的畫面.

2010年2月24日 星期三

電腦復活了

在更換了新的電源供應器後, 我的電腦終於復活了... 一個星期不見的 Windows 7 畫面, 終於又出現在我的眼前.

只是現在假期已經結束, 天天上班還沒空來好好的整頓這台新電腦. 在週末或許可以弄些新的東西出來.

2010年2月23日 星期二

程式設計(Delphi) - 移除超過日期的舊檔案

因為之前家裏車停放在門口時, 曾經被小偷敲破玻璃偷走音響/行車電腦. 在家門口裝了台攝影機, 接到電腦上錄影. 因為每天這樣錄下的容量還挺大的, 系統本身又沒有定期刪除舊資料的功能, 所以只好自己寫一個, 免得因為 硬碟空間不足, 而停止錄影.

這個程式適合中放在 Windows 排程中, 可設定每週執行一次, 只保留最近3天的檔案, 這樣就可避免硬碟容量被佔用問題. (會有人需要編好的執行檔嗎? 有需要的留個言吧!)




program rmFolder;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  windows,
  DateUtils,
  shellapi,
  classes;

procedure ShowSyntax() ;
begin
  writeln('移除超過指定天數前建立的目錄及子目錄') ;
  writeln('Syntax:') ;
  writeln(extractFilename(paramstr(0)),' [/D:天數] 路徑') ;
end ;

(*========================================
  取得超過指定期限的目錄(只找第一層), 存放在 slFolder 傳回.

  傳回值:
    符合條件的個數
*)
function GetFolderPath(sPath:string;iOld:integer;slFolder:TStringList):integer ;
var
  h : THandle ;
  dtSpecDate : TDateTime ;
  wfd : TWIN32FindData ;
  LocalFileTime : TFiletime ;
  systime : TSystemTime ;
  dt : TDateTime ;
begin
  result:=0 ;
  slFolder.Clear ;

  dtSpecDate:=today-iOld ;
  h:=findFirstFile(pchar(sPath+'*'),wfd) ;
  if h=INVALID_HANDLE_value then
    exit ;

  repeat
    if ((wfd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)<>0) and
      (wfd.cFileName[0]<>'.') then
      begin
      FileTimeToLocalFileTime(wfd.ftCreationTime, LocalFileTime);
      if not FileTimeTosystemtime(localfiletime,systime) then
        exit ;
      dt:=systemtimetodatetime(systime) ;
      if dt<dtSpecDate then
        slFolder.Add(sPath+strpas(wfd.cFileName)) ;
      end ;
    until not FindNextFile(h,wfd) ;

  findClose(h) ;
  result:=slFolder.Count ;
end ;

Function DelTree(DirName : string): Boolean;
var
 SHFileOpStruct : TSHFileOpStruct;
 DirBuf : array [0..MAX_PATH] of char;
begin
 try
   Fillchar(SHFileOpStruct,Sizeof(SHFileOpStruct),0);
   FillChar(DirBuf, Sizeof(DirBuf), 0 );
   StrPCopy(DirBuf, DirName);
   with SHFileOpStruct do
     begin
     Wnd    := 0;
     pFrom  := @DirBuf;
     wFunc  := FO_DELETE;
     fFlags := FOF_SILENT or FOF_NOCONFIRMATION;
     end;
  Result := (SHFileOperation(SHFileOpStruct) = 0);
  except
    Result := False;
 end;
end;

var
  i, iCode : integer ;
  sPath : string ;
  slFolder : TStringList ;
  iDayOld : integer ;
begin

  if paramcount=0 then
    begin
    ShowSyntax() ;
    exit ;
    end ;

  sPath:='' ;
  iDayOld:=0 ;
  for i:=1 to paramcount do
    begin
    if copy(ParamStr(i),1,3)='/D:' then
      begin
      val(Copy(ParamStr(i),4,6),iDayOld,iCode) ;
      if iCode<>0 then
        begin
        Showsyntax() ;
        exit ;
        end ;
      end ;

    if DirectoryExists(ParamStr(i)) then
      begin
      sPath:=ParamStr(i) ;
      end ;
    end ;

  if AnsiLastChar(sPath)^<>'\' then
    sPath:=sPath+'\' ;

  slFolder:=TStringList.Create ;
  iCode:=GetFolderPath(sPath,iDayOld,slFolder) ;
  for i:=0 to iCode-1 do
    begin
    DelTree(slFolder[i]) ;
    end ;
end.

2010年2月22日 星期一

更換電源供應器

終於在年假結束後, 和電腦公司聯絡上. 說好明天他會寄一個新的 Power 過來, 希望明天收到新的 X-PRO 500瓦電源供應器後, 就可以順利的讓我的新電腦復活過來.

買了電腦, 就是要用的, 沒想到這次運氣這麼不好, 買到不耐操的. 希望下一個 Power supply會更好.

2010年2月20日 星期六

頭份- 貝拉米餐廳

今天全家到頭份的 貝拉米餐廳 吃中餐。

這裏的主題是歐風料理, 場地也很有特色, 門口有一個風車隨風轉動.



進去之後, 右邊是一排停車的位置, 左手邊則是餐廳本體和一個廣場.

這個地方佔地不小, 一大塊草皮.

 草皮都沒灑農藥, 證據就是很多小昆蟲, 上一次是秋天的時候去, 有很多蟀蟀、蚱蜢之類的昆蟲, 小朋友在草地上玩得很高興。有戶外兒童區擺放一座兒童遊樂設施(大型溜滑梯), 還有一個小小的碼頭和池塘. 造景十分不錯. 而且水很乾淨, 這陣子下雨, 池塘裏的黑殼蝦都流到旁邊水溝, 結果幾個小朋友和大人, 就圍那裏抓蝦子, 玩得不亦樂乎. 再過去還有一個藍球架, 可以打半場, 只是我們家的小朋友都太小, 球還丟不進籃筐中. 這次還自備脚踏車一台, 可以在裏頭騎。


水池邊還有一個古早的手動式抽水幫浦, 這時的天氣太冷沒讓小朋友玩水.

吃得東西有幾大項, 我們點了 地中海比薩、海鮮焗意大利麵、雞腿燉飯、牛排... 等, 因為忙著吃, 所以都沒拍相片, (其實相片都是吃完才想到要拍的).

價位大約從 250 ~ 400 之間,住新竹、頭份地區的朋友, 有時間可以去吃吃看. 值得推薦.



程式設計(Delphi) - 英文單字重新排列 (Mix-up Vocabulary)

因為兒子的寒假作業, 有一大題是英文單字的重組, 範圍是他上一學期的英文課本內的單字, 有點簡單的單字很容易就猜出來, 但是一些比較少用到的單字, 真的是想破頭也不知道, 課本又有上百頁的內容, 翻到呆掉. 所以寫了一個小程式, 可以重新列單字的字母順序, 這樣看到眼熟的拼法就可以比較快的找的答案. 未來要改善的話, 應再搭配英文字期進行查表, 可以更有效率. 不過這是應急用的程式, 先將就一下吧.

程式碼如下:





unit UMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Edit1: TEdit;
    MemoResult: TMemo;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

var
  sl : TStringList ;  // 存放可能的排列方式
  iTotal : integer ;  // 排列方式的計數器

// 使用 rescursive 進行排列, 不要輸入長度超過 8 的字串, 8!=40320種排列已經看呆了
// 傳入值: p: 尚未使用的字串, q:準備輸出的已排列字串
procedure remap(p, q : string) ;
var
  i, iLen : integer ;
begin
  if p='' then
    begin
    sl.Add(q) ;
    inc(iTotal) ;
    end ;

  iLen:=length(p) ;
  for i:= 1 to iLen do
    remap(copy(p,1,i-1)+copy(p,i+1,iLen-i), q+copy(p,i,1)) ;
end ;

procedure TForm1.Button1Click(Sender: TObject);
begin
  // 初始化
  sl:=TStringList.Create ;
  iTotal:=0 ;
  memoResult.Lines.Clear ;
  
  // 要重組的字串放在 edit1.text 中傳入
  remap(Edit1.Text,'') ;
  
  // 顯示可能的排列方式個數
  caption:=inttostr(iTotal) ;
  
  // 列出所有的排列方式
  memoResult.Lines.AddStrings(sl);
  
  // free memory
  sl.free ;
end;

end.





VirtualBox 虛擬機器(虛擬化應用軟體)

虛擬機器, 指的是在一台電腦上, 運用特定的軟體, 虛擬出多台電腦環境, 例如在 Windows XP 為基礎的作業環境( 稱為HOST), 可以再虛擬出多台電腦, 安裝 Linux, Windows 98, Windows 7 等不同的作業系統(稱為GUEST). 這樣做的好處有不少, 對企業來說, 可以在一台機器上設置多種服務, 並動態調配資源, 現在很熱門的雲端運算, 其實也是一種虛擬化的運用. 對個人來說, 像我這樣會測試各樣軟體的人, 以前需要頻繁的重灌系統, 現在只要在一個基礎環境下切換不同的虛擬機器即可, 甚至以前要試 Client/Server 的環境時, 需要多台電腦. , 現在只要在同一台電腦上, 開啟多個虛擬機器, 就可以模擬網路的使用, 非常方便.

目前較常見, 而且是免費讓個人使用的虛擬化應用軟體, 有下列三種 VMWare Server , Virtual PC, VirtualBox. 這三個軟體我都有用過, 目前使用上以 VirtualBox 最順手, 感覺使用上的效能也是最好的.  原本想要寫一篇三個軟體的比較, 可是不幸的, 我的新電腦電源供應器壞了, 而這幾天年假電腦公司也休息, 聯絡不到人可以維修, 得等到電腦修好了, 才能進行實測囉.


2010年2月18日 星期四

程式技巧(Delphi) - 包含子目錄的檔案複製 ( 有 檔案個數 及 檔案大小 2個進度列)

這個程式是拿來當範例用的, 還有許多地方可以加強, 例如對目的檔案的日期、屬性等訊息並未複製, 只有檔案內容的複製. 未處理 unicode 檔案, 未檢查空間是否足夠, 未用多執行緒加速...等. 不過已可達到 複製包含子目錄下的檔案, 並顯示進度列這 2 個基本需求





unit Utest;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ComCtrls;

const
  _i32MB=32*1024*1024 ;

type
  TForm1 = class(TForm)
    LabelSrc: TLabel;
    EditSrc: TEdit;
    LabelTar: TLabel;
    EditTar: TEdit;
    btnCopy: TButton;
    ProgressBarByNum: TProgressBar;
    ProgressBarBySize: TProgressBar;
    procedure btnCopyClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    iNumofFiles : integer ;   // 記錄目錄下檔案總數
    i64SizeofFiles : int64 ;  // 記錄目錄下檔案大小總和
    pBuf : pointer ;
    function DoCopyFile(sSrcFile,sTarFile:string;iLeftNum:integer;var i64LeftSize:int64):boolean ;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
var
  slSrcFiles : TStringList ;

// 輸入: 要查詢的路徑(要含 *.*) , 要存放檔案大小總和的變數(用 int64避免4GB問題)
// 傳回值: 檔案總數
//         檔案列表會存放到 slSrcFiles 中, 此物件需在外部宣告
function TravelTree(sRoot:string; var i64TotalSize:int64):integer ;
var
  fd : WIN32_FIND_DATA ;
  h : Thandle ;
  sPath, sName : string ;
begin
  result:=0 ;
  h:=findfirstfile(pchar(sRoot),FD) ;
  if h=INVALID_HANDLE_VALUE then
    exit ;

  sPath:=ExtractFilePath(sRoot) ;
  repeat
    sName:=strpas(fd.cFilename) ;
    if (fd.dwFileAttributes and FILE_ATTRIBUTE_DIRECTORY)=FILE_ATTRIBUTE_DIRECTORY then
      begin
      // 若是目錄則用 recursive
      if (sName<>'.') and (sName<>'..') then
        result:=result+TravelTree(sPath+sName+'\*.*',i64totalSize) ;
      end
    else
      begin
      result:=result+1 ;
      slSrcFiles.Add(sPath+sName) ;

      if fd.nFileSizeHigh=0 then
        i64TotalSize:=i64TotalSize+fd.nFileSizeLow
      else
        i64TotalSize:=i64TotalSize+(int64(fd.nFileSizeHigh)shl 32)+fd.nFileSizeLow ;
      end ;
    until FindNextFile(h,fd)=false ;
  windows.FindClose(h) ;
end ;

function TForm1.DoCopyFile(sSrcFile,sTarFile:string;iLeftNum:integer;var i64LeftSize:int64):boolean ;
var
  fsSrc, fsTar : TFileStream ;
  sPath : string ;
  iReadSize : integer ;
begin
  sPath:=extractFilePath(sTarFile) ;
  if not directoryExists(sPath) then
    forceDirectories(sPath) ;

  result:=true ;
  try
    fsSrc:=TFileStream.Create(sSrcFile,fmOpenRead);
    fsTar:=TFileStream.Create(sTarFile,fmCreate);
    try
      repeat
        iReadSize:=fsSrc.Read(pBuf^,_i32MB) ;
        fsTar.Write(pBuf^,iReadSize) ;
        i64LeftSize:=i64LeftSize-iReadSize ;

        // 更新 大小 的進度列
        progressBarBySize.Position:=round((i64SizeOfFiles-i64LeftSize)/i64SizeOfFiles*100) ;
        // 處理訊息, 例如中斷執行
        application.ProcessMessages ;
        until iReadSize<_i32MB ;
    finally
      fsSrc.Free ;
      fsTar.Free ;
      end ;
    // 更新 個數 的進度列
    progressBarByNum.Position:=round((iNumOfFiles-iLeftNum)/iNumOfFiles*100) ;
  except
    result:=false ;
    end ;
end ;

procedure TForm1.btnCopyClick(Sender: TObject);
var
  i64Size: int64 ;
  sTarPath, sTarFile, sSrcFile : string ;
  iSrcLen : integer ;
  i : integer ;
begin
  i64Size:=0 ;
  slSrcFiles:=TStringList.Create ;
  try
    // 計算目錄下的檔案總數及檔案大小總和
    iNumofFiles:=TravelTree(EditSrc.Text+'\*.*',i64Size) ;
    i64SizeOfFiles:=i64Size ;

    // 進度列用 百分比 計算
    progressbarByNum.Max:=100 ;
    progressbarBySize.Max:=100 ;
    progressbarByNum.Position:=0 ;
    progressbarBySize.Position:=0 ;

    i:=slSrcFiles.Count-1 ;
    iSrcLen:=length(editSrc.text)+1 ;
    sTarPath:=editTar.text ;
    if not directoryExists(sTarPath) then
      forceDirectories(sTarPath) ;
    while i>=0 do
      begin
      // 來源檔名
      sSrcFile:=slSrcFiles[i] ;
      // 目的檔名
      sTarFile:=sTarPath+copy(sSrcFile,iSrcLen,maxint) ;
      // 複製每一個檔案
      DoCopyFile(sSrcFile,sTarFile, i, i64Size) ;

      dec(i) ;
      end ;

  finally
    slSrcFiles.Free ;
    end ;

end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  getmem(pBuf,_i32MB) ;

end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  freemem(pBuf,_i32MB) ;
end;

end.




2010年2月17日 星期三

慘劇-- 新電腦不能開機了

今天是悲慘的一天...

新買的那台 Q9400 , 居然不能開機了, 電腦鍵按下去, 一點反應也沒有, 看來應是 Power 故障, 這可是新品呀!! 就是敗在這一顆  X-PRO 500瓦的電源供應器 上

怨恨呀!! 又是過年期間, 打電話到電腦公司去, 都沒人接, 看來還要再過幾天才會有人上班, 為什麼我會遇到這麼悲情的事... 嗚嗚嗚...

新電腦不能用, 所以只好還是用我的 NB 上網, 原本想在新電腦上跑跑東西的, 就沒辦法了....

時不予我呀!!


2010年2月15日 星期一

複製檔案的好幫手

買了新電腦後, 一件麻煩的工作就是要把舊資料搬到新的電腦上. 資料又有區分, 有些是放在原本的備份硬碟上, 有些是在舊的電腦中的舊硬碟. 原本想在花些時間重新整理, 不過因為偷懶, 不想反覆的拆裝硬碟, 所以除了將一顆 250GB 的 碟硬加到新的機器上外, 其他的都用 USB外接硬碟的方式複製資料。




因為嫌 Windows 本身的檔案複製效能不好, 所以特別又到網路上搜尋一番, 看有什麼比較好用的工具可以加速檔案的搬移, 我預計要複製到新電腦上的資料, 大約有 300GB, 一堆自己拍的相片、DV影片檔, 若是讓 Windows 慢慢跑, 實在是沒什麼耐心.



Google 之後, 找到幾套較知名的檔案複製工具, 因為現在只是要找個比檔案總管快的系統, 所以也沒有仔細的比較, 只用了 2 套 , TeraCopy 和 FastCopy. 其中 FastCopy 在他的網頁上, 宣稱是Windows 系統上最快的複製檔案工具.(FastCopy is the Fastest Copy/Delete Software on Windows.) 這套是日本人寫的程式, 有分享 Source Code. 另一套TeraCopy則是 Code Sector 這家公司的產品, 家庭用戶可以免費使用, 另外有出 TeraCopy Pro 的版本, 不過反正我們也不會去用, 還是以 TeraCopy 為使用的對像.



FastCopy 號稱最快, 當然要先試用看看. 只是安裝後有些小小的失望, 因為UI給人的第一印象實在不怎麼樣. (見下圖)





相較之下, TeraCopy 就有質感多了.(見下圖)



這兩者都有提供整合到檔案總管的右鍵選單中, 也可以取代原本在檔案總管中 複製/貼上 以及 拖曳/放下 的功能. 但我個人覺得 TeraCopy 的整合寫得比較好, 基本上就很好的取代原本檔案總管中的複製檔案功能. FastCopy 雖然就功能上都能達到, 但總覺得操作畫面做得不精緻.



接下來是對檔案操作的效能問題, 這兩者都強調使用 多執行緒及其他加速方法, 可大幅改善 Windows 檔案複製的效能, 首先是使用TeraCopy 從 USB硬碟上複製 DVD 映像檔的目錄, 大約 30GB大小, 直接在檔案總管中拖放後, 就開始顯示 TeraCopy 的複製進度畫面, 速度一開始顯示 40MB/秒 , 後來速度很快就掉下來, 一直維持在 26~28 MB/秒 之間. TeraCopy平均大約 27MB, 效能幾乎就是那個USB外接碟宣稱的讀取速度.



用FastCopy 複製相片檔目錄, 大小約 20 GB , FastCopy 平均速度約 23~24 MB/秒 , 不過這個目錄下檔案數較多, 有幾百KB 的檔案也有幾 MB 的檔案, 和DVD目錄夾下的幾乎都是幾百 MB~幾GB 大小的檔案有差異, 不過看來起效能並看不出 "最快" 的感覺.



後來因為 TeraCopy 快了一點點, 而且使用較方便, 所以其他的檔案都是用 TeraCopy 進行備份. 在本機兩顆不同的硬碟之間互相 複製檔案 的速度也很不錯, 可以達到 42 MB/秒 左右的效能



關於 TeraCopy / FastCopy 以及其他像 KillCopy 、ExtremeCopy 等軟體, 就等有空再來寫一篇使用測試報告.

2010年2月14日 星期日

正月初一新年好

正月初一新年好, 二月十四情人節, 雙喜臨門剛剛好!

新竹這兩天都是陰雨綿綿, 雖然不冷, 可是卻是叫人不想出門, 現在是老婆和小孩都睡覺去, 才能有點時間上來更新.

新買的 Q9400 果然效能比之前用的電腦好太多了, 至少關機進系統的速度都是有秒當單位即可, 用不了一分鐘. 昨天試著安裝 Windows 7 Pro, 安裝過程也都十分順利, 12:35 ~ 13:04 安裝完整個 Windows 7 到可以使用,雖然比預期的慢了一點, 但還是可以接受.

目前正試著設定 WOL 及 遠端桌面 ,  WOL 還好, 試了一下就已經可以遠端開機. 可是現在卡在遠端電腦無法正確的建立連線. 防火牆設定有檢查過了, 可是還連不到 Q9400, 但是從 Q9400 可以 ping 到另一台 ASUS 的 筆記型電腦, 為什會一直不行呢? 晚一點再繼續研究...

2010年2月12日 星期五

小年夜

 今天是2月12日, 也是春節前的最後一個上班日. 公司裏頭今天也是冷清了許多, 有三分之一的人不在, 出差的出差, 請假的請假, 顯得份外冷清.

今年的假比往年慢了一天才放, 年味就覺得淡了好多, 還在上班, 沒什麼要過年的感覺. 記得多年前, 每逄春節的前幾天, 就開始準備過年, 採買禮盒、大掃除、整理環境... 到賣場、商店這些地方, 都會聽到有年味的音樂歌曲... 今年好像到現在都還沒聽到.

不過在小年夜(除夕前一天)拜天公還是要的. 這回訂在 丑時 , 也就是半夜一點開始拜, 所以現在先把今天的事記下, 免得晚一點準備拜拜的東西後就沒空了.

而且這種節日, 都是陪家人的時間, 反而不如平常能待在電腦前的時間多.

2010年2月11日 星期四

新電腦 2 台到貨

今天下午 2 台新電腦都到貨了

老婆用的 ASUS CS5111 (E5400 + 4GB DDR2 + 500GB HDD)



我測試用的組裝機 (Q9400 + 8GB DDR3 + 640GB HDD)

我用的這台雖然醜了點(尤其是和老婆的那台 CS5111 放在一起時), 但是效能不錯的. 可惜明天還要上班, 沒什麼時間好好擺弄這 2 台電腦. 不過已經準備把下星期的春節假期, 至少貢獻三分之一給這 2 台電腦了!!

測試用的電腦得先準備好幾個常用的作業系統,和相關的應用軟體. 講到這個得要再說一下, 微軟的 Technet Plus 還是很好用的. 為了要更方便的這些有的沒的環境, 我還特別訂閱了 
TechNet Plus Direct . , 可以完全線上存取 伺服器和作業系統 , 而且是沒有時間限制的完整版評估軟體. 對我這種想要試試新玩意兒的人很方便.

程式技巧(Delphi) - Windows 內建的旋轉圖片函數 PlgBlt

Windows 系統有內建的旋轉圖片函數 PlgBlt , 但大多數寫 Windows 程式的人都不知道, 提供個範例

// 計算旋轉後的座標
function RotateXY(dbTheda:double;p1:TPoint):TPoint ;

const
  _dbLastT:double=-99999.999 ;
  _cosA:double=0.0 ;
  _sinA:double=0.0 ;
var
  dbA : double ;
begin
  if dbTheda<>_dbLastT then
    begin
    dbA:=dbTheda*Pi/180 ;
    _sinA:=sin(dbA) ;
    _cosA:=cos(dbA) ;
    _dbLastT:=dbTheda ;
    end ;

  Result.x:=round(p1.x*_cosA+p1.y*_sinA) ;
  Result.y:=round(-p1.x*_sinA+p1.y*_cosA) ;
end ;
 
// 將 image1 中的影像旋轉指定的角度
procedure TForm1.Button1Click(Sender: TObject);

var
  ptOrgCenter, ptTarCenter, ptc : TPoint ;
  pta : array[0..3] of TPoint ;
  ba : array[0..3] of integer ;
  i : integer ;
  bmp : TBitmap ;
  dbTheta : Double ;
begin
  ptOrgCenter.x:=Image1.Picture.Width div 2 ;
  ptOrgCenter.y:=Image1.Picture.Height div 2 ;

  dbTheta:=StrToFloat(Edit1.Text) ;
  pta[0]:=RotateXY(dbTheta,Point(0,0)) ;

  pta[1]:=RotateXY(dbTheta,Point(Image1.Picture.Width-1,0)) ;
  pta[2]:=RotateXY(dbTheta,Point(0,Image1.Picture.Height-1)) ;
  pta[3]:=RotateXY(dbTheta,Point(Image1.Picture.Width-1,Image1.Picture.Height-1)) ;

  bmp:=TBitmap.Create ;
  bmp.PixelFormat:=pf24bit ;
  bmp.Canvas.Brush.Color:=clBtnFace ;

  for i:=0 to 3 do
    ba[i]:=pta[i].x ;

  bmp.width:=MaxIntValue(ba)-MinIntValue(ba) ;

  for i:=0 to 3 do
    ba[i]:=pta[i].y ;

  bmp.Height:=MaxIntValue(ba)-MinIntValue(ba) ;

  ptc:=RotateXY(dbTheta,Point(Image1.Picture.Width div 2,Image1.Picture.Height div 2)) ;

  ptTarCenter.x:=bmp.Width div 2 ;
  ptTarCenter.y:=bmp.Height div 2 ;

  pta[0].x:=pta[0].x+ptTarCenter.x-ptc.x ;
  pta[0].y:=pta[0].y+ptTarCenter.y-ptc.y ;
  pta[1].x:=pta[1].x+ptTarCenter.x-ptc.x ;
  pta[1].y:=pta[1].y+ptTarCenter.y-ptc.y ;
  pta[2].x:=pta[2].x+ptTarCenter.x-ptc.x ;
  pta[2].y:=pta[2].y+ptTarCenter.y-ptc.y ;

  PlgBlt(bmp.Canvas.Handle,pta,Image1.Canvas.Handle,0,0,image1.Picture.Width-1,image1.Picture.Height-1,0,0,0) ;

  Canvas.Draw(0,0,bmp) ;

  bmp.SaveToFile(ExtractFilePath(Application.Name)+'111.bmp') ;  // 將結果存成 BMP 檔案
  bmp.free ;
end;

2010年2月10日 星期三

買電腦前的評估

這次為了買新電腦, 做了不少功課. 記錄下來看看以後會不會後悔買錯東西.

買的電腦有 2 台, 分開記錄如下

第一台是老婆用的電腦, 目的是要取代舊的那台 P4 2.66 的舊電腦. 因為用了好多年, 現在主機上的幾個風扇吵到不行, 一直捨不得花錢換電腦的老婆終於受不了了, 要求換一台 "安靜無聲" 的電腦. 除了要安靜外, 老婆的另一個要求是要好看, 效能反而不是重點. 所以評估的重點放在小型的電腦上. 一開始考慮 華碩 的 eeeBox (如下圖)
只是硬碟太小, 怕老婆到時要我換硬碟時麻煩, 只要先放棄了. 再來評估的是 浩鑫 的 XPC , 號稱 (ICE 2)水冷式熱導管散熱模組 讓整台電腦 小冷美靜 , 只可惜對它四方的外形很有意見(如下圖), 還是放棄.



幾番尋找, 終於在 YAHOO 上找到了一台各方便都符合需求的機器 華碩的 CS5111 , 造型好看, 效能還可以接受(intel E5400 + 4GB RAM + 500GB HDD), 又已裝好 Windows 7 , 終於就給他買下去, 外觀如下圖.

只是在 Yahoo 拍賣下了單後, 老闆才說現在缺貨, 要到 2010-02-11才有貨. 現在還在痴痴的等, 還沒看到東西, 等收到東西再來篇開箱文.


第二台是我自己測試用的電腦. 在公司試一些系統雖然方便, 可是一直被老婆抱怨太晚回家, 所以弄一台在家裏自己玩. 所以這台電腦要考量的就是效能, 因為測試要切換不同的 OS , 尤其是 微軟的 OS 和 Server, 不先玩熟要建立起來, 還是很多小問題會發生, 但我也不可能買很多台, 所以到時會虛擬機器來跑就是唯一的選擇, 在這樣的前提下買台強壯一點的主機就很重要的. 不過 價錢 也是很重要的, 打算把年終的一部份砸下去, 預算訂在 3 萬以下. 一開始設定的目標就是組裝好的電腦, 因為現在年紀大了, 懶得一樣一樣零件自己裝, 還是花點錢買裝好的比較快.

起先想和上一台一樣, 買台 華碩 的電腦, 看上了 CG5270 (Q9400 + 6GB RAM +750GB HDD), 外觀如下圖.
 但是這台就要價將近 3萬, Q9400 好像風評也不是很好, 大多人都是換 Q9550 或是直接上 i5 或 i7. 而買 華碩 的可沒辦法換 CPU, 且一換就超過預算. 在 yahoo 和 PChome 看來看去, 又發現一台 宏碁 M5810 (見下圖), i5 750 + 2GB RAM + 640GB*2 HDD



自己再升級到 4GB 的 RAM , 總費用也不超過 30000, 開始心動了. 可是查了一下規格才發現, i5 不支援  VT-d (Intel's Virtualization Technology for Directed I/O), 這樣在開虛擬主機時會有點影響到效能, 但換 i7 又會超過預算, 害我猶豫了好幾天.

最後還是決定在 YAHOO 拍賣買台組裝機, 反正也是人家組好的, 免麻煩. (如下圖)
Q9550 + 8GB RAM + 640GB HDD 這樣 28300. 只是沒想到, 沒想到墨菲定律再次發威. 老闆都已經說下午會出貨, 結果又打電話來通知, 因為 Q9550 全台北都缺貨, 調不到貨可出, 問我要不要換Q9400 折 2500, 若是不行也只好退我錢~~~

為了讓我在這個春節假期有電腦可以用, 最後還是認了, Q9400 也是能用, 省下來的錢再去買顆硬碟算了, 反正空間永遠不嫌多, 我可以用時間換取空間... :)

就這樣買了 2 台電腦, 雖然到今天為止都還沒看到東西, 不過有希望都能在這星期收到貨, 這樣下星期的春節假期才有點事做.



啟動

今天是個具有紀念性的一天.
終於開始了網誌的記錄. 預計本週可以收到訂的新電腦, 預期在這個地方記錄各式IT工具軟體、小技巧、程式設計等等的心得.

讓我們開始新的一頁吧!

歷史的巨輪開始轉動... 轟...