Devahoy Logo
PublishedAt

CLI

ทำไม ZSH ของเราช้าจัง? + ทำให้เร็วขึ้นได้มั้ย

ทำไม ZSH ของเราช้าจัง? + ทำให้เร็วขึ้นได้มั้ย

สวัสดีครับ เนื่องจากว่าช่วงนี้ผมรู้สึกว่า เวลาเปิด iTerm2 หรือ Terminal ขึ้นมา มันเริ่มช้าๆ หน่วงๆ บ้างเวลาพิมพ์คำสั่ง (ไม่นับ ตอนเข้า tmux ทีแรก ก็สงสัยว่าอาจจะเพราะ tmux) สงสัยเป็นเพราะลงพวก plugins ของ zsh เยอะแน่ๆเลย

ก็เลยลองไปนั่งค้นๆ หาข้อมูลมาว่า มีวิธีการไหนที่เราจะ debugginer หรือ profiling ดูว่า zsh ของเรามันช้าตอนไหน ช้าช่วงไหน มี plugins หรือ config อะไรที่ทำให้มันช้า ก็โชคดีครับ มีบล็อกของหลายๆ คนเขียนไว้ ผมก็เลยเอามาปรับใช้ และทำให้ zsh ผมเร็วขึ้นเยอะเลย

บทความที่ผมอ่าน และลองทำตามคือ

สิ่งที่ได้เรียนรู้คือ

วิธีที่ใช้ดูว่า shell ใช้เวลาโหลดเท่าไหร่ ก็คือใช้คำสั่ง time ครับ ตัวอย่าง ในบทความ เค้าใช้วิธีการวน loop แล้วสั่ง time 10 รอบครับ อย่างของผม คือ

Terminal window
for i in $(seq 1 10); do /usr/bin/time $SHELL -i -c exit; done

ผลลัพธ์ที่ได้ เกือบ 1 วินาที ถือว่าช้าสำหรับผมนะ แต่เห็นหลายๆคน เค้า 2-3s เลย นี่แค่ 1s ก็รู้สึกว่ามันช้าละ (แอบสงสัย ว่าช้ากว่าตอนที่ลงพวก Powerlevel10k, Autocomplete, suggestion, hyperline ซะอีก)

Terminal window
0.95 real 0.58 user 0.33 sys
0.95 real 0.58 user 0.33 sys
0.94 real 0.58 user 0.32 sys
0.93 real 0.58 user 0.31 sys
0.94 real 0.58 user 0.32 sys
0.92 real 0.57 user 0.31 sys
0.94 real 0.58 user 0.32 sys
0.94 real 0.58 user 0.32 sys
0.96 real 0.59 user 0.32 sys
0.95 real 0.58 user 0.32 sys

เทียบกับ bash ปกติ เวลาต่างกันมาก

Terminal window
0.04 real 0.02 user 0.03 sys
0.04 real 0.02 user 0.03 sys
0.03 real 0.02 user 0.03 sys
0.03 real 0.02 user 0.02 sys
0.03 real 0.02 user 0.02 sys
0.03 real 0.02 user 0.02 sys
0.03 real 0.02 user 0.02 sys
0.03 real 0.02 user 0.03 sys
0.03 real 0.02 user 0.03 sys
0.03 real 0.02 user 0.02 sys

ลองมาย้อนกลับมาดู zsh ของตัวเอง แล้วลองคิด ว่าเรามีอะไรบ้างนะ ที่น่าจะช้า?

  • ผมใช้ oh-my-zsh และมี plugins บ้างบางส่วน
  • plugins ที่ช้า คือ auto suggestion / completion จำได้เมื่อก่อน ลงไว้ แล้วรู้สึกช้า เลยเอาออก คิดว่าไม่ได้จำเป็นมาก
  • ใช้ starship เป็น Prompt
  • ลง Powerline10k ปรับ theme ปรับอะไรพวกนี้
  • มีปรับ alias / export ค่า (ซึ่งที่คิด ไม่น่าจะมีผลอะไร)
  • มี ASDF ซึ่งเอาจัดการพวก Package manager ต่างๆ (ในบทความ nvm ทำให้ zsh ช้า เลยคิดว่าสงสัยเกี่ยวแน่เลย)

เราสามารถใช้คำสั่ง

Terminal window
zsh -xv
  • -x - คือ xtrace โหมด
  • -v - คือ verbose ผลลัพธ์นั่นเอง

แต่สิ่งที่ได้คือ แน่นอน มันละเอียดบอกทุกอย่าง แต่ดูแทบไม่ออก ว่าอันไหนช้า รู้แค่ว่ามัน load อะไรบ้างเท่านั้น

Profililng

ในเมื่อผมใช้ oh-my-zsh ข้อดีคือ มันมี built-in zsh/zprof มาให้เรา ทำให้ผมสามารถดูว่า zsh load อะไรบ้าง มีอะไรช้า ตรงไหนช้า ตรงไหนเร็ว เทียบกับ time ที่ดูได้แค่เวลารวม

วิธีการก็ง่ายๆ เลย เพิ่ม

Terminal window
zmodload zsh/zprof

ไปไว้ที่บนสุดของไฟล์ ~/.zshrc ของเรา นั่นเอง ก็ source ~/.zshrc ทีนึง เพื่อ reload

ทีนี้เราก็สามารถใช้คำสั่ง

Terminal window
zprof

ก็จะเห็นรายละเอียดแต่ละ plugins หรือแต่ละ process เลย จะได้รู้แล้ว ใครคือผู้ร้าย ที่ต้องกำจัดทิ้ง :)

สิ่งที่ผมแก้ปัญหาคือ ผมค่อยๆ เริ่มจาก เอาตัว /.zshrc.pre-oh-my-zsh ซึ่งเป็น backup ก่อนลง oh my zsh มาใช้ แล้วก็ค่อยๆ ไล่ใส่ plugins ไล่ใส่ config ลงไป สุดท้าย ก็ได้ผลที่ต้องการครับ อย่างน้อย ก็ระดับ 0.1s -0.15s ก็พอรับได้ครับ แม้จะไม่เท่าตัว bash/zsh เพียวๆ

สิ่งที่แปลกใจคือ บรรทัดนี้ ช้าสุดๆ (เพราะผมอยากลง Erlang 22.0.7 แล้วมีปัญหาบน Mac OS ก็เลยทำตามทบความนี้ https://github.com/kerl/kerl/issues/320)

Terminal window
export KERL_CONFIGURE_OPTIONS="--without-javac --with-ssl=$(brew --prefix openssl)"

พอเอาบรรทัดนี้ออก shell เร็วขึ้นมากเลย เลยไม่แน่ใจว่าทุกๆ ครั้งที่ shell รัน ตัว Kernel มันไปเรียก config options นี่รึเปล่าไม่แน่ใจ

สรุป

เมื่อก่อน เราจะชอบมาก เวลา Terminal / Shell มี effect หรือ Prompt เท่ๆ สีสวยๆ กดหรือพิมพ์มี gimmick เช่น power มีพลุ หรือโชว์เวลา โชว์ Battery โชว์อะไรเต็ม Terminal ไปหมด เจออะไรก็อยากลง augo suggestion / short cut จนทำให้สุดท้ายตัว config เรามันโหลดช้า

ลองๆเล่นๆ ปรับแต่ง zsh เวอร์ชั่นใหม่ ดูหลายๆ แบบ แล้วเลือกที่เหมาะสม ทั้ง features ที่ใช้ และความเร็วไม่ช้า เช่น

  • Pure - ลองใช้ดูก่อน ไม่รู้ดีมั้ย
  • เอา oh my zsh ออก และใช้แต่บาง feature ส่วน auto suggestion ก็ลงแยก, plugin ที่มี alias จริงๆ ใช้แค่ git อย่างเดียว ก็ทำ alias เอง ใช้อยู่ไม่ถึง 10 คำสั่งเลย
  • ลอง starship เห็นใน profiling ใช้เวลาโหลดนาน แต่พอ disabled/enable ต่างกัน 0.3s เลยใส่ไว้ก่อน
  • ลองสลับใช้ minimal ที่สุด ขาดอะไร ก็ค่อยๆ ใส่ แต่จะไม่ใส่มาเกิน เพื่อเผื่อใช้

สุดท้าย ผมว่า zsh / shell ของเรา เลือกใช้เครื่องมือ เท่าที่จำเป็น เท่าที่ใช้ดีกว่า ไม่ควรใส่ทุกอย่าง มาเผื่อไว้ใช้ แล้วทำให้มันช้า มันโหลดโดยไม่จำเป็น เสียเวลาเปล่าๆ ฮ่าๆ

สวัสดี 💻

เผื่อหลายๆ คนอยากลอง zsh หรือพวก PowerLevel10k หรือ Startshp / Hyper ก็ลองดู links ด้านล่างได้เลยครับ

Authors
avatar

Chai Phonbopit

เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust