เมื่อไม่นานมานี้ (ในฤดูใบไม้ร่วงปี 2016) ในระหว่างการพัฒนาเวอร์ชันถัดไปของแพลตฟอร์มเทคโนโลยี 1C:Enterprise คำถามเกิดขึ้นภายในทีมพัฒนาเกี่ยวกับการสนับสนุนมาตรฐานใหม่
สำหรับผู้ที่ไม่ทราบ 1C:Enterprise เป็นสภาพแวดล้อมสำหรับการพัฒนาอย่างรวดเร็วของแอปพลิเคชันธุรกิจข้ามแพลตฟอร์มและรันไทม์สำหรับการดำเนินการบนระบบปฏิบัติการและ DBMS ที่แตกต่างกัน โดยทั่วไป ผลิตภัณฑ์ประกอบด้วย:
คลัสเตอร์แอปพลิเคชันเซิร์ฟเวอร์ , ทำงานบน Windows และ Linuxลูกค้า ซึ่งทำงานกับเซิร์ฟเวอร์ผ่าน http หรือโปรโตคอลไบนารี่ของตัวเอง ทำงานบน Windows, Linux, macOSเว็บไคลเอนต์ , ทำงานใน Chrome, Internet Explorer, Microsoft Edge, Firefox, เบราว์เซอร์ Safari (เขียนด้วย JavaScript)- การพัฒนาสภาพแวดล้อม (
ตัวกำหนดค่า ) ใช้งานได้บน Windows, Linux, macOS เครื่องมือบริหาร แอปพลิเคชันเซิร์ฟเวอร์ ทำงานบน Windows, Linux, macOSลูกค้ามือถือ ซึ่งเชื่อมต่อกับเซิร์ฟเวอร์ผ่าน http(s) ทำงานบนอุปกรณ์มือถือที่ใช้ Android, iOS, Windowsแพลตฟอร์มมือถือ — เฟรมเวิร์กสำหรับการสร้างแอปพลิเคชันมือถือออฟไลน์ที่มีความสามารถในการซิงโครไนซ์ทำงานบน Android, iOS, Windows- การพัฒนาสภาพแวดล้อม
1C: เครื่องมือพัฒนาองค์กร เขียนด้วยภาษาจาวา - เซิร์ฟเวอร์
ระบบปฏิสัมพันธ์
เราพยายามเขียนโค้ดเดียวกันสำหรับระบบปฏิบัติการที่แตกต่างกันให้มากที่สุด - ฐานรหัสเซิร์ฟเวอร์เป็นเรื่องธรรมดา 99% ฐานรหัสไคลเอนต์อยู่ที่ประมาณ 95% แพลตฟอร์มเทคโนโลยี 1C:Enterprise เขียนด้วยภาษา C++ เป็นหลัก และลักษณะโค้ดโดยประมาณได้รับด้านล่าง:
- รหัส C++ 10 ล้านบรรทัด
- 14 ไฟล์
- 60 คลาส
- ครึ่งล้านวิธี
และเนื้อหาทั้งหมดนี้ต้องแปลเป็น C++14 วันนี้เราจะมาเล่าให้คุณฟังว่าเราทำเช่นนี้ได้อย่างไรและพบอะไรบ้างในกระบวนการนี้
ข้อจำกัดความรับผิดชอบ
ทุกสิ่งที่เขียนด้านล่างเกี่ยวกับการทำงานที่ช้า/เร็ว (ไม่ใช่) การใช้หน่วยความจำขนาดใหญ่โดยการใช้งานคลาสมาตรฐานในไลบรารีต่างๆ มีความหมายอย่างหนึ่ง: นี่เป็นเรื่องจริงสำหรับสหรัฐอเมริกา ค่อนข้างเป็นไปได้ที่การใช้งานแบบมาตรฐานจะเหมาะสมที่สุดสำหรับงานของคุณ เราเริ่มต้นจากงานของเราเอง: เรานำข้อมูลที่เป็นปกติสำหรับลูกค้าของเรา รันสถานการณ์ทั่วไปกับพวกเขา ดูที่ประสิทธิภาพ จำนวนหน่วยความจำที่ใช้ ฯลฯ และวิเคราะห์ว่าเราและลูกค้าของเราพอใจกับผลลัพธ์ดังกล่าวหรือไม่ . และพวกเขาก็ทำหน้าที่ขึ้นอยู่กับ
สิ่งที่เรามี
ในตอนแรก เราเขียนโค้ดสำหรับแพลตฟอร์ม 1C:Enterprise 8 โดยใช้ Microsoft Visual Studio โปรเจ็กต์นี้เริ่มต้นในต้นปี 2000 และเรามีเวอร์ชันสำหรับ Windows เท่านั้น โดยปกติแล้วตั้งแต่นั้นมาโค้ดก็ได้รับการพัฒนาอย่างแข็งขัน กลไกหลายอย่างได้ถูกเขียนใหม่ทั้งหมด แต่โค้ดนี้เขียนขึ้นตามมาตรฐานปี 1998 และตัวอย่างเช่น วงเล็บเหลี่ยมของเราถูกคั่นด้วยช่องว่างเพื่อให้การคอมไพล์สำเร็จ เช่นนี้
vector<vector<int> > IntV;
ในปี 2006 ด้วยการเปิดตัวแพลตฟอร์มเวอร์ชัน 8.1 เราได้เริ่มสนับสนุน Linux และเปลี่ยนไปใช้ไลบรารีมาตรฐานของบุคคลที่สาม
สตริงของเรามีพื้นฐานมาจากแนวคิดการปรับสตริงให้เหมาะสมซึ่งแสดงออกมาในช่วงต้นทศวรรษ 2000
สายการผลิตของเราใช้เทคโนโลยีการปรับให้เหมาะสมหลักสองประการ:
- สำหรับค่าแบบสั้น จะใช้บัฟเฟอร์ภายในในอ็อบเจ็กต์สตริงเอง (ไม่ต้องการการจัดสรรหน่วยความจำเพิ่มเติม)
- สำหรับอย่างอื่นทั้งหมดจะใช้กลไก
คัดลอกเมื่อเขียน . ค่าสตริงจะถูกเก็บไว้ในที่เดียว และใช้ตัวนับอ้างอิงระหว่างการกำหนด/การแก้ไข
เพื่อเร่งการคอมไพล์แพลตฟอร์ม เราได้แยกการใช้งานสตรีมออกจากตัวแปร STLPort ของเรา (ซึ่งเราไม่ได้ใช้) ซึ่งทำให้การคอมไพล์เร็วขึ้นประมาณ 20% ต่อมาเราจึงต้องใช้ประโยชน์อย่างจำกัด
วิธีที่สาม
เมื่อเปลี่ยนไปใช้มาตรฐาน C++14 เราได้พิจารณาตัวเลือกต่อไปนี้:
- อัปเกรด STLPort ที่เราแก้ไขเป็นมาตรฐาน C++14 ทางเลือกนั้นยากมากเพราะว่า... การสนับสนุน STLPort ถูกยกเลิกในปี 2010 และเราจะต้องสร้างโค้ดทั้งหมดด้วยตัวเอง
- เปลี่ยนไปใช้การใช้งาน STL อื่นที่เข้ากันได้กับ C ++ 14 เป็นที่พึงปรารถนาอย่างยิ่งว่าการใช้งานนี้มีไว้สำหรับ Windows และ Linux
- เมื่อทำการคอมไพล์สำหรับแต่ละ OS ให้ใช้ไลบรารีที่สร้างไว้ในคอมไพเลอร์ที่เกี่ยวข้อง
ตัวเลือกแรกถูกปฏิเสธทันทีเนื่องจากมีงานมากเกินไป
เราคิดถึงตัวเลือกที่สองมาระยะหนึ่งแล้ว ถือเป็นผู้สมัคร
และเราเลือกวิธีที่สาม
การเปลี่ยนแปลง
ดังนั้นเราจึงต้องแทนที่การใช้ STLPort ด้วยไลบรารีของคอมไพเลอร์ที่เกี่ยวข้อง (Visual Studio 2015 สำหรับ Windows, gcc 7 สำหรับ Linux, clang 8 สำหรับ macOS)
โชคดีที่โค้ดของเราเขียนตามหลักเกณฑ์เป็นหลักและไม่ได้ใช้กลอุบายที่ชาญฉลาดทุกประเภท ดังนั้นการโยกย้ายไปยังไลบรารีใหม่จึงดำเนินไปค่อนข้างราบรื่น ด้วยความช่วยเหลือของสคริปต์ที่แทนที่ชื่อประเภท คลาส เนมสเปซ และรวมไว้ในแหล่งที่มา ไฟล์. การย้ายข้อมูลส่งผลต่อไฟล์ต้นฉบับ 10 ไฟล์ (จาก 000 ไฟล์) wchar_t ถูกแทนที่ด้วย char14_t; เราตัดสินใจยกเลิกการใช้ wchar_t เพราะ char000_t ใช้เวลา 16 ไบต์ในทุกระบบปฏิบัติการ และไม่ทำลายความเข้ากันได้ของโค้ดระหว่าง Windows และ Linux
มีการผจญภัยเล็กๆ น้อยๆ ตัวอย่างเช่น ใน STLPort ตัววนซ้ำสามารถส่งไปยังตัวชี้ไปยังองค์ประกอบโดยปริยายได้ และในบางตำแหน่งในโค้ดของเรา ก็มีการใช้สิ่งนี้ ในห้องสมุดใหม่ ไม่สามารถทำได้อีกต่อไป และต้องวิเคราะห์และเขียนข้อความเหล่านี้ใหม่ด้วยตนเอง
ดังนั้นการย้ายโค้ดจึงเสร็จสมบูรณ์ โค้ดจะถูกคอมไพล์สำหรับระบบปฏิบัติการทั้งหมด ถึงเวลาสำหรับการทดสอบ
การทดสอบหลังการเปลี่ยนแปลงพบว่าประสิทธิภาพลดลง (ในบางสถานที่มากถึง 20-30%) และการใช้หน่วยความจำเพิ่มขึ้น (สูงสุด 10-15%) เมื่อเทียบกับโค้ดเวอร์ชันเก่า โดยเฉพาะอย่างยิ่งเนื่องมาจากประสิทธิภาพที่ต่ำกว่าประสิทธิภาพของสายอักขระมาตรฐาน ดังนั้นเราจึงต้องใช้เส้นของเราเองที่ปรับเปลี่ยนเล็กน้อยอีกครั้ง
คุณลักษณะที่น่าสนใจของการใช้งานคอนเทนเนอร์ในไลบรารีแบบฝังก็ถูกเปิดเผยเช่นกัน: ว่างเปล่า (ไม่มีองค์ประกอบ) std::map และ std::set จากไลบรารีในตัวจัดสรรหน่วยความจำ และเนื่องจากคุณสมบัติการใช้งานในบางสถานที่ในโค้ดจึงมีการสร้างคอนเทนเนอร์เปล่าประเภทนี้จำนวนมาก คอนเทนเนอร์หน่วยความจำมาตรฐานได้รับการจัดสรรเพียงเล็กน้อยสำหรับองค์ประกอบรูทหนึ่งองค์ประกอบ แต่สำหรับเราสิ่งนี้กลายเป็นเรื่องสำคัญ - ในหลาย ๆ สถานการณ์ ประสิทธิภาพของเราลดลงอย่างมากและการใช้หน่วยความจำเพิ่มขึ้น (เมื่อเทียบกับ STLPort) ดังนั้นในโค้ดของเรา เราได้แทนที่คอนเทนเนอร์ทั้งสองประเภทนี้จากไลบรารีในตัวด้วยการใช้งานจาก Boost โดยที่คอนเทนเนอร์เหล่านี้ไม่มีคุณสมบัตินี้ และวิธีนี้ช่วยแก้ปัญหาเรื่องการชะลอตัวและการใช้หน่วยความจำที่เพิ่มขึ้น
ตามที่มักเกิดขึ้นหลังจากการเปลี่ยนแปลงขนาดใหญ่ในโครงการขนาดใหญ่ การวนซ้ำครั้งแรกของซอร์สโค้ดไม่ได้ผลโดยไม่มีปัญหา และโดยเฉพาะอย่างยิ่งการสนับสนุนการดีบักตัววนซ้ำในการใช้งาน Windows นั้นมีประโยชน์ เราก้าวไปข้างหน้าทีละขั้นตอน และภายในฤดูใบไม้ผลิปี 2017 (เวอร์ชัน 8.3.11 1C:Enterprise) การโยกย้ายก็เสร็จสมบูรณ์
ผลของการ
การเปลี่ยนไปใช้มาตรฐาน C++14 ใช้เวลาประมาณ 6 เดือน โดยส่วนใหญ่แล้ว นักพัฒนาหนึ่งราย (แต่มีคุณสมบัติสูงมาก) ทำงานในโครงการนี้ และในขั้นตอนสุดท้ายของตัวแทนของทีมที่รับผิดชอบในพื้นที่เฉพาะที่เข้าร่วม เช่น UI คลัสเตอร์เซิร์ฟเวอร์ เครื่องมือการพัฒนาและการดูแลระบบ ฯลฯ
การเปลี่ยนแปลงนี้ทำให้งานของเราในการโยกย้ายไปใช้เวอร์ชันมาตรฐานล่าสุดง่ายขึ้นอย่างมาก ดังนั้นเวอร์ชัน 1C:Enterprise 8.3.14 (อยู่ระหว่างการพัฒนา ซึ่งมีกำหนดวางจำหน่ายในต้นปีหน้า) จึงถูกถ่ายโอนไปยังมาตรฐานแล้ว
หลังจากการโยกย้าย นักพัฒนามีตัวเลือกเพิ่มเติม หากก่อนหน้านี้เรามี STL เวอร์ชันที่แก้ไขแล้วและเนมสเปซ std หนึ่งรายการ ตอนนี้เรามีคลาสมาตรฐานจากไลบรารีคอมไพเลอร์ในตัวในเนมสเปซ std ในเนมสเปซ stdx - บรรทัดและคอนเทนเนอร์ของเราปรับให้เหมาะสมสำหรับงานของเรา ในบูสต์ - บูสต์เวอร์ชันล่าสุด และนักพัฒนาใช้คลาสเหล่านั้นที่เหมาะสมที่สุดเพื่อแก้ไขปัญหาของเขา
การใช้งานตัวสร้างการย้ายแบบ "ดั้งเดิม" ยังช่วยในการพัฒนา (
บินในครีม
บางทีผลลัพธ์ที่ไม่พึงประสงค์ที่สุด (แต่ไม่สำคัญ) ของการย้ายถิ่นก็คือ เรากำลังเผชิญกับปริมาณที่เพิ่มขึ้น
ที่มา: will.com