<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>jQueryTips by Tee++; &#187; performance</title>
	<atom:link href="http://www.jquerytips.com/tag/performance/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.jquerytips.com</link>
	<description>Coding is fun.</description>
	<lastBuildDate>Sun, 25 Apr 2010 11:30:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Hasing algorithm</title>
		<link>http://www.jquerytips.com/2009/06/03/hasing-algorithm/</link>
		<comments>http://www.jquerytips.com/2009/06/03/hasing-algorithm/#comments</comments>
		<pubDate>Wed, 03 Jun 2009 16:09:12 +0000</pubDate>
		<dc:creator>Tee++;</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.jquerytips.com/?p=481</guid>
		<description><![CDATA[วันนี้ขอพูดเรื่อง performance อีกสักที สำหรับคนที่เคยจับ application ที่ใหญ่ๆ หน่อย ที่มีจำนวน file upload มหาศาล หรือ เอาง่ายๆ แค่หลัก 2-3 หมื่นขึ้นไป ก็จะเห็นได้ว่า หลังจากนั้น application จะทำงาน ค่อยๆ ช้าลงๆๆๆ จนในที่สุด ก็ทะลุ node ที่เป็น limit ของ UNIX ไป (จำไม่ได้ 5 หรือ 6 หมื่นนี่ล่ะ)
วิธีแก้ที่ดีที่สุดก็คือการ ซอย folder ออกเป็น ย่อยๆ เพื่อไม่ให้ไฟล์ ไปรวมกันอยู่ที่เดียว เช่น



parent &#8211;


&#160; &#160; &#160; &#160; &#160; &#160; &#124;- child1


&#160; &#160; &#160; &#160; &#160; &#160; [...]]]></description>
			<content:encoded><![CDATA[<p>วันนี้ขอพูดเรื่อง performance อีกสักที สำหรับคนที่เคยจับ application ที่ใหญ่ๆ หน่อย ที่มีจำนวน file upload มหาศาล หรือ เอาง่ายๆ แค่หลัก 2-3 หมื่นขึ้นไป ก็จะเห็นได้ว่า หลังจากนั้น application จะทำงาน ค่อยๆ ช้าลงๆๆๆ จนในที่สุด ก็ทะลุ node ที่เป็น limit ของ UNIX ไป (จำไม่ได้ 5 หรือ 6 หมื่นนี่ล่ะ)</p>
<p>วิธีแก้ที่ดีที่สุดก็คือการ ซอย folder ออกเป็น ย่อยๆ เพื่อไม่ให้ไฟล์ ไปรวมกันอยู่ที่เดียว เช่น</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">parent &#8211;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |- child1</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; |- child2</div>
</li>
</ol>
</div>
<p>แบบนี้ไฟล์ก็จะไม่รวมอยู่ที่เดียวกัน แต่ จะมีปัญหาตามมาว่า แล้วเราจะ บริหารจัดการยังไง T_T</p>
<p>ตรงนี้แหละที่ ต้องมี hashing algorithm แบบต่างๆ ขึ้นมา ผมจะลอง ไล่ไปดูทีละแบบละกัน<span id="more-481"></span></p>
<p><strong>แบบที่นึง hash ตัวเลข</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> int_hash<span class="br0">&#40;</span><span class="re0">$no</span>, <span class="re0">$max</span>=<span class="nu0">5000</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<a href="http://www.php.net/is_numeric"><span class="kw3">is_numeric</span></a><span class="br0">&#40;</span><span class="re0">$no</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <a href="http://www.php.net/die"><span class="kw3">die</span></a><span class="br0">&#40;</span><span class="st0">&#8216;Value must be numeric&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$p0</span> = <a href="http://www.php.net/ceil"><span class="kw3">ceil</span></a><span class="br0">&#40;</span><span class="re0">$no</span> / <span class="br0">&#40;</span><span class="re0">$max</span> * <span class="re0">$max</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$p1</span> = <a href="http://www.php.net/ceil"><span class="kw3">ceil</span></a><span class="br0">&#40;</span><span class="re0">$no</span> % <span class="re0">$max</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$p0</span>.<span class="st0">&#8216;/&#8217;</span>.<a href="http://www.php.net/sprintf"><span class="kw3">sprintf</span></a><span class="br0">&#40;</span><span class="st0">&#8216;%0&#8242;</span>.<a href="http://www.php.net/strlen"><span class="kw3">strlen</span></a><span class="br0">&#40;</span><span class="re0">$max</span><span class="br0">&#41;</span>.<span class="st0">&#8216;d&#8217;</span>, <span class="re0">$p1</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>แบบนี้จะเป็นการ hash 2 level ง่ายๆ แต่ว่า ได้ผลดีทีเดียว โดยที่ ชั้นแรกจะ hash ได้สูงสุดถึง 25 ล้าน ก่อนที่จะสร้าง folder ใหม่ นั่นก็คือ ค่าตั้งแต่ </p>
<p>1 &#8211; 25000000 จะถูกเก็บเข้า Folder 1 ถ้ามากกว่า จะถูกสร้าง Folder 2 ขึ้นมา ส่วนในชั้นที่ 2 จะถูกสร้าง folder มาสูงสุดตามที่เรากำหนดค่า max ลงไป โดยในที่นี้ก็จะมี 0001 &#8211; 5000</p>
<p>จากนั้น data ที่ลงท้ายด้วย 1 ก็จะจัดเก็บเข้า folder 1 และ เป็นอย่างนี้เรื่อยไป </p>
<p>วิธีนี้เหมาะกับการ hash ค่าอะไรก็ตามที่เป็นตัวเลข เช่น auto increment หารทำงานจะค่อนข้างดีทีเดียว เพราะ data จะค่อยๆ หยอดไปทีละ 1 และมีขนาดพอๆ กันเกือบทุก folder แต่ว่า มัน hash ได้เฉพาะ ตัวเลข ลองมาดูวิธีต่อมากัน</p>
<p><strong>แบบที่ 2 hash โดยใช้ crc32</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> crc32_hash<span class="br0">&#40;</span><span class="re0">$key</span>, <span class="re0">$max</span>=<span class="nu0">5000</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><a href="http://www.php.net/crc32"><span class="kw3">crc32</span></a><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span> &amp; 0&#215;7fffffff<span class="br0">&#41;</span> % <span class="re0">$max</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>วิธี hash แบบนี้สาารถนำไป hash string ได้ด้วย โดยอาศัย ความสามารถของ CRC32 ซึ่งเป็น algorithm hash ในรูปแบบ 32-bit checksum โดยค่าที่เหมือนกัน จะได้ค่าเดียวกันเสมอ จากนั้น เอามาเข้า สมการเพื่อให้ได้ folder ไม่เกินตามที่เรากำหนด เราก็จะได้ สูตรง่ายๆ มาแล้ว อันนี้เอาไว้ hash แบบชั้นเดียวง่ายๆ แต่ใครอยากไป เพิ่ม level ก็เขียนต่อเอาครับ </p>
<p>แล้วก็วิธีสุดท้ายที่ผมจะแนะนำ โดยอันนี้ผมแกะออกมาก จาก Zend Cache ในส่วนของการ hash level </p>
<p><strong>โดยคราวนี้เราจะใช้ algorithm adler32 </strong></p>
<p>หลักการก็โครตจะแสนง่าย แต่ว่า ปะสิทธิภาพค่อนข้างจะดี </p>
<p>สมมุติผมมี string คำว่า &#8221; I wanna be a star. &#8221;</p>
<p>พอทำการ hash</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">hash<span class="br0">&#40;</span><span class="st0">&#8216;adler32&#8242;</span>, <span class="st0">&#8216;I wanna be a star.&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// ค่าที่ได้คือ ef050538</span></div>
</li>
</ol>
</div>
<p>จากนั้นผมก็มาคำนวน level โดยถ้า 1 level ผมก็จะทำการ ตัด string ที่ตำแหน่งแรกออกมาสร้าง dir ย่อย ก็จะได้ผลลัพธ์ ออกมาดังนี้</p>
<p>path: e/ef050538.hash</p>
<p>ถ้า 2 level ล่ะ </p>
<p>path: e/ef/ef050538.hash</p>
<p>และก็เป็นแบบนี้ไล่ๆ ไป ตามแต่ ที่เรากำหนด level</p>
<p>สำหรับวิธีนี้ node structure เราก็จะออกมาในรูปแบบ &#8220;สามเหลี่ยม&#8221; โดยยิ่งมี level มาก มันก็จะยิ่งซอยเยอะมาก แต่ว่า ถ้าเยอะมากไป มันก็เท่ากับว่า เราไม่ได้ hash อะไรเลย ดังนั้น สำหรับ application ระดับ กลาง &#8211; ใหญ่ ผมขอแนะนำที่ 2 level ก็พอครับ </p>
<p>สุดท้าย ผมเอา algorithm แบบที่ 3 มาเขียน ในรูปแบบ class เรียบร้อยแล้ว จะเอาไปใช้เลยก็ได้นะครับ โดยตัวอย่างที่ผมเอาไปใส่ไว้ ด้านล่างไฟล์ เป็นการทำ hash เพื่อ save text ธรรมดา ผมว่าเอาไป ประยุกต์ใช้งานกับระบบ cache หรือ file upload จะเห็นผลมากกว่า </p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/**</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* Hashin library</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;* @Author Tee++;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">&nbsp;* @Published 03/06/2009</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">&nbsp;*/</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">class</span> Hashing <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$parent_dir</span> = <span class="st0">&#8216;temp&#8217;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$prefix</span> = <span class="st0">&quot;prefix_&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$level</span> = <span class="nu0">2</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$algorithm</span> = <span class="st0">&#8216;adler32&#8242;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$make_dir</span> = <span class="kw2">TRUE</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co1">// file tailer</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$show_file</span> = <span class="kw2">TRUE</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$extension</span> = <span class="st0">&#8216;hash&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> do_hash<span class="br0">&#40;</span><span class="re0">$string</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$hashing</span> = <span class="re0">$this</span>-&gt;<span class="me1">hash_algorithm</span><span class="br0">&#40;</span><span class="re0">$string</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$path</span> = <span class="re0">$this</span>-&gt;<span class="me1">parent_dir</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$hash_dirs</span> = <span class="re0">$this</span>-&gt;_path<span class="br0">&#40;</span><span class="re0">$hashing</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$path</span> .= <span class="st0">&#8216;/&#8217;</span>.<span class="re0">$hash_dirs</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">make_dir</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_makePathRecursive<span class="br0">&#40;</span><span class="re0">$path</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">show_file</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$path</span> .= <span class="st0">&#8216;/&#8217;</span>.<span class="re0">$hashing</span>.<span class="st0">&#8216;.&#8217;</span>.<span class="re0">$this</span>-&gt;<span class="me1">extension</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$path</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> hash_algorithm<span class="br0">&#40;</span><span class="re0">$string</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> hash<span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">algorithm</span>, <span class="re0">$string</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> _path<span class="br0">&#40;</span><span class="re0">$string</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">level</span> &lt;= <span class="nu0">0</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$directories</span> = <a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">for</span> <span class="br0">&#40;</span><span class="re0">$i</span>=<span class="nu0">1</span>; <span class="re0">$i</span>&lt;=<span class="re0">$this</span>-&gt;<span class="me1">level</span>; <span class="re0">$i</span>++<span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/array_push"><span class="kw3">array_push</span></a><span class="br0">&#40;</span><span class="re0">$directories</span>, <span class="re0">$this</span>-&gt;<span class="me1">prefix</span>.<a href="http://www.php.net/substr"><span class="kw3">substr</span></a><span class="br0">&#40;</span><span class="re0">$string</span>, <span class="nu0">0</span>, <span class="re0">$i</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <a href="http://www.php.net/implode"><span class="kw3">implode</span></a><span class="br0">&#40;</span><span class="st0">&#8216;/&#8217;</span>, <span class="re0">$directories</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> _makePathRecursive<span class="br0">&#40;</span><span class="re0">$dir</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<a href="http://www.php.net/is_dir"><span class="kw3">is_dir</span></a><span class="br0">&#40;</span><span class="re0">$dir</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/mkdir"><span class="kw3">mkdir</span></a><span class="br0">&#40;</span><span class="re0">$dir</span>, <span class="nu0">0777</span>, <span class="kw2">TRUE</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">TRUE</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/* </span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">##### Example Usage #####</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">$string = &quot;IWannaBeARockStar&quot;;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">$hashing = new Hashing;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">$path = $hashing-&gt;do_hash($string);</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">file_put_contents($path, $string);</span></div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">*/</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">?&gt;</span></div>
</li>
</ol>
</div>
]]></content:encoded>
			<wfw:commentRss>http://www.jquerytips.com/2009/06/03/hasing-algorithm/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>MySQL::Merge Storage Engine</title>
		<link>http://www.jquerytips.com/2009/05/27/mysqlmerge-storage-engine/</link>
		<comments>http://www.jquerytips.com/2009/05/27/mysqlmerge-storage-engine/#comments</comments>
		<pubDate>Wed, 27 May 2009 14:28:08 +0000</pubDate>
		<dc:creator>Tee++;</dc:creator>
				<category><![CDATA[Others]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.jquerytips.com/?p=464</guid>
		<description><![CDATA[พักนี้เริ่มมั่วไปใหญ่ละ ตอนที่เปิดเว็บ มาตั้งใจว่าจะเขียนแต่เรื่อง jQuery กับ Javascript แต่พักนี้ไหง มีทุกเรื่องเลยก็ไม่รู้ กลายเป็น บล๊อกโปรแกรมมิ่ง ไปไม่รู้ตัว แต่ขออีกทีน่า คนมันอยากเขียนนี่หว่า เดี๋ยวครั้งหน้ากลับมา เขียนเรื่อง jQuery ต่อ
วันนี้ที่จะมาเขียนก็ฉีกแนวไปจากเดิมอีกละ จะมาพูดถึงเรื่อง Storage Engine ตัวนึงที่มี ใน MySQL 5.0 ขึ้นไป นั่นก็คือ merge storage engine (MRG_MyIsam) นั่นเอง เป็นการทำให้ table หลายๆ ตัว ถูก มองเห็นเป็นตัวเดียวกัน 
ก่อนอื่นผมสร้าง DB ขึ้นมาทำการทดสอบชื่อว่า merge_test
จากนั้นผมสร้่าง table ขึ้นมา 2 ตัว ชื่อว่า table_a, table_b



CREATE TABLE `merge_test`.`table_a` &#40;


`id` INT&#40; 10 &#41; NOT [...]]]></description>
			<content:encoded><![CDATA[<p>พักนี้เริ่มมั่วไปใหญ่ละ ตอนที่เปิดเว็บ มาตั้งใจว่าจะเขียนแต่เรื่อง jQuery กับ Javascript แต่พักนี้ไหง มีทุกเรื่องเลยก็ไม่รู้ กลายเป็น บล๊อกโปรแกรมมิ่ง ไปไม่รู้ตัว แต่ขออีกทีน่า คนมันอยากเขียนนี่หว่า เดี๋ยวครั้งหน้ากลับมา เขียนเรื่อง jQuery ต่อ</p>
<p>วันนี้ที่จะมาเขียนก็ฉีกแนวไปจากเดิมอีกละ จะมาพูดถึงเรื่อง Storage Engine ตัวนึงที่มี ใน MySQL 5.0 ขึ้นไป นั่นก็คือ <strong>merge storage engine</strong> (MRG_MyIsam) นั่นเอง เป็นการทำให้ table หลายๆ ตัว ถูก มองเห็นเป็นตัวเดียวกัน </p>
<p>ก่อนอื่นผมสร้าง DB ขึ้นมาทำการทดสอบชื่อว่า <strong>merge_test</strong></p>
<p>จากนั้นผมสร้่าง table ขึ้นมา 2 ตัว ชื่อว่า table_a, table_b<span id="more-464"></span></p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">CREATE TABLE `merge_test`.`table_a` <span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">`id` INT<span class="br0">&#40;</span> <span class="nu0">10</span> <span class="br0">&#41;</span> NOT <span class="kw2">NULL</span> AUTO_INCREMENT ,</div>
</li>
<li class="li1">
<div class="de1">`data` VARCHAR<span class="br0">&#40;</span> <span class="nu0">25</span> <span class="br0">&#41;</span> NOT <span class="kw2">NULL</span> ,</div>
</li>
<li class="li1">
<div class="de1">PRIMARY <a href="http://www.php.net/key"><span class="kw3">KEY</span></a> <span class="br0">&#40;</span> `id` <span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#41;</span> ENGINE = MYISAM ;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">CREATE TABLE `merge_test`.`table_b` <span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">`id` INT<span class="br0">&#40;</span> <span class="nu0">10</span> <span class="br0">&#41;</span> NOT <span class="kw2">NULL</span> AUTO_INCREMENT ,</div>
</li>
<li class="li1">
<div class="de1">`data` VARCHAR<span class="br0">&#40;</span> <span class="nu0">25</span> <span class="br0">&#41;</span> NOT <span class="kw2">NULL</span> ,</div>
</li>
<li class="li2">
<div class="de2">PRIMARY <a href="http://www.php.net/key"><span class="kw3">KEY</span></a> <span class="br0">&#40;</span> `id` <span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#41;</span> ENGINE = MYISAM ;</div>
</li>
</ol>
</div>
<p><strong>Engine ต้องเป็น MyIsam เท่านั้นนะครับ</strong></p>
<p>จากนั้นผม ก็ทำการ ทดสอบ insert ข้อมูล ลงไปใน table_a ก่อน ดังนี้</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">INSERT INTO `merge_test`.`table_a` <span class="br0">&#40;</span>`id`, `data`<span class="br0">&#41;</span> VALUES <span class="br0">&#40;</span><span class="kw2">NULL</span>, <span class="st0">&#8216;data for table a&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>แล้วต่อมาอีก ผมก็สร้าง merage table มามีชื่อว่า table_all</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">CREATE TABLE `table_all` <span class="br0">&#40;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; `id` int<span class="br0">&#40;</span><span class="nu0">10</span><span class="br0">&#41;</span> NOT <span class="kw2">NULL</span> AUTO_INCREMENT,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; `data` varchar<span class="br0">&#40;</span><span class="nu0">25</span><span class="br0">&#41;</span> NOT <span class="kw2">NULL</span>,</div>
</li>
<li class="li1">
<div class="de1">&nbsp; PRIMARY <a href="http://www.php.net/key"><span class="kw3">KEY</span></a> <span class="br0">&#40;</span>`id`<span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#41;</span> ENGINE=MERGE UNION=<span class="br0">&#40;</span>table_a,table_b<span class="br0">&#41;</span> INSERT_METHOD=LAST</div>
</li>
</ol>
</div>
<p>โดยต้องมี Structure เหมือนกับ 2 table ด้านบนไม่ผิดเพี้ยน จากนั้นกำำหนด Engine เป็น merge ซะ และใช้คำสั่ง Union ในการเลืกว่าจพ เชื่อม table ไหน จากนั้น กำหนด ให้ data insert อยู่ที่ last table นั่นก็คือ table_b นั่นเอง</p>
<p>จากนั้นมาลอง insert ข้อมูลลง table_all</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1">INSERT INTO `merge_test`.`table_all` <span class="br0">&#40;</span>`id`, `data`<span class="br0">&#41;</span> VALUES <span class="br0">&#40;</span><span class="kw2">NULL</span>, <span class="st0">&#8216;555 test&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
</ol>
</div>
<p>จะเห็นได้ว่า table_all จะเอา data ของ ทั้ง 2 table มาอยู่ในตัวเอง ดังภาพด้านล่าง</p>
<p><strong>table_a</strong><br />
<a href="http://www.jquerytips.com/wp-content/uploads/2009/05/table_a.jpg"><img src="http://www.jquerytips.com/wp-content/uploads/2009/05/table_a.jpg" alt="table_a" title="table_a" width="272" height="71" class="alignnone size-full wp-image-465" /></a></p>
<p><strong>table_b</strong><br />
<a href="http://www.jquerytips.com/wp-content/uploads/2009/05/table_b.jpg"><img src="http://www.jquerytips.com/wp-content/uploads/2009/05/table_b.jpg" alt="table_b" title="table_b" width="223" height="75" class="alignnone size-full wp-image-467" /></a></p>
<p><strong>table_all</strong><br />
<a href="http://www.jquerytips.com/wp-content/uploads/2009/05/table_all.jpg"><img src="http://www.jquerytips.com/wp-content/uploads/2009/05/table_all.jpg" alt="table_all" title="table_all" width="297" height="96" class="alignnone size-full wp-image-466" /></a></p>
<p>จากภาพเราก็จะเห็นได้ว่า data ที่เรา insert table_all จะไป ตกอยู่ที่ table_b ด้วย โดยที่ auto increment ไม่ผิดเพี้ยนไป </p>
<p>ก็คือ table_all จะเป็นตัว map data เท่านั้น โดยที่ ไม่ได้ทำหน้าที่เป็นตัวจัดเก็บจริงๆ<br />
*** ถ้ามี data เยอะๆ ไปลองสังเกตุไฟล์ table_all.frm ได้ว่า ไม่มีขนาดเพิ่มขึ้นตามจำนวน data ***</p>
<p>ทีนี้ เราก็จะสามารถบริหาร select, insert, delete, update โดยใช้ table_all เท่านั้น โดยไม่ต้องไปสนใจว่า data จะอยู่ที่ table_a หรือ table_b</p>
<p>วิธีนี้ไม่เหมือนกับการทำ Partition นะครับ เพราะว่า Data ไม่สามารถกำหนดในลักษณะั hasing ได้ ต้องเลือกเอาเลย ว่าจะ insert ลง table ไป &#8220;Last or First&#8221;</p>
<blockquote><p>เท่าที่ลองหาข้อมูลมา วิธีนี้ไม่ได้ช่วยเรื่อง performance เท่าไหร่ แต่ว่า เป็นการ merge table เพื่อนำมาวิเคราะห์ข้อมูลมากกว่า แตกต่างจาก partition อย่าสับสนกันนะครับ</p></blockquote>
<p>เอาล่ะ จบ เรื่อง MySQL เดี๋ยวครั้งแน่ jQuery แน่ๆ 555+</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jquerytips.com/2009/05/27/mysqlmerge-storage-engine/feed/</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>[CI Day 9] Query Caching Modify</title>
		<link>http://www.jquerytips.com/2009/01/23/ci-cache/</link>
		<comments>http://www.jquerytips.com/2009/01/23/ci-cache/#comments</comments>
		<pubDate>Fri, 23 Jan 2009 08:36:05 +0000</pubDate>
		<dc:creator>Tee++;</dc:creator>
				<category><![CDATA[Codeigniter]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.jquerytips.com/?p=240</guid>
		<description><![CDATA[สวัสดีมาต่อเรื่อง CI กันแล้วครับ ตอนนี้ผมตัดสินใจละ ว่าจะเขียนถึง Day 10 เท่านั้นแล้วก็จะกลับเข้ามาสู่ ภาคของ jQuery ต่อ เพราะว่าตั้งแต่ jQuery ออก V.1.3 ผมก็ไม่ได้อัพเดท อะไรเลย ทั้งๆ ที่มีของเล่นใหม่ๆ เพิ่มมาพอสมควร และที่สำคัญ ผมขี้เกียจเขียนเรื่อง CI ละ มันต้องอธิบาย กันลึกเกิน ไปซึ่งผม ก็เขียนอธิบาย ไม่ค่อยเก่งเสียด้วย แต่ถ้ามีอะไรก็ถามกันเข้ามาได้ครับ 
เออ ช่วงนี้เห็นหลายคนขอ M ผมเข้ามาเยอะเหลือเกิน ยังไงผมก็จะให้ไว้ในกระทู้นี้ละกัน d n a b o a r d @ g m a i l . c o m ยังไงแวะเวียนมาแลกเปลี่ยนความรู้กันได้เลย 
วันนี้เรื่องที่จะมาเล่า [...]]]></description>
			<content:encoded><![CDATA[<p>สวัสดีมาต่อเรื่อง CI กันแล้วครับ ตอนนี้ผมตัดสินใจละ ว่าจะเขียนถึง Day 10 เท่านั้นแล้วก็จะกลับเข้ามาสู่ ภาคของ jQuery ต่อ เพราะว่าตั้งแต่ jQuery ออก V.1.3 ผมก็ไม่ได้อัพเดท อะไรเลย ทั้งๆ ที่มีของเล่นใหม่ๆ เพิ่มมาพอสมควร และที่สำคัญ ผมขี้เกียจเขียนเรื่อง CI ละ มันต้องอธิบาย กันลึกเกิน ไปซึ่งผม ก็เขียนอธิบาย ไม่ค่อยเก่งเสียด้วย แต่ถ้ามีอะไรก็ถามกันเข้ามาได้ครับ </p>
<p>เออ ช่วงนี้เห็นหลายคนขอ M ผมเข้ามาเยอะเหลือเกิน ยังไงผมก็จะให้ไว้ในกระทู้นี้ละกัน d n a b o a r d @ g m a i l . c o m ยังไงแวะเวียนมาแลกเปลี่ยนความรู้กันได้เลย </p>
<p>วันนี้เรื่องที่จะมาเล่า คือเรื่องการทำ Caching ของ CI ครับ แน่นอนครับ ทำเวบสมัยนี้ มันไม่เหมือนเมื่อก่อนแล้ว มันมีเทคนิคที่ พัฒนาไปมาก ในการทำเวบ เรื่องที่ผมใส่ใจมากเป็นพิเศษ นอกเหนือจาก Structure แล้วก็คือ Performance นี่ล่ะครับ และสิ่งที่ Developer ทำกันมากที่สุด ในการ Tuning Performance นั่นก็คือ การทำ Caching ครับ ผมยกตัวอย่างเช่น <a href="http://www.facebook.com/">Facebook.com</a> <span id="more-240"></span></p>
<p>รู้มั้ยครับ facebook เองเขียนด้วย PHP ส่วน DB ก็ยังใช้ MySQL นี่ล่ะ แต่ทำไม มันถึงรองรับ คนได้มากเหลือเกิน ซึ่งจะว่ากันไปจริงๆ แล้วมันมีหลายเรื่องทั้ง Load Balance, Reverse Proxy แล้วก็ องค์ประกอบของ Hardware แต่เรื่องที่ น่าสนใจคือ FB มีการ Access DB น้อยมาก ซึ่งเราเองรู้กันดีอยู่แล้วว่า MySQL เนี่ย มันไม่ค่อยจะดีนัก ต่อเวบที่มี คนเยอะๆ มันอ่อนแอเหลือเกิน </p>
<p>ดังนั้นแทนที่ FB จะทำการ Access เข้า DB ตรงๆ อยู่ตลอดเวลา ก็เปลี่ยนมาออกแบบให้ Access ป่าน <a href="http://www.danga.com/memcached/">Memcached</a> ซึ่งเป็นการ Cached ใน Fast Memory (**Data จะหายเมื่อมีการ Reboot**) ด้วยวิธีนี้จะทำให้การ Access DB ลดน้อยลง จนเราแปลกใจ และเป็นสาเหตุหลักที่ทำให้เวบมี Down Time ต่ำมากๆ </p>
<p><em>อ้างอิง:</em> <a href="http://www.webmonkey.com/blog/Facebook_Presents_Scalability_Secret:_Memcached">Facebook Scalability</a></p>
<p>แต่ด้วยข้อจำกัดของ Server ที่เพื่อนๆ ใช้มันทำให้การที่ผมจะไปพูดถึง Cached ระดับ Memory เช่น APC, Memcached นั้น ดูจะแคบไปหน่อย ผมก็เลยขอเลี่ยงไปพูดถึง Cache ในระดับ Flat File แทน ซึ่งน่าจะทำกันได้ในทุกๆ Server อยู่แล้ว</p>
<p>(ผมไม่ขอพูดถึง Caching ทีมีใน CI นะครับ เพราะว่าผมไม่ปลื้มเท่าไหร่ ถ้าสนใจก็อ่านใน manual น่าจะเข้าใจได้ไม่ยาก)</p>
<p>เอาล่ะไม่รู้จะเกริ่นยาวไปถึงไหน มาเริ่มกันเลยดีกว่าครับ&#8230;.</p>
<p>ในการออกแบบ Structure ของวันนี้เราจะพูดถึงเรื่องหลักๆ 2 เรื่องคือ<br />
1. การออกแบบ Folder Structure (Node)<br />
2. การออกแบบ Cache แบบ GZIP</p>
<p><strong>เรื่องแรกก่อน (วันนี้สงสัยไม่จบง่ายๆ -*-)</strong></p>
<p>เพื่อนๆ รู้มั้ยครับ การจัดเก็บไฟล์ลงใน Dir แต่ละ Dir นั้นก็มีข้อจำกัดเหมือนกัน ไม่ใช่เอะอะๆ ยัดเก็บ Dir เดียว พรวดๆ ถ้าทำแบบนั้นมันจะเกิดปัญหาในท้ายที่สุดคือ Node เต็ม ซึ่งตามที่เคยรู้มามันควรจะเป็นราวๆ 60,000 ต่อ 1 ชั้นราวๆ นี้มั้ง (จริงๆ ยัดลงไปได้อีกเยอะ แต่มันจะช้าลงเรื่อยๆ จนตายไปในที่สุด) </p>
<p>ตัวอย่างการจัดเก็บที่ดีก็คือ <a href="http://www.flickr.com/">Flickr</a> ลองไปสังเกตุ Path ของรูปดูสิครับ จะเห็นได้ว่า มีการแบ่งเป็น Farm และ Sup Path ไว้อย่างดีเลยทีเดียว </p>
<p>ทีนี้ผมจะมาลอง algorithm ง่ายๆก่อน โดยจะใช้แค่ Dir ขวางเพียงชั้นเดียว โดยทำ Hashing ด้วย <a href="http://en.wikipedia.org/wiki/Cyclic_redundancy_check">CRC32</a></p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">function</span> crc32_hash<span class="br0">&#40;</span><span class="re0">$key</span>, <span class="re0">$max</span>=<span class="nu0">5000</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="kw1">return</span> <span class="br0">&#40;</span><a href="http://www.php.net/crc32"><span class="kw3">crc32</span></a><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span> &amp; 0&#215;7fffffff<span class="br0">&#41;</span> % <span class="re0">$max</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
</ol>
</div>
<p>เขียนเท่านี้ล่ะ ผมไม่ขออธิบายถึง CRC32 Algorithm นะครับ แต่ว่าเพื่อนๆ ไปหาข้อมูลเพิ่มได้จากพี่ Goo นั่นล่ะ ผมจะขอบอกแค่ว่าจาก Function ด้านบนสิ่งที่เพื่อนๆจะได้กลับมาก็คือ ข้อมูล 1 ชุดที่เป็นตัวเลข ไม่เกิน 5,000 โดยเราเอาอะไรใส่เข้าไปก็ได้ เช่น </p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><a href="http://www.php.net/echo"><span class="kw3">echo</span></a> crc32_hash<span class="br0">&#40;</span><span class="st0">&#8216;Tee++;&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="co1">// output 322</span></div>
</li>
</ol>
</div>
<p>ตัวเลขที่ออกมานั่นล่ะครับ คือส่งที่ผมจะเอาไปสร้าง node<br />
/main_dir/322/ </p>
<p>เห็นมั้ยครับเท่านี้ผมก็จะได้ Dir มาขวาง 1 ชั้นแล้ว ไม่จำเป็นต้องเอาไปเก็บที่ main_dir อย่างเดียว โดยที่ Folder ในชั้นที่ขวางนี้จะมีไม่เกิน 5,000 เพราะผมตั้งเอาไว้แค่นั้น </p>
<p>นอกจากนี้ Algorithm ของการทำ Hashing Dir ยังมีอีกมากมายครับ ลองหาเอาจากใน Net ดูกันเอา ส่วนตอนี้ผมจะเข้าเรื่องที่ผมจะเขียนก่อนล่ะ</p>
<p><strong>เรื่องที่สอง</strong></p>
<p>มาเขียน lib caching เพื่อไป plug ใน CI กัน<br />
[CI]/application/libraries/<strong>Caching.php</strong></p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span> <span class="kw1">if</span> <span class="br0">&#40;</span> ! <a href="http://www.php.net/defined"><span class="kw3">defined</span></a><span class="br0">&#40;</span><span class="st0">&#8216;BASEPATH&#8217;</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <a href="http://www.php.net/exit"><span class="kw3">exit</span></a><span class="br0">&#40;</span><span class="st0">&#8216;No direct script access allowed&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">class</span> Caching <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$CI</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$_parent</span> = <span class="st0">&#8216;cache/&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$_maxDir</span> = <span class="nu0">5000</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">var</span> <span class="re0">$_path</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> __construct<span class="br0">&#40;</span><span class="br0">&#41;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">CI</span> =&amp; get_instance<span class="br0">&#40;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;<span class="me1">CI</span>-&gt;<span class="me1">load</span>-&gt;<span class="me1">helper</span><span class="br0">&#40;</span><span class="st0">&#8216;node&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> setParent<span class="br0">&#40;</span><span class="re0">$parent</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/substr"><span class="kw3">substr</span></a><span class="br0">&#40;</span><span class="re0">$parent</span>, <span class="nu0">-1</span><span class="br0">&#41;</span> != <span class="st0">&quot;/&quot;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$parent</span> = <span class="re0">$parent</span>.<span class="st0">&#8216;/&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_parent = <span class="re0">$parent</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> setMaxDir<span class="br0">&#40;</span><span class="re0">$max</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_maxDir = <span class="re0">$max</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> setDir<span class="br0">&#40;</span><span class="re0">$subDir</span>, <span class="re0">$str</span>=<span class="kw2">null</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/is_null"><span class="kw3">is_null</span></a><span class="br0">&#40;</span><span class="re0">$str</span><span class="br0">&#41;</span> || <a href="http://www.php.net/empty"><span class="kw3">empty</span></a><span class="br0">&#40;</span><span class="re0">$str</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$hash</span> = <span class="st0">&#8217;server_&#8217;</span>.crc32_hash<span class="br0">&#40;</span><span class="re0">$str</span>, <span class="re0">$this</span>-&gt;_maxDir<span class="br0">&#41;</span>.<span class="st0">&#8216;/&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$this</span>-&gt;_path = APPPATH.<span class="re0">$this</span>-&gt;_parent.<span class="re0">$subDir</span>.<span class="st0">&#8216;/&#8217;</span>.<span class="re0">$hash</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="co2">#### end if use key as string #####</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> store<span class="br0">&#40;</span><span class="re0">$key</span>, <span class="re0">$data</span>, <span class="re0">$ttl</span>=<span class="nu0">86400</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$key</span> || !<span class="re0">$data</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; mkdirs<span class="br0">&#40;</span><a href="http://www.php.net/dirname"><span class="kw3">dirname</span></a><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">getFileName</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$h</span> = @<a href="http://www.php.net/gzopen"><span class="kw3">gzopen</span></a><span class="br0">&#40;</span><span class="re0">$this</span>-&gt;<span class="me1">getFileName</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span>, <span class="st0">&#8216;w&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$h</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> = <a href="http://www.php.net/serialize"><span class="kw3">serialize</span></a><span class="br0">&#40;</span><a href="http://www.php.net/array"><span class="kw3">array</span></a><span class="br0">&#40;</span><a href="http://www.php.net/time"><span class="kw3">time</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span> + <span class="re0">$ttl</span>, <span class="re0">$data</span><span class="br0">&#41;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/gzwrite"><span class="kw3">gzwrite</span></a><span class="br0">&#40;</span><span class="re0">$h</span>, <span class="re0">$data</span><span class="br0">&#41;</span> === <span class="kw2">false</span><span class="br0">&#41;</span>&nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">return</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/gzclose"><span class="kw3">gzclose</span></a><span class="br0">&#40;</span><span class="re0">$h</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> fetch<span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$key</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$filename</span> = <span class="re0">$this</span>-&gt;<span class="me1">getFileName</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<a href="http://www.php.net/file_exists"><span class="kw3">file_exists</span></a><span class="br0">&#40;</span><span class="re0">$filename</span><span class="br0">&#41;</span> || !<a href="http://www.php.net/is_writeable"><span class="kw3">is_writeable</span></a><span class="br0">&#40;</span><span class="re0">$filename</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="kw1">return</span> <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$h</span> = @<a href="http://www.php.net/gzopen"><span class="kw3">gzopen</span></a><span class="br0">&#40;</span><span class="re0">$filename</span>, <span class="st0">&#8216;r&#8217;</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$h</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">while</span> <span class="br0">&#40;</span>!<a href="http://www.php.net/gzeof"><span class="kw3">gzeof</span></a><span class="br0">&#40;</span><span class="re0">$h</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> .= <a href="http://www.php.net/gzread"><span class="kw3">gzread</span></a><span class="br0">&#40;</span><span class="re0">$h</span>, <span class="nu0">4096</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <a href="http://www.php.net/gzclose"><span class="kw3">gzclose</span></a><span class="br0">&#40;</span><span class="re0">$h</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$data</span> = <a href="http://www.php.net/unserialize"><span class="kw3">unserialize</span></a><span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$data</span> || <a href="http://www.php.net/time"><span class="kw3">time</span></a><span class="br0">&#40;</span><span class="br0">&#41;</span> &gt; <span class="re0">$data</span><span class="br0">&#91;</span><span class="nu0">0</span><span class="br0">&#93;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="re0">$this</span>-&gt;<span class="me1">delete</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<span class="kw1">return</span> <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$data</span><span class="br0">&#91;</span><span class="nu0">1</span><span class="br0">&#93;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> delete<span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$key</span><span class="br0">&#41;</span> <span class="kw1">return</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="re0">$filename</span> = <span class="re0">$this</span>-&gt;<span class="me1">getFileName</span><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">if</span> <span class="br0">&#40;</span><a href="http://www.php.net/file_exists"><span class="kw3">file_exists</span></a><span class="br0">&#40;</span><span class="re0">$filename</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <a href="http://www.php.net/unlink"><span class="kw3">unlink</span></a><span class="br0">&#40;</span><span class="re0">$filename</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">else</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="kw2">false</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="kw2">function</span> getFileName<span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class="kw1">return</span> <span class="re0">$this</span>-&gt;_path.<a href="http://www.php.net/md5"><span class="kw3">md5</span></a><span class="br0">&#40;</span><span class="re0">$key</span><span class="br0">&#41;</span>.<span class="st0">&#8216;.gz&#8217;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="br0">&#125;</span></div>
</li>
<li class="li2">
<div class="de2">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">?&gt;</span></div>
</li>
</ol>
</div>
<p>เอาล่ะ ผมจะมาอธิบายว่าในแต่ละ method ทำหน้าที่อะไรกันบ้าง<br />
1. construct<br />
ใช้สำหรับเรียกค่าต่างๆ ของ CI เข้ามาใช้กันและทำการ load helper node มาใช้ พอดีไอ้ function ชุดแรกผมไปเขียนใน helper ที่ชื่อว่า node น่ะครับ</p>
<p>2. setParnet<br />
เป็นตัวกำหนด Dir หลักที่จะ ทำการใส่ data cache ลงไป</p>
<p>3. setMaxDir<br />
เป็นตัวกำหนดว่าจะ hash dir ย่อยทั้งหมดภายใต้ main dir กี่ folder</p>
<p>4. setDir<br />
เป็นตัว hash dir ย่อยภายใต้ main dir อีกที โดยจะรับค่า string เข้ามาทำการ hash</p>
<p>5. strore<br />
เป็นตัวเก็บข้อมูลเพื่อทำการ Caching โดยจะระบุ key, data, expiration โดยจะ write file เป็น .gz เพื่อบีบขนาดให้เล็กที่สุด ข้อมูลภายในจะถูกเก็บเป็น array โดย </p>
<p>index:0 จะเก็บ current time + expire time<br />
index:1 data ในรูปแบบ data ที่เข้ามาปกติ โดย data จะอยู่ในรูปแบบใดก็ได้ เช่น string, array, object</p>
<p>จากนั้นจะทำการ Write ข้อมูลแบบ PHP Serialize เพื่อแปลง Array เป็น String ชุดเดียว </p>
<p>6. fetch<br />
เป็นตัวดึงข้อมูลกลับออกมาจาก cache โดยระบุ key ค้นหาเข้าไป การดึงข้อมูลกลับ จะทำการเช็คที่ index:0 ก่อนคือ Expiration ถ้าหมดอายุก็จะทำการ delete cache ทิ้งและ return false กลับมา (miss cached) ถ้าไม่ใช่ก็จะคืน data ที่ cached เข้าไปกลับมา</p>
<p>7. delete<br />
เป็นตัว ลบข้อมูลของ cached ตาม key index</p>
<p>8. getFileName<br />
อันนี้จะถูกใช้แค่ระหว่าง method เป็นการ hash ชื่อไฟล์ที่จะ cache ด้วย md5 โดยจะ return กลับไปพร้อมๆ กับ path </p>
<p>เอาล่ะๆ จบแล้วสำหรับขั้นตอนการเขียน ตอนนี้มาดูขั้นตอนการใช้งานจริงๆ กันเลยดีกว่า ส่วนมาก caching นี้ผมจะเอามา cache Query ที่อยู่ใน model เสียเป็นส่วนใหญ่คือ ไม่ให้ดึง data จาก DB ตลอดเวลา แต่ให้ดึงเอาจาก cache ในกรณีที่ data ไม่มีการเปลี่ยนแปลง</p>
<p>สมมุติ ผมมี model::User_model->getUserData($user_id) เพื่อที่จะดึงข้อมูลของสมาชิก แทนที่ผมจะ Query db ตรงๆ ผมก็จะเขียนแบบนี้แทน </p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="co1">//สมมุติว่า load library caching ที่เขียนไว้มาแล้ว</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$this</span>-&gt;<span class="me1">caching</span>-&gt;<span class="me1">setDir</span><span class="br0">&#40;</span><span class="st0">&#8216;user_dir&#8217;</span>, <span class="re0">$user_id</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/*****พอผ่านบรรทัดนี้แล้ว ผมก็จะได้ path ที่จะจัดเก็บหรือ ดึง data เรียบร้อยแล้ว****</span></div>
</li>
<li class="li2">
<div class="de2"><span class="coMULTI">อาจจะเป็น cache/user_dir/xxxx/ โดยที่ xxx คือการ hash ค่าของ $user_id ผ่าน algo CRC32 นั่นเอง*/</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$row</span> = <span class="re0">$this</span>-&gt;<span class="me1">caching</span>-&gt;<span class="me1">fetch</span><span class="br0">&#40;</span><span class="re0">$user_id</span><span class="br0">&#41;</span><span class="br0">&#41;</span></div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$sql</span> = <span class="st0">&quot;SELECT &#8230;&#8230;&#8230;.&quot;</span>;</div>
</li>
<li class="li2">
<div class="de2">&nbsp; <span class="re0">$row</span> = <span class="st0">&quot;ตรงนี้เป็นการเขียน mysql query ตามปกติ&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$this</span>-&gt;<span class="me1">caching</span>-&gt;<span class="me1">store</span><span class="br0">&#40;</span><span class="re0">$user_id</span>, <span class="re0">$row</span>, <span class="nu0">3600</span><span class="br0">&#41;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><span class="coMULTI">/* อันนี้เป็นการ fetch data ก่อนครับ โดยมีเงื่อนไขว่าถ้า data ใน cache ไม่มีแล้ว ให้ไป ทำการ query มาใหม่ แล้วค่อย เก็บ data ลง cache และระบุให้หมดอายุ ภายในอีก 3600 วินาทีข้างหน้า (1 ชั่วโมง) ดังนั้นในการ fetch ครั้งหน้่า เราก็จะได้ data จาก cache แล้ว */</span></div>
</li>
</ol>
</div>
<p>เป็นอันจบครับสำหรับ lib:caching ที่เขียนเองขึ้นมา ส่วนการจัดการ cache ผมจะ ไกด์คร่าวๆ ว่ามันควรจะเป็นยังไงนะครับ มันมีผังการเดินทางของมันอยู่ ตัวอย่างเช่น</p>
<p>1. ถ้า fetch ข้อมูล จาก key เจอ จะ ใช้ data จาก cache<br />
2. ถ้า fetch ข้อมูล จาก key ไม่เจอ ก็จะใช้ data สดๆ แต่ก็ทำ การ store cache ไปพร้อมๆกัน</p>
<p>3. ถ้ามีการ update data ก็จะทำการลบ cache ตาม key เพื่อให้ข้อมูลมีความสดใหม่ และวนกลับไปยังข้อ 2 </p>
<p>สรุป method ใน model ที่ควรจะมีความเกี่ยวเนื่องกับระบบ cache มันก็ควรจะมีพวกเรื่อง</p>
<p>getData, updateData</p>
<p>อืมม์ เรื่องการ manage cache ให้ได้ข้อมูลสดอยู่ตลอดไม่ใช่เรื่องง่ายครับ แต่ผมคิดว่ามันคงไม่ยากเกินไปหรอกครับ และที่สำคัญ ถ้าเพื่อนๆ ทำความเข้าใจกับ lib:caching ที่ผมเขียนขึ้นมาตัวนี้ได้แล้ว จะเอา method ไปแก้ไขเป็น memcached หรือ apc อะไรก็ไม่ลำบากแล้วล่ะครับ </p>
<p>วันนี้เนื้อหาค่อนข้างหนักพอสมควร ผมเองก็ปวดหัวละ ขอพอก่อนละกัน สวัสดีครับ</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jquerytips.com/2009/01/23/ci-cache/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>บทความว่าด้วยการ optimize code ด้วยการทำ caching</title>
		<link>http://www.jquerytips.com/2008/04/07/optimize-code-caching/</link>
		<comments>http://www.jquerytips.com/2008/04/07/optimize-code-caching/#comments</comments>
		<pubDate>Mon, 07 Apr 2008 15:40:09 +0000</pubDate>
		<dc:creator>Tee++;</dc:creator>
				<category><![CDATA[Others]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[caching]]></category>
		<category><![CDATA[optimize]]></category>
		<category><![CDATA[performance]]></category>

		<guid isPermaLink="false">http://www.jquerytips.com/2008/04/07/%e0%b8%9a%e0%b8%97%e0%b8%84%e0%b8%a7%e0%b8%b2%e0%b8%a1%e0%b8%a7%e0%b9%88%e0%b8%b2%e0%b8%94%e0%b9%89%e0%b8%a7%e0%b8%a2%e0%b8%81%e0%b8%b2%e0%b8%a3-optimize-code-%e0%b8%94%e0%b9%89%e0%b8%a7%e0%b8%a2/</guid>
		<description><![CDATA[ตัวผมเองนั้นมีประสบการณ์ไม่ดีกับปัญหา MySQL จนเกือบจะเลิกใช้มันไปแล้วครั้งนึง จนหาทาง optimize code แบบต่างๆออกมาซึ่งได้ผลดีบ้างน้อยบ้างตามแต่จะว่ากัน ดังนี้
1. query database I/O ธรรมดา
:ผลลัพธ์ คนเข้าเยอะ โฮสเดี้ยง เวบล่ม โดนด่า
2. ทำ index ให้กับ db
:ผลลัพธ์ สามารถใช้ได้แค่เป็นส่วนประกอบของการทำ optimize code เท่านั้น แต่ถือว่า &#8220;จำเป็น&#8221; เลยทีเดียว
3. ทำการ cache output ออกมาเป็น static (html)
:ผลลัพธ์ ดีทีเดียว แต่มีปัญหาเรื่องความสดของข้อมูล manage เรื่อง fresh content ยาก
4. ทำการเปลี่ยนเป็น flat db (text, xml, etc.)
:ผลลัพธ์ ใช้ได้เลย แต่มีปัญหาเรื่องการเขียนข้อมูลพร้อมกันทีละหลายคน lock ไม่ทัน ไฟล์ตาย ข้อมูล write มาไม่ครบ backup [...]]]></description>
			<content:encoded><![CDATA[<p>ตัวผมเองนั้นมีประสบการณ์ไม่ดีกับปัญหา MySQL จนเกือบจะเลิกใช้มันไปแล้วครั้งนึง จนหาทาง optimize code แบบต่างๆออกมาซึ่งได้ผลดีบ้างน้อยบ้างตามแต่จะว่ากัน ดังนี้</p>
<p>1. query database I/O ธรรมดา<br />
:ผลลัพธ์ คนเข้าเยอะ โฮสเดี้ยง เวบล่ม โดนด่า</p>
<p>2. ทำ index ให้กับ db<br />
:ผลลัพธ์ สามารถใช้ได้แค่เป็นส่วนประกอบของการทำ optimize code เท่านั้น แต่ถือว่า &#8220;จำเป็น&#8221; เลยทีเดียว</p>
<p>3. ทำการ cache output ออกมาเป็น static (html)<br />
:ผลลัพธ์ ดีทีเดียว แต่มีปัญหาเรื่องความสดของข้อมูล manage เรื่อง fresh content ยาก<span id="more-24"></span></p>
<p>4. ทำการเปลี่ยนเป็น flat db (text, xml, etc.)<br />
:ผลลัพธ์ ใช้ได้เลย แต่มีปัญหาเรื่องการเขียนข้อมูลพร้อมกันทีละหลายคน lock ไม่ทัน ไฟล์ตาย ข้อมูล write มาไม่ครบ backup ลำบาก</p>
<p>จนมาถึงวิธีที่ผมใช้มาจนปัจจุบัน เหมาะมากๆกับการที่มีคนเข้าจำนวนหลัก หมื่น จนถึง หลักแสน</p>
<p>ซึ่งวิธีที่ดีที่สุดในตอนนี้คงหนีไม่พ้นการทำ cache ใส่ memory โดยตรงพวก โดยใช้ extensions พวก apc, memcache</p>
<p>ซึ่งการทำแบบนี้ให้ผลลัพธ์ที่ดีในระดับ &#8220;พระเจ้า&#8221; เวบจะเร็วขึ้นอย่างทันตาเห็น เพราะ cache จะถูกทำใน fast memory ซึ่งมีความเร็วเป็นทุนเดิมอยู่แล้ว และเมื่อขอ้มูลเต็มจะมีการ clear เอาของที่เก่าออกเอง</p>
<p>แต่ทว่า&#8230;.</p>
<p>ข้อเสียคือต้องลงทุนไปตั้ง Server เองเพราะไม่มี share hosting ที่ไหนให้เรามา แชร์ ram มันหรอกจริงมั้ยครับ T_T</p>
<p>ฉะนั้นเราก็จะมาทำกันง่ายๆก่อนด้วยการทำ cache ในระดับ file </p>
<p>ซึ่งง่ายที่สุดประหยัดค่าใช้จ่ายที่สุด ที่สำคัญลงมือทำได้เลย</p>
<p>************************************<br />
รูปแบบของcache จะแบ่งออกเป็น hit กับ miss ซึ่ง hit หมายถึง user เรียกข้อมูลใช้จาก cache ได้ทันทีซึ่งเป็น &#8220;ตัวดี&#8221; ส่วน miss คือ user ไม่สามารถเรียกใช้ cache ได้ในกรณีต่างๆ ซึ่งเป็น &#8220;ตัวไม่ดี&#8221;</p>
<p>ถ้าเราใช้ cache แบบ memory เราสามารถจะวัดผลได้เลยว่ามี hit กี่ % แต่ถ้าเป็น file ก็คงต้องให้ admin มา monitor กันละครับ เอาเป็นว่า ลืมไปก่อนละกัน อิอิ</p>
<p>แต่ว่าการเริ่ม cache ทุกครั้งจะต้องเริ่มจาก miss ก่อนเสมอ คือ</p>
<p>1. user เข้ามาครั้งแรกเรียกข้อมูลจาก cache ไม่เจอ<br />
2. ดึงข้อมูลโดยตรงจาก db (miss)<br />
3. ทำการสร้าง cache จากข้อมูลที่ user ดึง<br />
4. user เข้ามาครั้งที่ 2 เรียกข้อมูลจาก cache เจอ เรียกใช้ได้ทันที (hit)</p>
<p>ทีเหลือต้องไป manage ความสดใหม่ของ cache เอาเอง เช่น</p>
<p>1. user ทำการอัพเดท profile ลบ cache ทิ้งรอให้ user สร้าง cache ด้วยตัวเอง ซึ่งแน่นอนจะเกิด miss อีก 1 ที</p>
<p>หรือจะทำงานหนักขึ้น (coding)</p>
<p>2. user ทำการอัพเดท profile แล้วเราอัพเดท cache ทันที ไม่รอให้เกิดการ miss</p>
<p>************************************<br />
ลองมาดูตัวอย่างการทำ cache จากผลลัพธ์ การ query อย่างง่ายๆ กันก่อน</p>
<div class="dean_ch" style="white-space: wrap;">
<ol>
<li class="li1">
<div class="de1"><span class="kw2">&lt;?php</span></div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$cache</span> = <span class="st0">&quot;cache/&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1"><span class="re0">$key</span> = <span class="st0">&quot;your_key&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li2">
<div class="de2"><span class="kw1">if</span> <span class="br0">&#40;</span>!<span class="re0">$data</span> = <a href="http://www.php.net/file_get_contents"><span class="kw3">file_get_contents</span></a><span class="br0">&#40;</span><span class="re0">$cache</span>.<span class="re0">$key</span><span class="br0">&#41;</span><span class="br0">&#41;</span> <span class="br0">&#123;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$sql</span> = <span class="st0">&quot;SELECT &#8230;&#8230;.&quot;</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="co1">//&#8230;&#8230; query step &#8230;&#8230; (ละไว้ในฐานที่เข้าใจ)</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp; <span class="re0">$data</span> = <span class="re0">$results</span>;</div>
</li>
<li class="li1">
<div class="de1">&nbsp; file_put_contents<span class="br0">&#40;</span><span class="re0">$cache</span>.<span class="re0">$key</span>, <span class="re0">$data</span><span class="br0">&#41;</span>; <span class="co1">// php5 only!</span></div>
</li>
<li class="li2">
<div class="de2"><span class="br0">&#125;</span></div>
</li>
<li class="li1">
<div class="de1">&nbsp;</div>
</li>
<li class="li1">
<div class="de1"><a href="http://www.php.net/print_r"><span class="kw3">print_r</span></a><span class="br0">&#40;</span><span class="re0">$data</span><span class="br0">&#41;</span>; <span class="co1">// ทดสอบข้อมูล</span></div>
</li>
<li class="li1">
<div class="de1"><span class="kw2">?&gt;</span></div>
</li>
</ol>
</div>
<p>ตามโคดข้างบนจะเป็นการเรียกcache ถ้าไม่มีก็ให้ทำการสร้าง cache ซึ่งโคดตัวนี้ผมแค่เขียนเป็นแนวทางเพื่อให้เห็นภาพ แต่ว่ามันใช้ไม่ได้จริงๆ แหะๆ เพราะจุดอ่อนมากมายเช่นไม่มีการตั้ง cache expire ไม่มีการ lock ข้อมูลระหว่างเขียนไม่สามารลบ cache ออกได้เอง</p>
<p>ซึ่งตามปกติคนที่จะใช้ cache ในลักษณะนี้มักจะเขียน class ขึ้นมา 1 ตัวเพื่อทำหน้าที่ในส่วน</p>
<p>1. การ store ค่าลง cache พร้อมระบุเวลาหมดอายุ รวทั้ง key<br />
2. การ fetch ค่าที่ยังไม่หมดอายุ จาก cache โดยใช้ key อ้างอิง<br />
3. การ ลบค่า ออกจาก cache โดยการระบุ key<br />
4. การ clear cache ทั้งหมด</p>
<p>ซึ่งลองดูตัวอย่างได้จากlink ด้านล่าง เอา class ไปใช้ได้เลยหรือจะปรับปรุงให้ดีขึ้นตามสไตล์ก็แล้วแต่ ในที่นี้ผมเห็นมี class ที่ทำงานกับ 3 แบบเลยคือ file,apc, memcache ลองดูแล้วกันครับ</p>
<p>http://www.rooftopsolutions.nl/article/107</p>
<p>************************************<br />
ข้อพึงระวังในการทำ File Cache ก็คือพยายามอย่าเก็บไฟล์ cache ไว้ที่ folder เดียว เพราะมันจะมีปัญหาเรื่องการ seek ข้อมูลอีก -*-</p>
<p>โดยอาจจะใช้อัลกอลิทึ่มสักตัวมาคำนวนว่า cache นี้ควรจะเก็บไว้ที่โฟลเดอร์ไหน ตัวอย่าง</p>
<p><code>$cache = "cache/';<br />
$key = "mykey";<br />
$sub = (strlen($key)%9);</p>
<p>$cache.=$sub."/"; // ควรจะได้ค่าเป็น cache/5/</code></p>
<p>ซึ่งแบบนี้เท่ากับว่าเราจะมี cache/ เป็น directory ที่เก็บหลัก ข้างในยังแบ่งย่อยได้อีก 9 เพราะ mod 9</p>
<p>หรือจะใช้วิธีตัดตัวอักษรตัวแรก แล้วทำเป็นโฟลเดอร์ย่อย คือ 1-9 a-z รอไว้เลยก็ได้</p>
<p>แต่ถ้าวันไหนเกิดcache เต็มก็ลบออกไปหมด แล้วให้มัน built ใหม่ยังดีกว่าให้มัน fetch ค่าจาก db ที่เผลอๆ บางที join กัน 5-10 ตาราง ตรงๆ แน่นอน</p>
]]></content:encoded>
			<wfw:commentRss>http://www.jquerytips.com/2008/04/07/optimize-code-caching/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>
