การจัดหาดอทช้ากว่าการอ่านเนื้อหาไฟล์หรือไม่?


13

ฉันได้เขียนโมดูล PowerShell ซึ่งดึงคำจำกัดความของฟังก์ชั่นจากไฟล์ต้นฉบับต่างๆ (เช่นหนึ่งไฟล์. ps1 ต่อฟังก์ชั่น) สิ่งนี้ทำให้เรา (ในฐานะทีม) สามารถทำงานกับฟังก์ชั่นที่แตกต่างกันในแบบคู่ขนาน โมดูล (ไฟล์. psm1) รับรายการไฟล์. ps1 ที่มีอยู่ ...

$Functions = Get-ChildItem -Path $FunctionPath *.ps1

... จากนั้นวนซ้ำในรายการและดึงในการกำหนดฟังก์ชั่นแต่ละรายการผ่านการจัดหาดอท:

foreach($Function in $Functions) {
  . $Function.Fullname                                     # Can be slow
}

ปัญหา:เราสังเกตเห็นว่าความเร็วในการทำให้สมบูรณ์อาจแตกต่างกันมากตั้งแต่ 10 ถึง 180 วินาทีสำหรับไฟล์ต้นฉบับประมาณ 50 ไฟล์ขึ้นอยู่กับเครื่องที่เราทดสอบ เราไม่สามารถอธิบายความแปรผันของเวลาที่หลากหลายและเชื่อว่าเราควบคุมตัวแปรเช่นประเภทเครื่อง, OS, บัญชีผู้ใช้, สิทธิ์ผู้ดูแลระบบ, โปรไฟล์ PS, รุ่น PS ฯลฯ เวลาที่ใช้อาจแตกต่างกันไปในโฮสต์เดียวกัน ผู้ใช้จากวันหนึ่งไปยังวันถัดไป

เราสงสัยว่านี่เป็นปัญหาของการเข้าถึงดิสก์และทดสอบว่าเราสามารถอ่านจากดิสก์ได้เร็วแค่ไหน ปรากฎว่าการทำงานGet-Contentกับไฟล์ทั้งหมดนั้นเร็วมากซึ่งเราได้ใช้ประโยชน์จากการแก้ไขปัญหา:

foreach($Function in $Functions) {
  Invoke-Expression (Get-Content $Function.Fullname -Raw)  # Is quick
}

ทำไมการเพิ่มฟังก์ชั่นเหล่านี้ผ่าน dot-sourcing จึงช้ากว่าการอ่านและการรันเนื้อหาไฟล์?

คำตอบ:


17

การตั้งค่าวิทยาศาสตร์

ก่อนอื่นสคริปต์บางอย่างเพื่อช่วยเราทดสอบสิ่งนี้ สิ่งนี้สร้างไฟล์สคริปต์ 2000 ไฟล์โดยแต่ละไฟล์มีฟังก์ชั่นขนาดเล็ก:

1..2000 | % { "Function Test$_(`$someArg) { Return `$someArg * $_ }" > "test$_.ps1" }

นั่นควรจะเพียงพอที่จะทำให้ค่าใช้จ่ายในการเริ่มต้นระบบปกติไม่สำคัญมากนัก คุณสามารถเพิ่มมากขึ้นถ้าคุณต้องการ สิ่งนี้โหลดพวกเขาทั้งหมดโดยใช้การจัดหาดอท:

dir test*.ps1 | % {. $_.FullName}

สิ่งนี้โหลดพวกเขาทั้งหมดโดยการอ่านเนื้อหาก่อน:

dir test*.ps1 | % {iex (gc $_.FullName -Raw)}

ตอนนี้เราต้องทำการตรวจสอบอย่างจริงจังว่า PowerShell ทำงานอย่างไร ฉันชอบJetBrains dotPeekสำหรับเครื่องถอดรหัส หากคุณเคยพยายามที่จะฝัง PowerShell ในการประยุกต์สุทธิSystem.Management.Automationคุณจะพบว่าการชุมนุมที่มีมากที่สุดของสิ่งที่เกี่ยวข้องคือ ถอดรหัสที่หนึ่งในโครงการและ PDB

เพื่อดูว่าเวลาทั้งหมดนี้ถูกใช้ไปที่ไหนเราจะใช้ Profiler ฉันชอบสิ่งที่สร้างขึ้นใน Visual Studio มันมากง่ายต่อการใช้งาน เพิ่มโฟลเดอร์ที่มี PDB ไปสถานที่สัญลักษณ์ ตอนนี้เราสามารถทำการทำโปรไฟล์ของอินสแตนซ์ PowerShell ที่เพิ่งเรียกใช้หนึ่งในสคริปต์ทดสอบ (ตั้งค่าพารามิเตอร์บรรทัดคำสั่งเพื่อใช้-Fileกับพา ธ แบบเต็มของสคริปต์แรกเพื่อลองตั้งค่าตำแหน่งเริ่มต้นไปยังโฟลเดอร์ที่มีสคริปต์เล็ก ๆ ทั้งหมด) เมื่อเสร็จแล้วให้เปิดคุณสมบัติบนpowershell.exeรายการภายใต้เป้าหมายและเปลี่ยน อาร์กิวเมนต์ที่ใช้สคริปต์อื่น จากนั้นคลิกขวาที่รายการสูงสุดใน Performance Explorer แล้วเลือกเริ่มการทำโปรไฟล์. Profiler ทำงานอีกครั้งโดยใช้สคริปต์อื่น ตอนนี้เราสามารถเปรียบเทียบ ให้แน่ใจว่าคุณคลิก "แสดงรหัสทั้งหมด" ถ้าได้รับตัวเลือก; สำหรับฉันที่แสดงในพื้นที่การแจ้งเตือนในมุมมองสรุปของรายงานการทำโปรไฟล์ตัวอย่าง

ผลลัพธ์ที่ได้เข้ามา

บนเครื่องของฉันGet-Contentเวอร์ชันใช้เวลา 9 วินาทีในการผ่านไฟล์สคริปต์ 2000 ฟังก์ชั่นที่สำคัญของ "เส้นทางลัด" คือ:

Microsoft.PowerShell.Commands.GetContentCommand.ProcessRecord
Microsoft.PowerShell.Commands.InvokeExpressionCommand.ProcessRecord

มันสมเหตุสมผลมาก: เราต้องรอGet-Contentอ่านเนื้อหาจากดิสก์และเราต้องรอInvoke-Expressionเพื่อใช้ประโยชน์จากเนื้อหาเหล่านั้น

ในรุ่น dot-source เครื่องของฉันใช้เวลา 15 วินาทีในการทำงานกับไฟล์เหล่านั้น ในครั้งนี้ฟังก์ชั่นบนเส้นทางที่ร้อนเป็นวิธีการพื้นเมือง:

WinVerifyTrust
CodeAuthzFullyQualifyFilename

อันที่สองดูเหมือนจะไม่มีเอกสาร แต่WinVerifyTrust"ทำการตรวจสอบความน่าเชื่อถือกับวัตถุที่ระบุ" มันเกี่ยวกับที่คลุมเครือที่สุดเท่าที่คุณจะได้รับ แต่ในคำอื่น ๆ ฟังก์ชั่นนั้นจะตรวจสอบความถูกต้องของทรัพยากรที่กำหนดโดยใช้ผู้ให้บริการที่กำหนด โปรดทราบว่าผมยังไม่ได้เปิดใช้งานการรักษาความปลอดภัยสิ่งใด ๆ แฟนซีสำหรับ PowerShell Unrestrictedและนโยบายการดำเนินการสคริปต์ของฉันคือ

นั่นหมายถึงอะไร

กล่าวโดยย่อคือคุณกำลังรอให้แต่ละไฟล์ได้รับการยืนยันในบางวิธีอาจตรวจสอบลายเซ็นแม้ว่าจะไม่จำเป็นเมื่อคุณไม่ จำกัด สคริปต์ที่อนุญาตให้เรียกใช้ เมื่อคุณgcและiexเนื้อหาแล้วมันเหมือนกับว่าคุณได้พิมพ์ฟังก์ชั่นที่คอนโซลดังนั้นจึงไม่มีทรัพยากรที่จะตรวจสอบ


2
เบ็นขอบคุณสำหรับคำตอบที่ยอดเยี่ยมนี้ ประทับใจที่คุณไปไกลถึงการรวบรวมซึ่งเป็นขั้นตอนเกินกว่าสิ่งที่ฉันได้ลอง ฉันจะดูว่ามีวิธีใดที่ฉันสามารถทำตามวิธีการทดสอบของคุณในหนึ่งในเครื่องที่ปัญหานี้รุนแรงที่สุด อาจใช้เวลานานดังนั้นอย่ากลั้นลมหายใจของคุณ!
Charlie Joynt
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.