บทช่วยสอนการเพิ่มประสิทธิภาพโค้ด Delphi:
การเพิ่มประสิทธิภาพสตริง
Delphi มีสตริงสามประเภท: สตริงแบบสั้น (string[n], n=1..255) พื้นที่เก็บข้อมูลได้รับการจัดสรรแบบคงที่ และขนาดถูกกำหนด ณ เวลาคอมไพล์ ซึ่งสืบทอดมาจาก bp สำหรับ ประเภทของ dos; character array (pchar) มีไว้สำหรับความเข้ากันได้กับ API ต่างๆ เป็นหลัก ซึ่งปรากฏใน bp7 และตอนนี้มีการใช้กันอย่างแพร่หลายมากขึ้นใน Delphi สตริงอักขระแบบยาว (การตอบรับ) เป็นเอกลักษณ์เฉพาะของ Delphi พื้นที่จัดเก็บข้อมูลได้รับการจัดสรรแบบไดนามิก ณ รันไทม์ ซึ่งมีความยืดหยุ่นมากที่สุดและเสี่ยงต่อการละเมิดมากที่สุด
ประเภทสตริงเริ่มต้นของ Delphi AnsiString จะถูกเตรียมใช้งานโดยอัตโนมัติให้ว่างโดยไม่ต้องเริ่มต้นซ้ำ รหัสต่อไปนี้:
Delphi มีสตริงสามประเภท: สตริงแบบสั้น (string[n], n=1..255) พื้นที่เก็บข้อมูลได้รับการจัดสรรแบบคงที่ และขนาดถูกกำหนด ณ เวลาคอมไพล์ ซึ่งสืบทอดมาจาก bp สำหรับ ประเภทของ dos; character array (pchar) มีไว้สำหรับความเข้ากันได้กับ API ต่างๆ เป็นหลัก ซึ่งปรากฏใน bp7 และตอนนี้มีการใช้กันอย่างแพร่หลายมากขึ้นใน Delphi สตริงอักขระแบบยาว (การตอบรับ) เป็นเอกลักษณ์เฉพาะของ Delphi พื้นที่จัดเก็บข้อมูลได้รับการจัดสรรแบบไดนามิก ณ รันไทม์ ซึ่งมีความยืดหยุ่นมากที่สุดและเสี่ยงต่อการละเมิดมากที่สุด
vars:สตริง;
เริ่ม
ส:=;
-
จบ;
s:=; ไม่จำเป็น แต่เป็นที่น่าสังเกตว่าสิ่งนี้ไม่มีผลกระทบต่อผลลัพธ์ของค่าส่งคืนของฟังก์ชัน โดยทั่วไปแล้ว การส่งผ่านอาร์กิวเมนต์ var จะเร็วกว่าการส่งกลับค่าสตริง
การใช้ SetLength เพื่อจัดสรรสตริงแบบยาวล่วงหน้า (AnsiString) เพื่อจัดสรรหน่วยความจำแบบไดนามิกเป็นข้อได้เปรียบที่สำคัญของ AnsiString แต่สามารถเอาชนะตัวเองได้อย่างง่ายดาย ตัวอย่างทั่วไปมีดังนี้:
s2:= ;
สำหรับ i:=2 ถึง length(s1) ทำ s2:=s2+s1[i];
ไม่ต้องพูดถึงว่าสามารถแทนที่ด้วยการลบได้ ปัญหาหลักคือ พื้นที่หน่วยความจำของ s2 ได้รับการจัดสรรซ้ำ ๆ ในลูปของตัวอย่างข้างต้นซึ่งค่อนข้างใช้เวลานาน วิธีที่ง่ายและมีประสิทธิภาพมีดังนี้:
ความยาวที่กำหนด(s2,ความยาว(s1)-1);
สำหรับ i:=2 ถึง length(s1) ทำ s2[i-1]:=s1[i];
ด้วยวิธีนี้ หน่วยความจำ s2 จะถูกจัดสรรใหม่เพียงครั้งเดียวเท่านั้น
ความปลอดภัยของเธรดของสตริงและอาร์เรย์ไดนามิก ก่อน Delphi 5 การเรียกที่ไม่ปลอดภัยสำหรับการดำเนินการกับอาร์เรย์แบบไดนามิกและสตริงแบบยาวเหล่านี้ใช้การนับการอ้างอิงเพื่อจัดการกับปัญหาที่สำคัญ อย่างไรก็ตาม ตั้งแต่ Delphi 5 การเรียกเหล่านั้นได้เปลี่ยนไปเป็นการดำเนินการบางอย่างโดยตรง นำหน้าคำแนะนำที่สำคัญด้วยคำแนะนำในการล็อคเพื่อหลีกเลี่ยงปัญหานี้ น่าเสียดายที่การปรับเปลี่ยนนี้มีราคาค่อนข้างแพง เนื่องจากคำสั่งการล็อคในโปรเซสเซอร์ Pentium II นั้นค่อนข้างใช้เวลานาน และต้องใช้เวลาประมาณ 28 รอบคำสั่งเพิ่มเติมจึงจะเสร็จสิ้นการดำเนินการนี้ ดังนั้นประสิทธิภาพโดยรวมจึงลดลงอย่างน้อยครึ่งหนึ่ง มีทางเดียวเท่านั้นที่จะแก้ไขปัญหานี้ได้ นั่นคือการแก้ไขโค้ดหลักของ delphi rtl หลังจากสำรองไฟล์ต้นฉบับแล้ว ให้แทนที่การล็อกทั้งหมดใน source/rtl/sys/system.pas ด้วย {lock} แน่นอนว่าจะต้องแทนที่ทั้งคำ ขั้นตอนต่อไปคือการลบคำสั่ง xchg ที่รวมอยู่ในไลบรารีรันไทม์ delphi4 ด้วย เนื่องจากคำสั่งนี้มีคำนำหน้าการล็อกโดยนัย xchg edx ในกระบวนการ _lstrasg และ _strlasg ใน system.pas จะต้อง จะถูกลบออก แทนที่ [eax] ด้วยรหัสต่อไปนี้:
mov ecx, [eax]
mov[eax],edx
mov edx,ecx
โอเค เสร็จแล้ว เพียงคอมไพล์และเขียนทับ system.dcu ด้วยวิธีนี้ประสิทธิภาพการดำเนินการจะสูงกว่า delphi5 ถึง 6 เท่าและสูงกว่า delphi4 ถึง 2 เท่า