วันพุธที่ 30 พฤศจิกายน พ.ศ. 2554

Linux HugeTLBfs: Improve MySQL Database Application Performance

http://www.cyberciti.biz/tips/linux-hugetlbfs-and-mysql-performance.html


Linux HugeTLBfs: Improve MySQL Database Application Performance

by VIVEK GITE on MAY 20, 2009 · 10 COMMENTS

Applications that perform a lot of memory accesses (several GBs) may obtain performance improvements by using large pages due to reduced Translation Lookaside Buffer (TLB) misses. HugeTLBfs is memory management feature offered in Linux kernel, which is valuable for applications that use a large virtual address space. It is especially useful for database applications such as MySQL, Oracle and others. Other server software that uses the prefork or similar (e.g. Apache web server) model will also benefit.


The CPU's Translation Lookaside Buffer (TLB) is a small cache used for storing virtual-to-physical mapping information. By using the TLB, a translation can be performed without referencing the in-memory page table entry that maps the virtual address. However, to keep translations as fast as possible, the TLB is usually small. It is not uncommon for large memory applications to exceed the mapping capacity of the TLB. Users can use the huge page support in Linux kernel by either using the mmap system call or standard SYSv shared memory system calls (shmget, shmat).

Only selected hardware and operating system support memory pages greater than the default 4KB. The following configuration tested on RHEL 5.3 64 bit using a stock kernel with tons of RAM and multiple CPUs.

How do I verify that my kernel supports hugepage?

Type the following command:
$ grep -i huge /proc/meminfo
Sample output:

HugePages_Total:     0 HugePages_Free:      0 HugePages_Rsvd:      0 Hugepagesize:     2048 kB

The kernel built with hugepage support should show the number of configured hugepages in the system. Otherwise, you need to be built Linux kernel with the CONFIG_HUGETLBFS option.

How do I configure HugeTLBfs?

The HugeTLBfs feature permits an application to use a much larger page size than normal, so that a single TLB entry can map a larger address space. A HugeTLB entry can vary in size. For example, i386 architecture supports 4K and 4M (2M in PAE mode) page sizes, ia64 architecture supports multiple page sizes 4K, 8K, 64K, 256K, 1M, 4M, 16M, 256M and ppc64 supports 4K and 16M. To allocate hugepage, you can define the number of hugepages by configuring value at /proc/sys/vm/nr_hugepages, enter:
# sysctl -w vm.nr_hugepages=40
Above command will try to configure 40 hugepages in the system. Now, run the following again:
# grep -i huge /proc/meminfo
Sample output:

HugePages_Total:    40 HugePages_Free:     40 HugePages_Rsvd:      0 Hugepagesize:     2048 kB

Where,

  • HugePages_Total: 40 - The size of the pool of hugepages. On busy server with 16/32GB RAM, you can set this to 512 or higher value.
  • HugePages_Free: 40 - The number of hugepages in the pool that are not yet allocated.
  • HugePages_Rsvd: 0 - The number of hugepages for which a commitment to allocate from the pool has been made, but no allocation has yet been made.
  • Hugepagesize: 2048 kB -

Configure MySQL to use HugeTLBfs

In MySQL, large pages can be used by InnoDB, to allocate memory for its buffer pool and additional memory pool. Find mysql user id:
# id mysql
Sample output:

uid=27(mysql) gid=27(mysql) groups=27(mysql)
Open /etc/sysctl.conf:
# vi /etc/sysctl.conf
Add the following configuration:

# Set the number of pages to be used. # Each page is normally 2MB, so a value of 40 = 80MB. # Set it 512 or higher if you have lots of memory vm.nr_hugepages=40 # Set the group number (mysql group number is 27) that is allowed to access this memory. The mysql user must be a member of this group. vm.hugetlb_shm_group=27 # Increase the amount of shmem allowed per segment # This depends upon your memory, remember your kernel.shmmax = 68719476736 # Increase total amount of shared memory. kernel.shmall = 4294967296

Save and close the file. Reload settings:
# systclt -p
Open /etc/my.cnf:
# vi /etc/my.cnf
Add large-pages options

[mysqld] large-pages datadir=/var/lib/mysql socket=/var/lib/mysql/mysql.sock user=mysql # rest of config...

Save and close the file. Open /etc/security/limits.conf, enter:
# vi /etc/security/limits.conf
Append the following line to set max locked-in-memory address space to unlimited:

@mysql      soft    memlock         unlimited @mysql      hard    memlock         unlimited

Save and close the file. Finally, restart the mysql server:
# /etc/init.d/mysqld restart

A note about mount command option

If your application uses huge pages through the mmap() system call, you have to mount a file system of type hugetlbfs like this:
# mount -t hugetlbfs none /myapp
Another example, with more control over uid, gid and other options:

# mount -t hugetlbfs -o uid={value},gid={value},mode={value},size={value},nr_inodes={value} none /myapp

Further readings:

  1. Please refer to kernel documentation in Documentation /vm/hugetlbpage.txt for more information. MySQL large memory support help page.
  2. man page - mount

วันพุธที่ 16 พฤศจิกายน พ.ศ. 2554

hosxp_getdataset_reportserver

var cds:tclientdataset;
begin
cds:=tclientdataset.create;
cds.data:=hosxp_getdataset_reportserver('select xxx from xxx');
cds.AssignDataToMainReport;
cds.free;

end;

วันอาทิตย์ที่ 25 กันยายน พ.ศ. 2554

install Percona 5.5 on Centos6

'm unable to install Percona 5.5 on Centos6 without using --nogpgcheck:

rpm -Uhv http://www.percona.com/downloads/percona-release/percona-rel ease-0.0-1.x86_64.rpm
yum install Percona-Server-client-55 Percona-Server-server-55
...lots of output...
Package Percona-Server-client-55-5.5.14-rel20.5.149.rhel6.x86_64.rpm is not signed

I have a /etc/yum.repos.d/Percona.repo file that looks correct and also have a /etc/pki/rpm-gpg-RPM-GPG-KEY-percona file.

If I force it in with --nogpgcheck it conflicts with mysql-libs which a bunch of core packages depend on so the installation ends up looking like this (on a clean machine with a fresh Centos 6 install):

yum remove mysql-libs
yum install --nogpgcheck Percona-Server-client-55 Percona-Server-server-55
yum install --nogpgcheck mysql-libs cronie cronie-anacron crontabs postfix sysstat webalizer

Is running Percona 5.5 on Centos 6 recommended at this time?

วันอาทิตย์ที่ 19 มิถุนายน พ.ศ. 2554

วันพฤหัสบดีที่ 16 มิถุนายน พ.ศ. 2554

WinEXEC กับ hosxp

procedure TForm1.Button1Click(Sender: TObject);
var url:string;
begin
url:=vartostr(getsqldata('select url from patch'));
WinEXEC('HOS_Update.exe '+url);
end;

วันจันทร์ที่ 6 มิถุนายน พ.ศ. 2554

ติดตั้ง Windows XP ด้วย USB Flash Drive (work! 100%)

ติดตั้ง Windows XP ด้วย USB Flash Drive (work! 100%)

วันนี้จะมาแนะนำวิธีการลงวินโดว ผ่านทาง USB รับรองวิธีนี้ได้ผล 100% แต่ต้องเป็นเครื่องที่รองรับการ boot USB เท่านั้น โดยปกติแล้วเครื่องรุ่นใหม่ๆทีี่เพิ่งออกมาก็รองรับ boot USB ได้แล้ว การลงวินโดวผ่านทาง USB เร็วกว่าลงจากแผ่นอย่างมาก ท้ายบทความมีตัวอย่างการทดลองลงเครื่อง ASUS EEE PC 4G ด้วย

ก่อนอื่นต้องดาวน์โหลดโปรแกรม WinSetupFromUSB กันก่อน

Mirror 1 : http://www.mediafire.com/?iydhhvmjmnm


ขั้นตอนการทำ USB Flash Drive

เปิดโปรแกรม WinSetupFromUSB_1-0-beta6.exe

เลือก Drive ที่ต้องการติดตั้ง

เลือกประเภทระบบปฎิบัติการ

กด OK

กด OK

จอนี้จะดับไปเองเป็นการเสร็จสิ้นการ Format

ปิดหน้าต่างนี้ไปได้เลย

เลือกแผ่น Windows XP ที่ต้องการ

กด GO เพื่อเริ่มกระบวนการ

เสร็จแล้ว

ไฟล์ใน USB Flash Drive ที่พร้อมใช้

ตัวอย่างวิธีปรับแต่ง BIOS เพื่อลงวินโดวผ่านทาง USB

เข้าไปที่หน้า BIOS เพื่อตั้งค่า Boot

ตั้ง Hard Disk Drives

เลือก 1st Drive เป็น USB Flash Drive

ตั้ง Boot Device Priority

เลือก Boot Device Priority

USB Flash Drive

USB Flash Drive

แบบนี้แปลว่า Boot ได้

ลงวินโดวตามขั้นตอนปกติ

ติดตั้ง Windows 7 ด้วย USB Flash Drive (work! 100%)

ติดตั้ง Windows 7 ด้วย USB Flash Drive (work! 100%)

ภาคต่อจากตอนที่แล้ว หลังจากที่ได้แนะนำวิธีลง Windows xp ด้วย USB Flash Drive ไปแล้ว วันนี้จะมาแนะนำวิธีลง Windows 7 ด้วย USB Flash Drive กันครับ ด้วยโปรแกรมที่มีชื่อว่า Windows 7 USB DVD Download Tool จึงช่วยให้เราติดตั้ง Windows 7 ได้อย่างง่ายดายกว่าเดิม สำหรับบทความนี้คงไม่ต้องกังวลว่าเครื่องจะรองรับการบูทผ่าน USB หรือเปล่า เพราะแน่นอนอยู่แล้วว่าเครื่องที่ท่านจะลง Windows 7 นั้นไม่ใช่เครื่องเก่าแก่โบราณแน่ๆ

ก่อนอื่นต้องดาวน์โหลดโปรแกรม Windows 7 USB DVD Download Tool กันก่อน

Mirror 1 : http://www.mediafire.com/?n51hhxeado2yca1


ขั้นตอนการทำ USB Flash Drive

เปิดโปรแกรม Windows 7 USB DVD Download Tool

เลือกไฟล์ iso ของแผ่น Windows 7

เลือก USB Device

เลือก Flash Drive ปลายทางแล้วกด Being copying

วันเสาร์ที่ 4 มิถุนายน พ.ศ. 2554

สวิตซ์เปิด-ปิด 4 ช่องควบคุมผ่าน พอร์ตอนุกรม

http://www.adisak51.com/project06.html

delphi ตัวอย่างการตรวจสอบ version และ update โปรแกรม

unit frmMain;

interface

{$WARN SYMBOL_PLATFORM OFF}

uses
Forms, Windows, Classes, Controls, StdCtrls, ExtCtrls,
dxCore, dxButton, WinInet, Gauges, SysUtils, Dialogs;

type
TfrmLiveUpdate = class(TForm)
lblVersion: TLabel;
btnNext: TdxButton;
lblToDo: TLabel;
bvlBevel1: TBevel;
lblStatus: TLabel;
gauDownload: TGauge;
btnCancel: TdxButton;
bvlBevel2: TBevel;
lblWhatsNew: TLabel;
procedure FormPaint(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure btnNextClick(Sender: TObject);
procedure btnCancelClick(Sender: TObject);
procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
{ Steps }
procedure CheckForUpdates;
procedure DownloadUpdate;
procedure InstallUpdate;
private
{ Private declarations }
NumStep: Byte;
IndexFileName: String;
PatchFileName: String;
TheFile: TStringList;
public
{ Public declarations }
end;

const
NewVersionLine : Byte = 0;
FileSizeLine : Byte = 1;
FileNameLine : Byte = 2;
var
frmLiveUpdate: TfrmLiveUpdate;
CurVer: String[5];

implementation

{$R *.dfm}

function RunAndWait(const TheApp: String; const Wait: Boolean): Boolean;
var
CmdLine: Array[0..255] Of char;
StartupInfo: TStartupInfo;
ProcessInfo: TProcessInformation;
begin
Result := False;
StrPCopy(CmdLine, TheApp);
FillChar(StartupInfo, SizeOf(StartupInfo), 0);
StartupInfo.cb := SizeOf(StartupInfo);
StartupInfo.dwFlags := STARTF_USESHOWWINDOW;
StartupInfo.wShowWindow := SW_SHOWNORMAL;
If CreateProcess(Nil, CmdLine, Nil, Nil, False, NORMAL_PRIORITY_CLASS, Nil, Nil, StartupInfo, ProcessInfo) Then Begin
Result := True;
If Wait Then
WaitForSingleObject(ProcessInfo.hThread, INFINITE);
CloseHandle(ProcessInfo.hThread);
CloseHandle(ProcessInfo.hProcess);
end;
end;

function DownloadFile(Const Source, Dest: String; Const ToLabel: TLabel = Nil; Const PrgBar: TGauge = Nil): Boolean;
var
NetHandle: HINTERNET;
UrlHandle: HINTERNET;
Buffer: Array[0..1024] Of Char;
BytesRead, Reserved: dWord;

ReadFile: String;
NumByte: Integer;
FileSize: dWord;
begin
ReadFile := '';
ToLabel.Caption := 'Connecting...';
Application.ProcessMessages;
NetHandle := InternetOpen('Delphi 5.x', INTERNET_OPEN_TYPE_PRECONFIG, Nil, Nil, 0);

If Assigned(NetHandle) Then Begin
UrlHandle := InternetOpenUrl(NetHandle, PChar(Source), Nil, 0, INTERNET_FLAG_RELOAD, 0);

If Assigned(UrlHandle) Then Begin
If (ToLabel <> Nil) Or (PrgBar <> Nil) Then Begin
Buffer := '';
FileSize := SizeOf(Buffer);
Reserved := 0;
If HttpQueryInfo(UrlHandle, HTTP_QUERY_CONTENT_LENGTH, @Buffer, FileSize, Reserved) Then
FileSize := StrToIntDef(Buffer, -1);
End;

If ToLabel <> Nil Then
ToLabel.Caption := '0 of 0 bytes';
If PrgBar <> Nil Then Begin
PrgBar.MinValue := 0;
PrgBar.MaxValue := FileSize;
PrgBar.Progress := 0;
End;

FillChar(Buffer, SizeOf(Buffer), 0);
Repeat
FillChar(Buffer, SizeOf(Buffer), 0);
InternetReadFile(UrlHandle, @Buffer, SizeOf(Buffer), BytesRead);
For NumByte := 0 To BytesRead - 1 Do
ReadFile := Concat(ReadFile, Buffer[NumByte]);

If ToLabel <> Nil Then
ToLabel.Caption := FormatFloat('0,000', Length(ReadFile)) + ' of ' + FormatFloat('0,000', FileSize) + ' bytes';
If PrgBar <> Nil Then
PrgBar.Progress := PrgBar.Progress + StrToInt(IntToStr(BytesRead));
Application.ProcessMessages;
Until BytesRead = 0;
InternetCloseHandle(UrlHandle);
End;
InternetCloseHandle(NetHandle);
End;

ToLabel.Caption := '';
Application.ProcessMessages;

If Length(ReadFile) > 0 Then
Begin
If FileExists(Dest) Then
DeleteFile(PChar(Dest));

With TFileStream.Create(Dest, fmCreate) Do
Try
Write(ReadFile[1], Length(ReadFile));
Finally
Free;
End;

Result := True;
End
Else
Result := False;
end;

procedure DeleteAllDir(Path, Mask: String; Recursive: Boolean);
var
Result: Integer;
SearchRec: TSearchRec;
begin
If Path[Length(Path)] <> '\' Then
Path := Concat(Path, '\');

Try
Result := FindFirst(Path + Mask, faAnyFile - faDirectory, SearchRec);
While Result = 0 Do Begin
If Not DeleteFile(Path + SearchRec.Name) Then Begin
FileSetAttr(Path + SearchRec.Name, 0); { reset all flags }
DeleteFile(Path + SearchRec.Name);
End;
Result := FindNext(SearchRec);
End;
FindClose(SearchRec);

If Not Recursive Then Exit;

Result := FindFirst(Path + '*.*', faDirectory, SearchRec);
While Result = 0 Do Begin
If (SearchRec.Name <> '.') And (SearchRec.Name <> '..') Then Begin
FileSetAttr(Path + SearchRec.Name, faDirectory);
DeleteAllDir(Path + SearchRec.Name + '\', Mask, True);
RmDir(Path + SearchRec.Name);
End;
Result := FindNext(SearchRec);
End;
FindClose(SearchRec);
Except
MessageDlg('The directory could not be deleted.', mtError, [mbOk], 0);
End;
end;

procedure TfrmLiveUpdate.FormPaint(Sender: TObject);
const
Red1 : Byte = 146;
Red2 : Byte = 186;
Green1 : Byte = 157;
Green2 : Byte = 197;
Blue1 : Byte = 210;
Blue2 : Byte = 250;
var
HalfHeight: Integer;
Row: Integer;
begin
HalfHeight := ClientHeight Div 2;

For Row := 0 To HalfHeight Do
With Canvas Do Begin
Brush.Color := RGB(
Red1 + Round((Red2 - Red1) / HalfHeight * Row),
Green1 + Round((Green2 - Green1) / HalfHeight * Row),
Blue1 + Round((Blue2 - Blue1) / HalfHeight * Row));
FillRect(Rect(0, Row, ClientWidth, Row + 1));
End;

For Row := HalfHeight + 1 To ClientHeight Do
With Canvas Do Begin
Brush.Color := RGB(
Red2 - Round((Red2 - Red1) / HalfHeight * (Row - HalfHeight)),
Green2 - Round((Green2 - Green1) / HalfHeight * (Row - HalfHeight)),
Blue2 - Round((Blue2 - Blue1) / HalfHeight * (Row - HalfHeight)));
FillRect(Rect(0, Row, ClientWidth, Row + 1));
End;
end;

procedure TfrmLiveUpdate.FormCreate(Sender: TObject);
begin
NumStep := 1;
end;

procedure TfrmLiveUpdate.CheckForUpdates;
var
FromFile: String;
InternetVer: String[5];

NumLine: Byte;
HistoryFile: TStringList;
label EndOfProc;
begin
lblToDo.Caption := '';
FromFile := CurVer[1] + CurVer[3] + CurVer[4];
FromFile := 'http://www.myprog.com/Updates/' + FromFile + '/Version.txt';
IndexFileName := ExtractFilePath(Application.ExeName) + '~UpdInfo.txt';
Application.ProcessMessages;
Try
lblStatus.Caption := 'Checking for updates...';
Application.ProcessMessages;
If Not DownloadFile(FromFile, IndexFileName) Then Begin
MessageDlg('Live-update couldn''t retrieve the catalog file of available updates. Please check that your connection to the Internet in functioning correctly and retry.', mtError, [mbOk], 0);
GoTo EndOfProc;
End;

TheFile := TStringList.Create;
TheFile.LoadFromFile(IndexFileName);

InternetVer := TheFile[NewVersionLine];
If Length(CurVer) < 4 Then
CurVer := CurVer + '0';
If Length(InternetVer) < 4 Then
InternetVer := InternetVer + '0';

lblStatus.Caption := '';
If InternetVer > CurVer Then
Begin
Inc(NumStep);
lblStatus.Caption := 'Downloading history...';
lblToDo.Caption := 'A new version (' + InternetVer + ') is available.' + #10 +
'The size of the patch is: ' + FormatFloat('#,##0', StrToInt(TheFile[
FileSizeLine]) / 1024) + ' KB.' + #10#10 + 'Click "Next" to download.';

bvlBevel2.Visible := True;
FromFile := ChangeFileExt(FromFile, '.his');
If DownloadFile(FromFile, ChangeFileExt(IndexFileName, '.his')) Then Begin
HistoryFile := TStringList.Create;
HistoryFile.LoadFromFile(ChangeFileExt(IndexFileNa me, '.his'));
For NumLine := 0 To HistoryFile.Count - 1 Do
lblWhatsNew.Caption := lblWhatsNew.Caption + HistoryFile[NumLine] + #10;
HistoryFile.Free;
End;
End
Else
Begin
If InternetVer = CurVer Then
MessageDlg('You have the most recent version of MyProg.', mtInformation, [mbOk], 0)
Else
MessageDlg('Your version is newer than on the Internet.', mtInformation, [mbOk], 0);
End;

EndOfProc:
lblStatus.Caption := '';
Except
MessageDlg('Sorry, I am unable to check for a new version. Make sure you are connected to the Internet.', mtError, [mbOk], 0);
lblStatus.Caption := '';
End;
end;

procedure TfrmLiveUpdate.DownloadUpdate;
label EndOfProc;
begin
Try
lblToDo.Caption := '';
lblWhatsNew.Caption := '';
lblStatus.Caption := 'Downloading...';

PatchFileName := TheFile[FileNameLine];
While Pos('/', PatchFileName) > 0 Do
Delete(PatchFileName, 1, Pos('/', PatchFileName));
Application.ProcessMessages;

gauDownload.Visible := True;
If Not DownloadFile(TheFile[FileNameLine], ExtractFilePath(Application.ExeName) + PatchFileName, Nil, gauDownload) Then
MessageDlg('Live-update couldn''t downlaod the patch. Please check that your connection to the Internet in functioning correctly and retry.', mtError, [mbOk], 0)
Else
Begin
lblToDo.Caption := 'The patch was downloaded successfully.';
InstallUpdate;
Inc(NumStep);
End;
gauDownload.Visible := False;

EndOfProc:
lblStatus.Caption := '';
Except
MessageDlg('Live-update couldn''t retrieve the catalog file of available updates. Please check that your connection to the Internet in functioning correctly and retry.', mtError, [mbOk], 0);
End;
end;

procedure TfrmLiveUpdate.InstallUpdate;
begin
If MessageDlg('The patch was downloaded successfully to "' + ExtractFileDir(Application.ExeName) + '". Would you like to run it now?', mtConfirmation, [mbYes, mbNo], 0) = mrYes Then Begin
Hide;
RunAndWait(ExtractFilePath(Application.ExeName) + PatchFileName, True);
If MessageDlg('Would you like to delete the patch (' + ExtractFilePath(Application.ExeName) + PatchFileName + ')?', mtConfirmation, [mbYes, mbNo], 0) = mrYes Then
DeleteFile(ExtractFilePath(Application.ExeName) + PatchFileName);
Show;
End;
btnNext.Visible := False;
btnCancel.Caption := 'Close';
end;

procedure TfrmLiveUpdate.btnNextClick(Sender: TObject);
begin
btnNext.Enabled := False;
btnCancel.Enabled := False;
Screen.Cursor := crHourGlass;

Case NumStep Of
1: CheckForUpdates;
2: DownloadUpdate;
End;

Screen.Cursor := crDefault;
btnCancel.Enabled := True;

If btnNext.Visible Then
Begin
btnNext.Enabled := True;
btnNext.SetFocus;
End
Else
Begin
btnCancel.Enabled := True;
btnCancel.SetFocus;
End;
end;

procedure TfrmLiveUpdate.btnCancelClick(Sender: TObject);
begin
Close;
end;

procedure TfrmLiveUpdate.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
If btnNext.Visible Then
CanClose := MessageDlg('Are you sure you want to cancel Live-Update?', mtConfirmation, [mbYes, mbNo], 0) = mrYes
Else
CanClose := True;
end;

procedure TfrmLiveUpdate.FormClose(Sender: TObject;
var Action: TCloseAction);
begin
DeleteAllDir(ExtractFileDir(Application.ExeName), '~*.*', False);
Try TheFile.Free; Except End;
end;

end.

------

วันศุกร์ที่ 3 มิถุนายน พ.ศ. 2554

stack overflow มันคืออะไร

stack overflow มักจะเกิดจากการทำ recursion มากเกินไป
เช่นการเรียกฟังก์ชันเดิมวนซ้ำไม่สิ้นสุด หรือการใช้วงเล็บมากกว่าขีดจำกัดของภาษา
ทำให้ stack ที่รอการคืนค่าจากฟังก์ชันเกิดเต็มขึ้นมา

at line 0 ก็คือบรรทัดที่ 0 (บรรทัดแรก)