<?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>Cold Start &#8211; Few Steps &#8211; ก้าวสั้นๆ แต่ไปเรื่อยๆ</title>
	<atom:link href="https://myifew.com/tag/cold-start/feed/" rel="self" type="application/rss+xml" />
	<link>https://myifew.com</link>
	<description></description>
	<lastBuildDate>Sat, 09 Nov 2019 02:22:23 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://myifew.com/wp-content/uploads/2018/07/cropped-logo6-ts-32x32.png</url>
	<title>Cold Start &#8211; Few Steps &#8211; ก้าวสั้นๆ แต่ไปเรื่อยๆ</title>
	<link>https://myifew.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>9 วิธีจัดการกับ Cold Start ใน Serverless ให้ทำงานได้ไวที่สุด พร้อมตัวอย่าง</title>
		<link>https://myifew.com/5386/9-ways-to-fighting-with-cold-start-in-serverless/</link>
					<comments>https://myifew.com/5386/9-ways-to-fighting-with-cold-start-in-serverless/#respond</comments>
		
		<dc:creator><![CDATA[iFew]]></dc:creator>
		<pubDate>Thu, 30 May 2019 12:50:32 +0000</pubDate>
				<category><![CDATA[Technology]]></category>
		<category><![CDATA[AWS]]></category>
		<category><![CDATA[AWS Lambda]]></category>
		<category><![CDATA[Cold Start]]></category>
		<category><![CDATA[Microservices]]></category>
		<category><![CDATA[Performance Test]]></category>
		<category><![CDATA[Serverless]]></category>
		<guid isPermaLink="false">https://myifew.com/?p=5386</guid>

					<description><![CDATA[Update 6 Nov 2019 &#8211; ทาง AWS ได้แก้ไขปัญหาเรื่อง Cold Start เนื่องจากใช้ VPC แล้ว ซึ่งมีผลกับ Region ดังนี้ US West&#8230;]]></description>
										<content:encoded><![CDATA[
<p><strong>Update 6 Nov 2019</strong> &#8211; ทาง AWS ได้แก้ไขปัญหาเรื่อง Cold Start เนื่องจากใช้ VPC แล้ว ซึ่งมีผลกับ Region ดังนี้ US West (N. California), EU (Ireland), EU (Paris), Asia Pacific (Mumbai), Asia Pacific (Seoul), Asia Pacific (Singapore), Asia Pacific (Sydney), and South America (San Paulo)    &#8211; ที่มา <a rel="noreferrer noopener" href="https://aws.amazon.com/th/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/" target="_blank">aws.amazon.com</a> </p>



<p><strong>Update 27 Sep 2019</strong> &#8211;  ทาง AWS ได้แก้ไขปัญหาเรื่อง Cold Start เนื่องจากใช้ VPC แล้ว ซึ่งมีผลกับ Region ดังนี้  US East (Ohio), EU (Frankfurt), and Asia Pacific (Tokyo)  &#8211; ที่มา <a rel="noreferrer noopener" aria-label="aws.amazon.com (opens in a new tab)" href="https://aws.amazon.com/th/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/" target="_blank">aws.amazon.com</a></p>



<p style="text-align:center">&#8230;</p>



<p>ผมเชื่อว่าใครก็ตามที่ตัดสินใจทำ Serverless มักเจอปัญหาที่แก้ไม่ตกคือ เรื่อง Cold Start ซึ่งบล็อกนี้ผมขอแชร์ประสบการณ์ที่ได้แก้ปัญหาทั้งหมด 9 วิธี เผื่อจะเป็นประโยชน์กันนะครับ  (ขออ้างอิงจากผู้ให้บริการ AWS Lambda และภาษาที่ใช้พัฒนา C# .NET Core)</p>



<span id="more-5386"></span>



<h2 class="wp-block-heading">ทำความเข้าใจ Cold Start คืออะไร</h2>



<p>ขอเกริ่นถึงสั้นๆ ของการทำงาน Serverless คือ เมื่อมีการร้องขอ (Request) ไปที่  Instances (เข้าใจง่ายๆ คือ Server ตัวหนึ่ง) เพื่อให้มันทำงาน มันจะใช้เวลาช่วงหนึ่งเพื่อทำการ Initial Instances จากนั้นค่อยเรียกโค้ดที่เราเขียน ขึ้นมาทำงานตามคำสั่ง </p>



<p>เมื่อมีการเรียกซ้ำอีก มันก็จะทำต่อเนื่องได้ทันที ไม่ต้องเสียเวลา Initial Instances ใหม่ แต่เมื่อทำงานเสร็จและปล่อยไว้สักระยะหนึ่ง เจ้า Instances ตัวนั้นก็จะเข้าสู่โหมด Idle อีก (หรือบางคนเรียกว่า หลับ, sleep) ดังนั้นเมื่อมีการร้องขอ (Request) ใช้งานอีกครั้ง จะเกิดกระบวนการ Initial Instances แบบเดิม ก่อนที่จะทำงานโค้ดของเรา</p>



<p>การ Initial Server ในครั้งแรก หรือครั้งหลังจากโหมด Idle นี่เอง เราจะเรียกว่า Cold Start</p>



<figure class="wp-block-image"><img fetchpriority="high" decoding="async" width="1200" height="578" src="https://myifew.com/wp-content/uploads/2019/02/01_cold_start_aws_client-1200x578.jpeg" alt="" class="wp-image-5286" srcset="https://myifew.com/wp-content/uploads/2019/02/01_cold_start_aws_client-1200x578.jpeg 1200w, https://myifew.com/wp-content/uploads/2019/02/01_cold_start_aws_client-1024x493.jpeg 1024w, https://myifew.com/wp-content/uploads/2019/02/01_cold_start_aws_client-768x370.jpeg 768w, https://myifew.com/wp-content/uploads/2019/02/01_cold_start_aws_client-700x337.jpeg 700w, https://myifew.com/wp-content/uploads/2019/02/01_cold_start_aws_client-600x289.jpeg 600w, https://myifew.com/wp-content/uploads/2019/02/01_cold_start_aws_client.jpeg 1266w" sizes="(max-width: 1200px) 100vw, 1200px" /><figcaption>Initial Instances หรือ Cold Start คือช่วงตั้งแต่ Download the code, Container Setup, Initialization and start of the code</figcaption></figure>



<p>และมากกว่านั้น ภาษาที่ต้องมีการ Compile จะมีขั้นตอน 1-3 นานกว่าภาษา Script หลายเท่า (ผมลองพ่น Hello World โดยใช้ Node ไม่ถึง 1 วินาที, เทียบกับ .Net Core ใช้เวลา 4-5 วินาที)</p>



<p>และมีคำถามบ่อยๆ ว่าจะเข้าสู่โหมด Idle ภายในกี่นาที คำตอบคือ ไม่มีใครสามารถตอบได้ชัดเจน บางแหล่งก็บอก 30-45 นาที บางแหล่งก็บอก 15 นาที แต่สำหรับผมที่เล่นเอง จะเจอแถวๆ 5 นาทีเป็นต้นไป เรียกได้ว่าลุกไปเข้าห้องน้ำแป๊บนึง พอกลับมา มันก็ช้าอีกแล้ว (ผมใช้ AWS Lambda ที่ ap-southeast-1)  </p>



<figure class="wp-block-image"><img decoding="async" width="1624" height="860" src="https://myifew.com/wp-content/uploads/2019/05/estimate-time-to-sleep.png" alt="" class="wp-image-5407"/><figcaption>ความเป็นไปได้ที่จะเกิด Cold Start หลังมีการเรียกใช้ไปแล้ว x นาที (รูปอ้างอิงจาก <a rel="noreferrer noopener" href="https://mikhail.io/serverless/coldstarts/aws/" target="_blank">mikhail.io</a>)</figcaption></figure>



<p>อ่านพื้นฐานเรื่อง Serverless และ AWS Lambda ฉบับเต็มได้ที่ </p>



<ul class="wp-block-list"><li><a href="https://myifew.com/5166/understand-serverless-with-aws-lambda-for-newbie/">มาทำความรู้จักกับ Serverless และ AWS Lambda ฉบับคนคิดจะใช้</a></li></ul>



<h2 class="wp-block-heading">9 วิธีเพื่อใช้ลดเวลา Cold Start</h2>



<p>คราวนี้ Cold Start ได้เป็นเสี้ยนหนามของผมมาก สุดท้ายแล้ว ผมพบว่ามี 9 วิธี ที่จะลดเวลา Cold Start ได้ ผู้อ่านสามารถเลือกไปทำ หรือจะทำทั้งหมดเลยก็ได้ ลองดูกันว่ามีวิธีใดบ้าง</p>



<ol class="wp-block-list"><li>เพิ่ม Memory Allocated</li><li>Lean and Clean Code</li><li>ลด และ/หรือ เลือกใช้ Dependency ที่จำเป็นและเหมาะสม</li><li>Warm ตัว Server ของเราตลอดเวลา</li><li>Warm ตัว Server ของเราตามเวลาที่เหมาะสม</li><li>ใช้ Custom Runtimes และเลือกใช้ Runtimes ที่ทำงานได้เร็ว</li><li>ใช้ Custom Runtimes และทำเป็น Native App</li><li>หลีกเลี่ยงการใช้ VPC ถ้าไม่จำเป็น</li><li>เลือกภาษาเพื่อใช้ทำ Serverless ที่เหมาะสม</li></ol>



<h2 class="wp-block-heading">1. เพิ่ม Memory Allocated</h2>



<p>วิธีง่ายที่สุดคือใช้เงินจอง Memory ให้กับ AWS Lambda Instances มากๆ (Memory Allocated) ซึ่งมันก็เห็นผลได้เร็วและชัดเจนซะด้วย </p>



<p>กรณีแบบนี้ผมคิดว่าเหมาะกับการคำนวณ (Compute) ที่ไม่ได้เกิดขึ้นบ่อย แต่ต้องทำงานได้ไว และไม่ต้องการแก้ไขให้ยุ่งยาก &#8212; หรือพูดสั้นๆ คือ ยอมจ่ายค่า Memory ที่แพงขึ้น แลกกับ Duration Time ที่ลดลง แต่นานๆที เรียกใช้</p>



<p>กรณีนี้ผมทดลองด้วย C# .NET Core 2.1 ดึงข้อมูลจาก MySQL จำนวน 3 รายการ</p>



<figure class="wp-block-image"><img decoding="async" width="2542" height="1214" src="https://myifew.com/wp-content/uploads/2019/05/memory-allocated-memberlist-128.png" alt="" class="wp-image-5387"/><figcaption>Memory Allocated 128 MB &#8211; Duration Time 10,169 ms</figcaption></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1473" height="234" src="https://myifew.com/wp-content/uploads/2019/05/memory-allocated-memberlist-256.png" alt="" class="wp-image-5388"/><figcaption>Memory Allocated 256 MB &#8211; Duration Time 4999 ms</figcaption></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1457" height="237" src="https://myifew.com/wp-content/uploads/2019/05/memory-allocated-memberlist-512.png" alt="" class="wp-image-5389"/><figcaption>Memory Allocated 512 MB &#8211; Duration Time 2,426 ms</figcaption></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1450" height="233" src="https://myifew.com/wp-content/uploads/2019/05/memory-allocated-memberlist-1024.png" alt="" class="wp-image-5390"/><figcaption>Memory Allocated 1,024 MB &#8211; Duration Time 1,153 ms</figcaption></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1834" height="758" src="https://myifew.com/wp-content/uploads/2019/05/memory-allocated-compare.png" alt="" class="wp-image-5391"/><figcaption>เทียบโค้ดชุดเดียวกัน แต่ใช้ Memory Allocate ต่างกันกัน</figcaption></figure>



<p>สังเกตได้ว่า ยิ่งเพิ่ม Memory Allocated มากเท่าไร ก็ยิ่งลดเวลา Cold Start ได้มากเป็นเท่าตัว</p>



<p>แต่วิธีการนี้อาจจะไม่ดี 100% กับทุกกรณี เช่น ทดสอบแสดงข้อความ &#8220;Hello World&#8221; ด้วยภาษา Javascript  ตามรูปด้านล่าง</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1347" height="643" src="https://myifew.com/wp-content/uploads/2019/05/aws-coldstart-js-by-memory.png" alt="" class="wp-image-5411"/><figcaption>Javascript แสดงข้อความ Hello Wold ที่จัดสรร Memory ต่างกัน แต่ผลออกมาแทบไม่ต่างกัน <br>(รูปอ้างอิงจาก <a href="https://mikhail.io/2018/08/serverless-cold-start-war/">mikhail.io</a>)</figcaption></figure>



<p>สังเกตว่า แม้เพิ่ม Memory Allocated ไปมากเท่าใด เวลาของ Cold Start ก็ไม่ต่างกันมากนัก และ Memory สูงที่สุด ก็ไม่ได้บ่งบอกว่าจะเร็วที่สุดด้วย ดังนั้นเราจึงควรหาวิธีอื่นเพื่อลด Cold Start แทน</p>



<p>ถ้าให้ผมแนะนำ กรณีเพิ่ม Memory Allocated นี้ เราไม่ควรจะคาดเดา ซึ่งผมเคยเขียนวิธีการทดสอบไว้แล้ว สามารถอ่านวิธีการได้ที่ <a rel="noreferrer noopener" aria-label="จัดสรรทรัพยากร AWS Lambda อย่างไร ให้ราคาถูกและเร็วที่สุด (opens in a new tab)" href="https://myifew.com/5339/how-to-optimize-memory-on-aws-lambda-for-costs-and-fastest/" target="_blank">จัดสรรทรัพยากร AWS Lambda อย่างไร ให้ราคาถูกและเร็วที่สุด</a></p>



<h2 class="wp-block-heading" id="mce_24">2. Lean and Clean Code</h2>



<p>วิธีการนี้อาศัยทักษะทางเขียนโปรแกรมหน่อย คือการทำให้ Application เรากระชับที่สุด อะไรไม่ใช้ก็ตัดทิ้ง อะไรที่จำเป็นน้อย ทำให้ไม่จำเป็นเลยได้หรือไม่ อะไรเปลี่ยนวิธีได้ก็เปลี่ยน เช่น</p>



<p>การเรียกใช้ Config จาก JSON File วิธีนี้จะทำให้เราต้องเรียกใช้ Package Dependency จัดการไฟล์ JSON ต่างๆ ซึ่งเราสามารถย้ายไปใช้ Environment Variable แทนได้  ซึ่งถูกต้องตามหลัก <a href="https://myifew.com/5080/the-twelve-factors/">The Twelve Factors</a> ด้วย</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1894" height="408" src="https://myifew.com/wp-content/uploads/2019/05/lean-clean-config-in-environment-1.png" alt="" class="wp-image-5393"/><figcaption>Environment Variable ใน AWS Lambda</figcaption></figure>



<p>หรือการเรียกใช้ Package Dependency เกินความจำเป็น หรือไม่ได้ใช้แล้ว แต่ลืมลบ กรณีนี้เครื่องมือดีๆ สามารถช่วยเราได้ เช่น Visual Studio ที่จะทำการแจ้งเตือนให้เราลบตัวไม่ใช้ออก</p>



<p>ทั้งนี้ รวมไปถึงพวก Class, Function ต่างๆ ที่เขียนไว้ แต่ไม่ได้ใช้ ก็ต้องลบออกด้วย</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1184" height="332" src="https://myifew.com/wp-content/uploads/2019/05/lean-clean-delete-not-using-used.png" alt="" class="wp-image-5420"/><figcaption>Package อะไรไม่ใช้ ก็ลบออกไป</figcaption></figure>



<p>ยิ่งเราทำให้ขนาดโค้ดเราเล็กลงได้เท่าไร ก็ทำให้ไฟล์ที่แพ็คขึ้นสู่ AWS Lambda (Deployment Package File) เล็กลงตามเท่านั้น มันจะส่งผลเรื่อง Cold Start ที่ลดเวลาลงไปด้วย </p>



<p>ลองดูได้จากสถติของเว็บ <a rel="noreferrer noopener" href="https://mikhail.io/serverless/coldstarts/aws/" target="_blank">mikhail.io</a> ที่เขาใช้ Javascript ในการแสดงคำว่า &#8220;Hello World&#8221; แต่ทดลองเพิ่ม NPM packages เข้าไปใน Deployment Package File ด้วย </p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1624" height="860" src="https://myifew.com/wp-content/uploads/2019/05/compare-cold-start-deployment-size.png" alt="" class="wp-image-5409"/><figcaption>เทียบเวลาการเกิด Cold Start เมื่อ Deployment Package (แบบ zip แล้ว) มีขนาดไฟล์ที่ใหญ่ขึ้น (รูปอ้างอิงจาก <a rel="noreferrer noopener" href="https://mikhail.io/serverless/coldstarts/aws/" target="_blank">mikhail.io</a> ) <br></figcaption></figure>



<p>ผลกระทบต่อมา ถ้าเราทำให้ Deployment Package File ใหญ่ขึ้น หมายถึงการทำให้ AWS Lambda Instances ใหญ่ขึ้นตามด้วย ถ้ามาถึงขั้นนี้แล้ว แม้จะเพิ่ม Memory เข้าไปช่วยเท่าไร ก็ไม่เห็นผลนะครับ เพราะ Cold Start ยังนานเหมือนเดิม แถมเสียเงินค่า Memory เพิ่มขึ้นด้วย</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1622" height="862" src="https://myifew.com/wp-content/uploads/2019/05/compare-cold-start-instance-size.png" alt="" class="wp-image-5410"/><figcaption>เมื่อ Instances Lambda เราใหญ่ การเพิ่ม Memory เข้าไป ดูจะไม่ข่วยทำให้เวลาในการ Cold Start ลดขึ้น แถมเสียเงินไปโดยเปล่าประโยชน์  (รูปอ้างอิงจาก <a rel="noreferrer noopener" href="https://mikhail.io/serverless/coldstarts/aws/" target="_blank">mikhail.io</a> ) </figcaption></figure>



<h2 class="wp-block-heading">3. ลด และ/หรือ เลือกใช้ Dependency ที่จำเป็นและเหมาะสม</h2>



<p>ข้อนี้จำเป็นต้อง Debug ให้เห็นรายละเอียดก่อน เพื่อประเมินว่าอะไรคือจุดที่ทำให้โค้ดเราทำงานช้า หรืออาจจะไปดูจาก Benchmark ที่มีผู้ทดสอบเปรียบเทียบ Package ต่างๆ เพื่อที่เราจะได้เลือกใช้ได้เหมาะสมตั้งแต่เริ่มพัฒนางาน</p>



<p>ปกติผมเขียน .NET Core ผมจะใช้ Entity Framework (EF) Core หรือ EF Core เพราะมันเหมือนชุดมาตรฐานที่ทำงานได้เข้ากันดี และมีเครื่องมือค่อนข้างครบ แต่ปรากฎว่า EF Core นี่เอง ทำให้ใช้เวลา Cold Start มากกว่าเดิมอย่างแสนสาหัส!! </p>



<p>ผมฝืนใช้มันอยู่นาน และไปหาทางแก้วิธีอื่นแทน จนกลับมาเอะใจตอนที่ Compile ว่า EF Core มันตัวใหญ่นี่หว่า ผมเลยลองเปลี่ยนไปใช้ ADO.NET หรือ Micro ORM อย่าง Dapper แทน ซึ่งผลปรากฎว่า เร็วขึ้นอีก 100% เลยทีเดียว </p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2028" height="756" src="https://myifew.com/wp-content/uploads/2019/05/change-dependency-compare-128mb.png" alt="" class="wp-image-5401"/><figcaption>ผลเปรียบเทียบในการใช้ ADO.NET, Dapper, EF Core เพื่อเรียกข้อมูลจาก Database</figcaption></figure>



<p>เรื่องนี้คงไม่ขอเขียนเยอะ กราฟมันบอกชัดเจนอยู่แล้ว หากใครสนใจลองเอาไปเปรียบเทียบ สามารถดาวน์โหลดโค้ดของผมได้จากที่นี่ (ต้องใช้ .NET Core 3.0, MySQL)</p>



<ul class="wp-block-list"><li>ADO.NET &#8211; <a href="https://github.com/ifew/aws-lambda-db">https://github.com/ifew/aws-lambda-db</a></li><li>Dapper &#8211; <a href="https://github.com/ifew/aws-lambda-dapper">https://github.com/ifew/aws-lambda-dapper</a></li><li>Entity Framework (EF) Core &#8211; <a href="https://github.com/ifew/aws-lambda-efcore">https://github.com/ifew/aws-lambda-efcore</a></li></ul>



<p>กรณี Benchmark เทียบ Database Framework ดูเพิ่มเติมได้ที่</p>



<ul class="wp-block-list"><li><a rel="noreferrer noopener" aria-label="Dapper vs Entity Framework vs ADO.NET Performance Benchmarking (opens in a new tab)" href="https://exceptionnotfound.net/dapper-vs-entity-framework-vs-ado-net-performance-benchmarking/" target="_blank">Dapper vs Entity Framework vs ADO.NET Performance Benchmarking</a></li><li><a rel="noreferrer noopener" aria-label="Fetch performance of various .NET ORM / Data-access frameworks (opens in a new tab)" href="https://weblogs.asp.net/fbouma/fetch-performance-of-various-net-orm-data-access-frameworks" target="_blank">Fetch performance of various .NET ORM / Data-access frameworks</a></li><li><a href="https://koukia.ca/entity-framework-core-2-0-vs-dapper-net-performance-benchmark-querying-sql-azure-tables-7696e8e3ed28" target="_blank" rel="noreferrer noopener" aria-label="Entity Framework Core 2.0 vs. Dapper performance benchmark, querying SQL Azure tables (opens in a new tab)">Entity Framework Core 2.0 vs. Dapper performance benchmark, querying SQL Azure tables</a></li></ul>



<h2 class="wp-block-heading">4. Warm ตัว Server ของเราตลอดเวลา</h2>



<p>หากเรามีความจำเป็นต้องใช้ Lambda อยู่บ่อยๆ มีผู้เข้าใช้กระจัดกระจายแบบกำหนดเวลาไม่ได้ รู้แต่เข้าเมื่อไร ต้องเร็ว เช่น การแสดงรายการสินค้าของหน้าเว็บไซต์ E-Commerce เป็นต้น ถ้าสุดท้ายแล้วเราไม่สามารถแก้ไขโค้ดได้อีก หรือไม่อยากเพิ่ม Memory อีก เราก็ต้องทำให้ Server ของเราตื่นอยู่เสมอนั่นเอง</p>



<p>วิธีการคือ การตั้งเวลาให้มี Cronjob ไปเรียก (Ping) Server ของเราอยู่เรื่อยๆ อย่างเช่น AWS Lambda ที่ผมเจอ จะ Idle ทุกๆ 5 นาทีไปแล้ว ผมก็ต้องหา Cronjob ไปทำการ Invoke Lambda ประมาณนาทีที่ 5 เสมอ </p>



<p>วิธีการแบบนี้จะเปลือง Request มาก เพราะแปลว่า 1 วัน ผมจะต้องปลุกมัน 288 ครั้ง ถ้าครั้งหนึ่งต้องใช้เวลาประมวลผล (Duration Time) 2 วินาที และจอง Memory 512MB คิดดูว่าเดือนหนึ่งผมจะต้องเสียเงินไปเท่าไร</p>



<p>ซึ่งหากใครสนใจลองทำ วิธีนี้ค้นเจอได้ตามเว็บทั่วไป ส่วนมากจะใช้ CloudWatch ในการทำ ซึ่งผมไม่รู้ว่าทำไมถึงแนะนำให้ทำกันแบบนี้ แต่มันก็ไม่ผิดนะ ถ้าเหมาะสมกับรูปแบบงาน คือ ถ้าตัว Server เราถูกเรียกบ่อยทั้งวัน กอปรกับใช้เวลาประมวลผลไม่มาก ใช้ Memory ไม่สูง ก็อาจจะเหมาะสม</p>



<p>สามารถดูเพิ่มเติมได้ที่</p>



<ul class="wp-block-list"><li><a rel="noreferrer noopener" aria-label="How to Keep Your Lambda Functions Warm (opens in a new tab)" href="https://read.acloud.guru/how-to-keep-your-lambda-functions-warm-9d7e1aa6e2f0" target="_blank">How to Keep Your Lambda Functions Warm</a></li><li><a rel="noreferrer noopener" aria-label="Tutorial: Schedule AWS Lambda Functions Using CloudWatch Events (opens in a new tab)" href="https://docs.aws.amazon.com/AmazonCloudWatch/latest/events/RunLambdaSchedule.html" target="_blank">Tutorial: Schedule AWS Lambda Functions Using CloudWatch Events</a></li><li><a rel="noreferrer noopener" aria-label="Lambda Warmer: Optimize AWS Lambda Function Cold Starts (opens in a new tab)" href="https://www.jeremydaly.com/lambda-warmer-optimize-aws-lambda-function-cold-starts/" target="_blank">Lambda Warmer: Optimize AWS Lambda Function Cold Starts</a></li><li><a href="https://github.com/jeremydaly/lambda-warmer">Lambda Warmer﻿</a></li></ul>



<h2 class="wp-block-heading">5. Warm ตัว Server ของเราตามเวลาที่เหมาะสม</h2>



<p>วิธีการนี้เหมือนกับข้อ 4 คือมี Conjob ไปเรียก (Ping) Server แต่ต่างกันที่ กำหนดเวลาในการเรียกให้ถี่มากน้อย ขึ้นกับการใช้งานจริง</p>



<p>เช่น 08:00-22:00 คนเข้าเว็บไซต์เยอะ ก็ให้เรียกทุก 5 นาที เพื่อให้ Instances ไม่เข้าโหมด Idle ส่วนเวลาตั้งแต่ 22:01-07:59 ให้เรียกทุก 10 นาที แทน เป็นต้น</p>



<p>หรือใคร Advance หน่อย ก็ทำสคริ้ปอัตโนมัติเพื่อ Edit Config Lambda ในช่วงเวลา 22:01-07:59 เพื่อปรับ  Memory ขึ้นไป แต่ไม่ต้องทำการ Ping ซึ่งมันก็จะไปใช้สูตรแบบข้อ 1. เพิ่ม Memory Allocated แทนการใช้แบบข้อ 4. เพื่อ Warm ตัว Server ตลอดเวลา</p>



<p>สามารถดูเพิ่มเติมได้ที่ </p>



<ul class="wp-block-list"><li><a rel="noreferrer noopener" aria-label="AWS CLI - Modify the version-specific settings of a Lambda function  (opens in a new tab)" href="https://docs.aws.amazon.com/cli/latest/reference/lambda/update-function-configuration.html" target="_blank">AWS CLI &#8211; Modify the version-specific settings of a Lambda function </a></li><li><a rel="noreferrer noopener" aria-label="How to trigger aws lambda at different schedule every day (opens in a new tab)" href="https://stackoverflow.com/questions/53570401/how-to-trigger-aws-lambda-at-different-schedule-every-day" target="_blank">How to trigger aws lambda at different schedule every day</a></li></ul>



<h2 class="wp-block-heading">6. ใช้ Custom Runtimes และเลือกใช้ Runtimes ที่ทำงานได้เร็ว</h2>



<p>กรณีของผู้ให้บริการอย่าง Amazon ได้เพิ่มฟีเจอร์มาให้กับ AWS Lambda คือ การ  <a rel="noreferrer noopener" aria-label="Custom Runtimes (opens in a new tab)" href="https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html" target="_blank">Custom Runtimes</a> ได้เอง โดยไม่จำเป็นต้องใช้ตัวมาตรฐานที่ให้มา</p>



<p>ตัวอย่างเช่น .NET Core Runtime ที่ทาง Amazon มีมาให้คือ version 1.0 และ 2.1 เท่านั้น</p>



<p><strong>.NET Runtimes (ดูเพิ่มเติม ได้ที่ <a rel="noreferrer noopener" aria-label="AWS Lambda Runtimes (opens in a new tab)" href="https://docs.aws.amazon.com/lambda/latest/dg/lambda-runtimes.html" target="_blank">AWS Lambda Runtimes</a>)</strong></p>



<table class="wp-block-table"><tbody><tr><th>Name</th><th>Identifier</th><th>Languages</th><th>Operating System</th></tr><tr><td>.NET Core 2.1</td><td><code>dotnetcore2.1</code></td><td>C#PowerShell Core 6.0</td><td>Amazon Linux</td></tr><tr><td>.NET Core 1.0</td><td><code>dotnetcore1.0</code></td><td>C#</td><td>Amazon Linux</td></tr></tbody></table>



<p>แต่ปัจจุบันมี 2.2 และ 3.0 แล้ว ซึ่งถ้าเราพบว่า 3.0 ทำงานได้ดีกว่า หรือไวกว่า เราก็สามารถสร้าง Runtimes ขึ้นมาเองได้ หรืออาจจะไปสร้างเป็น <a href="https://aws.amazon.com/th/blogs/apn/aws-lambda-custom-runtime-for-php-a-practical-example/" target="_blank" rel="noreferrer noopener" aria-label="PHP Runtimes (opens in a new tab)">PHP Runtimes</a> ก็ยังได้ ถ้าเราอยากจะใช้ แต่ Amazon ไม่ได้ทำรองรับ</p>



<p>ในประเด็นนี้ ผมพยายามทดสอบหลายครั้ง ผมพบว่าใน .NET Core เมื่อทำ Custom Runtimes แล้ว ไม่ได้ช่วยทำให้ไวขึ้นแต่อย่างใด แถมช้าลงด้วย มีดีอย่างเดียวคือ ได้ใช้ฟีเจอร์ใหม่ๆ ในเวอร์ชั่นใหม่ (แต่ในภาษาอื่นๆ ถ้าใครทำดูแล้วได้ผลที่ดีขึ้น ลองมาแชร์กันได้ครับ)</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2534" height="1090" src="https://myifew.com/wp-content/uploads/2019/05/crt-netcore21.png" alt="" class="wp-image-5398"/><figcaption>.NET Core 2.1 Runtimes (ตัวมาตรฐานของ Amazon)</figcaption></figure>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2542" height="1092" src="https://myifew.com/wp-content/uploads/2019/05/crt-netcore30.png" alt="" class="wp-image-5399"/><figcaption>.NET Core 3.0 preview4 Runtimes (ตัว Custom Runtimes ที่ผมทำขึ้นมา)</figcaption></figure>



<p>สังเกตว่า ตัวมาตรฐาน .NET Core 2.1 Runtimes ทำงานได้ไวกว่าที่ผม Custom Runtimes เอง ที่เวอร์ชั่น 3.0 (แม้ว่าจริงๆแล้วผล <a href="https://devblogs.microsoft.com/dotnet/performance-improvements-in-net-core-3-0/" target="_blank" rel="noreferrer noopener" aria-label="Benchmark ของ .NET Core 3.0 (opens in a new tab)">Benchmark ของ .NET Core 3.0</a> จะทำงานได้ไวกว่า 2.1 ในสภาพแวดล้อมที่ไม่ใช่ AWS Lambda ก็ตาม)</p>



<p>ใครอยากทดสอบ Custom Runtimes ลองดูโค้ดตัวอย่างที่ผมทำไว้ได้</p>



<ul class="wp-block-list"><li>.NET Core 3.0  &#8211; <a rel="noreferrer noopener" aria-label="https://github.com/ifew/aws-lambda-crt-example (opens in a new tab)" href="https://github.com/ifew/aws-lambda-crt-example" target="_blank">https://github.com/ifew/aws-lambda-crt-example</a></li><li>.NET Core 3.0 with ADO.NET &#8211; <a rel="noreferrer noopener" aria-label="https://github.com/ifew/aws-lambda-crt-db (opens in a new tab)" href="https://github.com/ifew/aws-lambda-crt-db" target="_blank">https://github.com/ifew/aws-lambda-crt-db</a></li><li>.NET Core 3.0 with Dapper &#8211; <a rel="noreferrer noopener" aria-label="https://github.com/ifew/aws-lambda-crt-db-dapper (opens in a new tab)" href="https://github.com/ifew/aws-lambda-crt-db-dapper" target="_blank">https://github.com/ifew/aws-lambda-crt-db-dapper</a></li></ul>



<p>เรื่อง Custom Runtimes สามารถศึกษาเพิ่มเติมได้ที่นี่ครับ</p>



<ul class="wp-block-list"><li><a href="https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html">Custom AWS Lambda Runtimes</a></li><li><a href="https://medium.com/@zaccharles/benchmarking-lambdas-new-custom-runtime-for-net-core-43ea79b5a35a" target="_blank" rel="noreferrer noopener" aria-label="Benchmarking Lambda’s New Custom Runtime for .NET Core (opens in a new tab)">Benchmarking Lambda’s New Custom Runtime for .NET Core</a></li></ul>



<h2 class="wp-block-heading" id="mce_94">7. ใช้ Custom Runtimes และทำเป็น Native App</h2>



<p>แม้ว่าการทำ Custom Runtimes ผมจะไม่พอใจกับผลลัพธ์ที่เกิดขึ้น (กรณี C# .NET Core) แต่เราสามารถเอาวิธีการเดียวกันมาเรียกใช้ Binary Executable File แทนได้นะ ด้วยการทำโค้ดของเราให้เป็น Native Application ซะเลย </p>



<p>การแก้ไขปัญหาด้วยวิธีนี้ ผมภูมิใจนำเสนอมากๆๆๆ เรียกได้ว่า เป็นไม้ตาย ที่แก้ปัญหา Cold Start ได้อยู่หมัดจากทุกๆ วิธีที่ผมทำมาเลยทีเดียว แต่ก็ค่อนข้างทำยากและมีข้อจำกัดเยอะ</p>



<p>มาลองดูสถิติที่ผมทำบน C# .NET Core กัน ว่าผลแตกต่างแค่ไหน ซึ่งผมเทียบโดยใช้ Database Framework ต่างกัน 3 ตัว ที่ทำงานต่างกันบน Runtimes แบบปกติ (.NET Core 2.1), Custom Runtimes (.NET Core 3.0) และ Native (.NET Core  3.0 + CoreRT)</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="2106" height="310" src="https://myifew.com/wp-content/uploads/2019/05/nativeapp-compare.png" alt="" class="wp-image-5402"/></figure>



<p>จากตาราง ตัว Lambda Native (ช่องสีเขียว) ชนะใสๆ แบบขาดรอย เพราะ Cold Start แค่ 1.3 วินาที ในขณะที่ตัวอื่นๆ ทำงานที่ 10-33 วินาที (เทียบกันที่ ADO.NET)</p>



<p>สังเกตว่าทำไมผมมี Lambda Native แค่ ADO.NET อย่างเดียว </p>



<p>เนื่องจาก Lambda Native ใช้ Runtimes ชื่อว่า CoreRT ซึ่งมันเป็น .NET Core runtime อีกตัวที่พัฒนามาเพื่อ AOT (ahead of time compilation) โดยเฉพาะ กล่าวคือ มันจะแปลงภาษาจาก High-Level Programming เช่น C#, Java ไปเป็นภาษาเครื่อง (Machine code) กันเลยทีเดียว</p>



<p>แต่ๆๆ เจ้าตัว CoreRT ยังไม่สมบูรณ์นัก และมีผู้ใช้งานไม่มาก หาข้อมูลได้ยาก จึงทำให้การพัฒนาได้ยากตาม รวมไปถึงหลายสิ่งยังไม่สามารถใช้งานได้ เช่น <a rel="noreferrer noopener" aria-label="เมื่อมีการเอา Dapper มาใช้ แต่โดนแจ้ง Error ว่า &quot;Operation is not supported on this platform&quot; (opens in a new tab)" href="https://github.com/dotnet/corert/issues/7386" target="_blank">เมื่อมีการเอา Dapper มาใช้ แต่โดนแจ้ง Error ว่า &#8220;Operation is not supported on this platform&#8221;</a> ด้วยเหตุผลนี้เอง ผมถึงบอกว่า ทำไมยังมีข้อจำกัดอยู่ และทำได้ยาก</p>



<p>ดูตัวอย่างที่ผมทำได้ที่นี่</p>



<ul class="wp-block-list"><li>Hello World &#8211; <a href="https://github.com/ifew/aws-lambda-lambdanative">https://github.com/ifew/aws-lambda-lambdanative</a></li><li>ADO.NET &#8211; <a href="https://github.com/ifew/aws-lambda-lambdanative-db">https://github.com/ifew/aws-lambda-lambdanative-db</a></li></ul>



<p>สามารถดูข้อมูลการทำ Lambda Native เพิ่มเติมได้ที่</p>



<ul class="wp-block-list"><li>LambdaNative &#8211; <a href="https://github.com/zaccharles/lambda-native">https://github.com/zaccharles/lambda-native</a></li><li>CoreRT &#8211; <a href="https://github.com/dotnet/corert">https://github.com/dotnet/corert</a></li></ul>



<h2 class="wp-block-heading">8. หลีกเลี่ยงการใช้ VPC ถ้าไม่จำเป็น</h2>



<p><strong>Update 6 Nov 2019</strong> &#8211; ทาง AWS ได้แก้ไขปัญหาเรื่อง Cold Start เนื่องจากใช้ VPC แล้ว ซึ่งมีผลกับ Region ดังนี้ US West (N. California), EU (Ireland), EU (Paris), Asia Pacific (Mumbai), Asia Pacific (Seoul), Asia Pacific (Singapore), Asia Pacific (Sydney), and South America (San Paulo)    &#8211; ที่มา <a rel="noreferrer noopener" href="https://aws.amazon.com/th/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/" target="_blank">aws.amazon.com</a> </p>



<p><strong>Update 27 Sep 2019</strong> &#8211;  ทาง AWS ได้แก้ไขปัญหาเรื่อง Cold Start เนื่องจากใช้ VPC แล้ว ซึ่งมีผลกับ Region ดังนี้  US East (Ohio), EU (Frankfurt), and Asia Pacific (Tokyo)  &#8211; ที่มา <a rel="noreferrer noopener" aria-label="aws.amazon.com (opens in a new tab)" href="https://aws.amazon.com/th/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/" target="_blank">aws.amazon.com</a></p>



<p style="text-align:center">&#8230;</p>



<p>คำแนะนำจาก <a rel="noreferrer noopener" aria-label="theburningmonk.com (opens in a new tab)" href="https://theburningmonk.com/2018/01/im-afraid-youre-thinking-about-aws-lambda-cold-starts-all-wrong/" target="_blank">theburningmonk.com</a> บอกว่า ควรหลีกเลี่ยง ถ้าไม่จำเป็น เพราะการใช้ VPC มันจะกำหนดให้ Lambda ต้องสร้าง ENIs ขึ้นมา (Elastic Network Interface) เพื่อใช้คุยกันภายใน VPC และในเว็บไซต์บอกว่า กระบวนการนี้มันจะทำให้เพิ่มเวลา Cold Start อีกประมาณ  10 วินาที!!</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1632" height="864" src="https://myifew.com/wp-content/uploads/2019/05/vpc-novpc-cold-start.png" alt="" class="wp-image-5406"/><figcaption>เทียบเวลาการเปิดใช้งาน AWS Lambda ตัวเดียวกัน แบบไม่มี VPC และมี VPC (รูปอ้างอิงจาก <a href="https://mikhail.io/serverless/coldstarts/aws/" target="_blank" rel="noreferrer noopener" aria-label="mikhail.io (opens in a new tab)">mikhail.io</a>)</figcaption></figure>



<p>และในเว็บไซต์ <a href="https://epsagon.com/blog/aws-lambda-programming-language-comparison/">epsagon.com</a> ได้ให้ข้อมูลเพิ่มเติมว่า การกำหนด Memory ที่มากขึ้น ใน AWS Lambda ของภาษา C# , Java มันจะทำการสร้าง ENIs เพิ่มจำนวนขึ้นด้วย แม้ว่า AWS Lambda จะมีกระบวนการที่นำ ENIs เก่ามาใช้ใหม่ได้ก็ตาม โดยสังเกตได้จากสูตรที่ชี้แจงไว้ใน AWS Document</p>



<p>ดังนั้น สรุปได้คือ ถ้าเราใช้ VPS และยิ่งเพิ่ม Memory Allocate เข้าไปในตัว AWS Lambda มันก็จะยิ่งเพิ่ม ENIs ให้เหมาะสมกัน และจะส่งผลกับ Cold Start ที่ใช้เวลามากขึ้นตามไปด้วย</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1586" height="828" src="https://myifew.com/wp-content/uploads/2019/05/memory-related-enis.png" alt="" class="wp-image-5404"/><figcaption>การเพิ่ม Memory เพื่อรองรับ Capacity ที่มากขึ้น เท่ากับ  AWS Lambda จะต้องเพิ่มจำนวนการสร้าง ENIs ตามไปด้วย (รูปอ้างอิงจาก <a href="https://docs.aws.amazon.com/lambda/latest/dg/vpc.html">https://docs.aws.amazon.com/lambda/latest/dg/vpc.html</a>)<br></figcaption></figure>



<p>ปล. มีข่าวดีแว่วๆมา อ้างอิงจาก <a href="https://twitter.com/jeremy_daly/status/1068272580556087296">@jeremy_daly</a> ที่เข้าร่วมงาน AWS re:Invent ว่า AWS มีแผนจะแก้ปัญหาเรื่องนี้ภายในปี 2019 นี่แหละครับ</p>



<h2 class="wp-block-heading">9. เลือกภาษาเพื่อใช้ทำ Serverless ที่เหมาะสม</h2>



<p>ข้อสุดท้าย ถ้าไม่ผูกติดกับภาษาในการพัฒนา Serverless แนะนำให้ใช้ตระกูล Scripting Language แทน Compiled language จะช่วยแก้ปัญหา Cold Start ได้อย่างมาก</p>



<p>ลองดูจากสถิติของเว็บไซต์ <a rel="noreferrer noopener" href="https://mikhail.io/serverless/coldstarts/aws/" target="_blank">mikhail.io</a></p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1624" height="864" src="https://myifew.com/wp-content/uploads/2019/05/cold-start-per-language.png" alt="" class="wp-image-5408"/><figcaption>เทียบเวลาการเกิด Cold Start ในแต่ละภาษา (รูปอ้างอิงจาก <a rel="noreferrer noopener" href="https://mikhail.io/serverless/coldstarts/aws/" target="_blank">mikhail.io</a>)</figcaption></figure>



<p>พวก JavaScript, Python, Go, Java, และ Ruby จะทำงานเสร็จแถวๆ 500ms หรือไม่เกิน 800ms แต่สำหรับ C# จะใช้เวลาตั้งแต่ 0.8 จนถึง 5 วินาที เลยทีเดียว</p>



<p>ตัวอย่างสถิติอีกสักแห่ง จากเว็บไซต์ <a href="https://read.acloud.guru/does-coding-language-memory-or-package-size-affect-cold-starts-of-aws-lambda-a15e26d12c76">read.acloud.guru</a></p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1796" height="1068" src="https://myifew.com/wp-content/uploads/2019/05/compare-cold-start-by-language.png" alt="" class="wp-image-5412"/><figcaption>เวลาเกิด Cold Start โดยเปรียบเทียบภาษาที่ใช้กับการจัดสรร Memory (รูปอ้างอิงจาก <a href="https://read.acloud.guru/does-coding-language-memory-or-package-size-affect-cold-starts-of-aws-lambda-a15e26d12c76">read.acloud.guru</a>)</figcaption></figure>



<p>สถิติจากเว็บไซต์นี้ ได้ผลใกล้เคียงกับที่แรกคือ พวก JavaScript, Python ยังคงทำงานได้เร็วแถวๆ 500ms ส่วน Java และ C# ใช้เวลา Cold Start นานมาก</p>



<p>และให้ข้อมูลเพิ่มเติมนิดนึงครับว่า แม้จะเปลี่ยนผู้ให้บริการ ก็ได้ผลไม่ต่างกัน ถ้าหากใครคิดว่า ใช้ C# บน Azure Function น่าจะเร็วกว่า AWS Lambda นั้น คิดผิดนะคร้าบบบ..</p>



<figure class="wp-block-image"><img loading="lazy" decoding="async" width="1209" height="837" src="https://myifew.com/wp-content/uploads/2019/05/coldstart-per-language-vendor.png" alt="" class="wp-image-5413"/><figcaption>เทียบเวลาการเกิด Cold Start ในแต่ละภาษา และแต่ละผู้ให้บริการ (รูปอ้างอิงจาก <a rel="noreferrer noopener" href="https://mikhail.io/serverless/coldstarts/aws/" target="_blank">mikhail.io</a>)</figcaption></figure>



<p>ให้สังเกตว่า C# บน Azure Function ทำงานได้ช้ากว่า AWS Lambda ประมาณ 500ms &#8211; 1 วินาที เลยทีเดียว</p>



<p>อ่านข้อมูลการเปรียบเทียบเพิ่มเติมได้ที่นี่</p>



<ul class="wp-block-list"><li><a rel="noreferrer noopener" aria-label="Comparing AWS Lambda performance of Node.js, Python, Java, C# and Go (opens in a new tab)" href="https://read.acloud.guru/comparing-aws-lambda-performance-of-node-js-python-java-c-and-go-29c1163c2581" target="_blank">Comparing AWS Lambda performance of Node.js, Python, Java, C# and Go</a></li><li><a href="https://read.acloud.guru/does-coding-language-memory-or-package-size-affect-cold-starts-of-aws-lambda-a15e26d12c76" target="_blank" rel="noreferrer noopener" aria-label="How does language, memory and package size affect cold starts of AWS Lambda? (opens in a new tab)">How does language, memory and package size affect cold starts of AWS Lambda?</a></li></ul>



<h2 class="wp-block-heading">สรุป</h2>



<p>ตอนนี้เราก็คงต้องต่อสู่กับ Cold Start กันต่อไป เพราะเราไม่สามารถแก้ไขอะไรมันได้มากนัก ส่วนผู้ให้บริการเองอย่าง Amazon, Azure, Google Cloud ก็รู้ปัญหานี้เช่นกัน และพยายามปรับปรุงมันให้ดีขึ้นอยู่เรื่อยๆ แต่ที่สำคัญ ก่อนที่เราจะตัดสินใจใช้ Serverless เราต้องคิดให้ดีก่อนว่าเหมาะสมกับงานของเราแล้วหรือยัง</p>



<p>&#8212;</p>



<p>ที่มาภาพหน้าปก <a href="http://www.drunktiki.com/2016/08/17/yoda-pug/yoda-pug-jpg/">http://www.drunktiki.com/2016/08/17/yoda-pug/yoda-pug-jpg/</a></p>
]]></content:encoded>
					
					<wfw:commentRss>https://myifew.com/5386/9-ways-to-fighting-with-cold-start-in-serverless/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
	</channel>
</rss>
