ทำไมการพิมพ์ถึง stdout ช้ามาก? มันสามารถเร่งความเร็วได้หรือไม่


166

ฉันประหลาดใจ / ผิดหวังอยู่เสมอว่าต้องใช้เวลานานแค่ไหนในการส่งออกไปยังเครื่องด้วยคำสั่งพิมพ์ หลังจากการบันทึกอย่างช้า ๆ เมื่อเร็ว ๆ นี้ฉันตัดสินใจที่จะมองมันและรู้สึกประหลาดใจมากที่พบว่าเกือบตลอดเวลาที่ใช้รอเครื่องเทอร์มินัลเพื่อประมวลผลผลลัพธ์

การเขียนไปยัง stdout สามารถเร่งความเร็วได้บ้าง

ผมเขียนสคริปต์ (' print_timer.py' ที่ด้านล่างของคำถามนี้) เพื่อเปรียบเทียบระยะเวลาเมื่อเขียน 100k เส้นที่ stdout /dev/nullเพื่อไฟล์และมีการเปลี่ยนเส้นทางไปยัง นี่คือผลการจับเวลา:

$ python print_timer.py
this is a test
this is a test
<snipped 99997 lines>
this is a test
-----
timing summary (100k lines each)
-----
print                         :11.950 s
write to file (+ fsync)       : 0.122 s
print with stdout = /dev/null : 0.050 s

ว้าว. เพื่อให้แน่ใจว่าไพ ธ อนไม่ได้ทำอะไรบางอย่างอยู่เบื้องหลังเช่นตระหนักว่าฉันกำหนด stdout ใหม่ให้กับ / dev / null หรือบางอย่างฉันเปลี่ยนเส้นทางนอกสคริปต์ ...

$ python print_timer.py > /dev/null
-----
timing summary (100k lines each)
-----
print                         : 0.053 s
write to file (+fsync)        : 0.108 s
print with stdout = /dev/null : 0.045 s

ดังนั้นจึงไม่ใช่เคล็ดลับหลามมันเป็นเพียงเทอร์มินัล ฉันมักจะรู้ว่าการทิ้งเอาท์พุทไปยัง / dev / null เร่งสิ่งต่างๆ แต่ไม่เคยคิดว่ามันสำคัญมาก!

มันทำให้ฉันประหลาดใจว่า tty นั้นช้าแค่ไหน เป็นไปได้อย่างไรที่การเขียนไปยังดิสก์ทางกายภาพนั้นเป็นวิธีที่เร็วกว่าการเขียนไปที่ "หน้าจอ" (สันนิษฐานว่าเป็น all-RAM op) และมีความรวดเร็วพอ ๆ กับการทิ้งขยะโดยใช้ / dev / null?

ลิงค์นี้พูดถึงว่าเทอร์มินัลจะบล็อก I / O อย่างไรจึงจะสามารถ"แยก [อินพุต] อัปเดตเฟรมบัฟเฟอร์สื่อสารกับเซิร์ฟเวอร์ X เพื่อเลื่อนหน้าต่างและอื่น ๆ " ... แต่ฉันไม่ รับอย่างเต็มที่มัน สิ่งที่ใช้เวลานาน

ฉันคาดหวังว่าจะไม่มีทางออก (สั้นจากการใช้ tty ที่เร็วขึ้น?) แต่รูปที่ฉันถามอยู่แล้ว


UPDATE: หลังจากอ่านความคิดเห็นฉันสงสัยว่าขนาดหน้าจอของฉันมีผลต่อเวลาพิมพ์จริงแค่ไหนและมันก็มีความสำคัญ ตัวเลขที่ช้ามาก ๆ ข้างต้นนั้นคือเครื่องของฉัน Gnome ที่เป่าได้ถึง 1920x1200 ถ้าฉันลดมันให้เล็กลงฉันจะได้ ...

-----
timing summary (100k lines each)
-----
print                         : 2.920 s
write to file (+fsync)        : 0.121 s
print with stdout = /dev/null : 0.048 s

แน่นอนว่าจะดีกว่า (~ 4x) แต่ไม่เปลี่ยนคำถามของฉัน มันเพิ่มคำถามของฉันเท่านั้นเพราะฉันไม่เข้าใจว่าทำไมการเรนเดอร์หน้าจอเทอร์มินัลควรทำให้แอปพลิเคชันเขียนช้าลง ทำไมโปรแกรมของฉันต้องรอให้การเรนเดอร์หน้าจอดำเนินการต่อ

แอปเทอร์มินัล / tty ทั้งหมดไม่ถูกสร้างขึ้นเท่ากันหรือไม่? ฉันยังไม่ได้ทดลอง สำหรับฉันแล้วดูเหมือนว่าเทอร์มินัลควรจะสามารถบัฟเฟอร์ข้อมูลที่เข้ามาทั้งหมดแยกวิเคราะห์ / แสดงผลอย่างล่องหนและแสดงเฉพาะชิ้นล่าสุดที่ปรากฏในการกำหนดค่าหน้าจอปัจจุบันที่อัตราเฟรมที่สมเหตุสมผล ดังนั้นถ้าฉันสามารถเขียน + fsync ลงในดิสก์ได้ในเวลา ~ 0.1 วินาทีเทอร์มินัลควรจะสามารถทำการดำเนินการเดียวกันให้เสร็จสมบูรณ์ตามลำดับนั้น (อาจมีการปรับปรุงหน้าจอเล็กน้อยในขณะที่ทำ)

ฉันยังคงหวังว่าจะมีการตั้งค่า tty ที่สามารถเปลี่ยนได้จากด้านแอปพลิเคชันเพื่อให้พฤติกรรมนี้ดีขึ้นสำหรับโปรแกรมเมอร์ หากนี่เป็นปัญหาของแอปพลิเคชันเทอร์มินัลอย่างเคร่งครัดนี่อาจจะไม่ได้อยู่ใน StackOverflow ใช่ไหม

ฉันพลาดอะไรไป


นี่คือโปรแกรมไพ ธ อนที่ใช้สร้างช่วงเวลา:

import time, sys, tty
import os

lineCount = 100000
line = "this is a test"
summary = ""

cmd = "print"
startTime_s = time.time()
for x in range(lineCount):
    print line
t = time.time() - startTime_s
summary += "%-30s:%6.3f s\n" % (cmd, t)

#Add a newline to match line outputs above...
line += "\n"

cmd = "write to file (+fsync)"
fp = file("out.txt", "w")
startTime_s = time.time()
for x in range(lineCount):
    fp.write(line)
os.fsync(fp.fileno())
t = time.time() - startTime_s
summary += "%-30s:%6.3f s\n" % (cmd, t)

cmd = "print with stdout = /dev/null"
sys.stdout = file(os.devnull, "w")
startTime_s = time.time()
for x in range(lineCount):
    fp.write(line)
t = time.time() - startTime_s
summary += "%-30s:%6.3f s\n" % (cmd, t)

print >> sys.stderr, "-----"
print >> sys.stderr, "timing summary (100k lines each)"
print >> sys.stderr, "-----"
print >> sys.stderr, summary

9
จุดประสงค์ทั้งหมดของการเขียนไปยัง stdout คือเพื่อให้มนุษย์สามารถอ่านผลลัพธ์ ไม่มีมนุษย์คนใดในโลกที่สามารถอ่านข้อความ 10,000 บรรทัดภายใน 12 วินาทีดังนั้นอะไรคือจุดที่ทำให้ stdout เร็วขึ้น ???
Seun Osewa

14
@Seun Osewa: ตัวอย่างหนึ่ง (ที่ขับรถคำถามของฉัน) คือเมื่อทำสิ่งที่ชอบแก้จุดบกพร่องพิมพ์คำสั่ง คุณต้องการเรียกใช้โปรแกรมของคุณและดูผลลัพธ์ที่เกิดขึ้น คุณเห็นได้ชัดว่าบรรทัดส่วนใหญ่จะบินไปโดยที่คุณมองไม่เห็น แต่เมื่อมีข้อยกเว้นเกิดขึ้น (หรือคุณกดคำสั่ง getch / raw_input / sleep แบบมีเงื่อนไขที่คุณวางไว้อย่างระมัดระวัง) คุณต้องการดูผลงานพิมพ์โดยตรงมากกว่า ต้องเปิดหรือรีเฟรชมุมมองไฟล์อย่างต่อเนื่อง
รัส

3
การดีบักคำสั่งพิมพ์เป็นสาเหตุหนึ่งที่ทำให้อุปกรณ์ tty (เช่นเทอร์มินัล) เป็นค่าเริ่มต้นสำหรับการบัฟเฟอร์บรรทัดแทนการบัฟเฟอร์บล็อก: เอาต์พุตการดีบักไม่ได้ใช้ประโยชน์มากนักหากโปรแกรมหยุดทำงานและการดีบักเอาต์พุตไม่กี่บรรทัดสุดท้ายยังคงอยู่ในบัฟเฟอร์ แทนที่จะล้างไปยังสถานี
Stephen C. Steel

@ สตีเฟ่น: นี่คือเหตุผลที่ฉันไม่ได้ใส่ใจมากนักกับการปรับปรุงครั้งใหญ่ที่นักวิจารณ์คนหนึ่งอ้างโดยการเพิ่มขนาดบัฟเฟอร์ มันเอาชนะจุดประสงค์ของการพิมพ์ debug ทั้งหมด! ฉันทำการทดลองเล็กน้อยขณะตรวจสอบ แต่ไม่เห็นการปรับปรุงสุทธิ ฉันยังสงสัยเกี่ยวกับความคลาดเคลื่อน แต่ไม่ใช่จริง ๆ
รัส

บางครั้งสำหรับโปรแกรมที่รันนานมากฉันจะพิมพ์บรรทัดปัจจุบัน stdout ทุก ๆ n วินาที - คล้ายกับการหน่วงเวลาการรีเฟรชในแอป curses มันไม่ได้สมบูรณ์แบบ แต่ให้ความคิดเกี่ยวกับสิ่งที่ฉันเป็นครั้งคราวในขณะที่
rkulla

คำตอบ:


155

เป็นไปได้อย่างไรที่การเขียนไปยังดิสก์ทางกายภาพนั้นเป็นวิธีที่เร็วกว่าการเขียนไปที่ "หน้าจอ" (สันนิษฐานว่าเป็น all-RAM op) และมีความรวดเร็วพอ ๆ กับการทิ้งขยะโดยใช้ / dev / null?

ขอแสดงความยินดีคุณเพิ่งค้นพบความสำคัญของการบัฟเฟอร์ I / O :-)

ดิสก์ดูเหมือนจะเร็วกว่าเนื่องจากมีบัฟเฟอร์สูงการwrite()โทรทั้งหมดของ Python จะส่งคืนก่อนที่จะมีการเขียนข้อมูลใด ๆ ลงในดิสก์ทางกายภาพ (ระบบปฏิบัติการทำสิ่งนี้ในภายหลังโดยรวมการเขียนหลายพันรายการเป็นชิ้นใหญ่และมีประสิทธิภาพ)

ในทางกลับกันเทอร์มินัลทำบัฟเฟอร์เล็กน้อยหรือไม่มีเลย: แต่ละคนprint/ write(line)รอให้การเขียนแบบเต็ม (เช่นแสดงไปยังอุปกรณ์ส่งออก) ให้เสร็จสมบูรณ์

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

fp = file("out.txt", "w", 1)   # line-buffered, like stdout
[...]
for x in range(lineCount):
    fp.write(line)
    os.fsync(fp.fileno())      # wait for the write to actually complete

ฉันรันการทดสอบการเขียนไฟล์ของคุณบนเครื่องของฉันและด้วยการบัฟเฟอร์มันก็มี 0.05s ที่นี่สำหรับ 100,000 บรรทัด

อย่างไรก็ตามด้วยการแก้ไขข้างต้นเพื่อเขียน unbuffered มันใช้เวลา 40 วินาทีในการเขียนเพียง 1,000 บรรทัดไปยังดิสก์ ผมขึ้นรอให้ 100,000 เส้นที่จะเขียน แต่คะเนจากก่อนหน้านี้ก็จะใช้เวลานานกว่าหนึ่งชั่วโมง

นั่นทำให้มุมมอง 11 วินาทีของเทอร์มินัลใช่มั้ย

ดังนั้นเพื่อตอบคำถามเดิมของคุณการเขียนไปยังเทอร์มินัลนั้นเร็วจริง ๆ ทุกสิ่งที่พิจารณาและไม่มีที่ว่างมากมายที่จะทำให้มันเร็วขึ้น (แต่เทอร์มินัลแต่ละตัวจะแตกต่างกันไป ตอบ).

(คุณสามารถเพิ่มบัฟเฟอร์การเขียนได้มากขึ้นเช่นเดียวกับดิสก์ I / O แต่คุณจะไม่เห็นสิ่งที่เขียนไปยังเทอร์มินัลของคุณจนกว่าบัฟเฟอร์จะถูกลบทิ้งมันเป็นการแลกเปลี่ยน: การโต้ตอบกับประสิทธิภาพจำนวนมาก)


6
ฉันได้รับบัฟเฟอร์ I / O ... คุณเตือนฉันอย่างแน่นอนว่าฉันควรมี fsync สำหรับการเปรียบเทียบเวลาที่สมบูรณ์จริง ๆ (ฉันจะอัปเดตคำถาม) แต่ fsync ต่อบรรทัดนั้นเป็นสิ่งที่ไม่ดี tty จริง ๆ ต้องทำอย่างมีประสิทธิภาพหรือไม่ ไม่มีไฟล์เทอร์มินัล / ระบบปฏิบัติการด้านเทียบเท่ากับไฟล์หรือไม่? เช่น: แอปพลิเคชันเขียนไปยัง stdout และส่งคืนก่อนหน้าจอเทอร์มินัลโดยที่เทอร์มินัล (หรือระบบปฏิบัติการ) ทำการบัฟเฟอร์ทั้งหมด เทอร์มินัลสามารถทำให้หางไปยังหน้าจออย่างสมเหตุสมผลด้วยอัตราเฟรมที่มองเห็นได้ การบล็อกอย่างมีประสิทธิภาพในทุกบรรทัดดูเหมือนว่าโง่ ฉันรู้สึกว่าฉันยังขาดอะไร
รัส

คุณก็สามารถเปิดการจัดการที่ stdout os.fdopen(sys.stdout.fileno(), 'w', BIGNUM)มีขนาดใหญ่บัฟเฟอร์ตัวเองใช้สิ่งที่ต้องการ สิ่งนี้แทบจะไม่เป็นประโยชน์ แต่: เกือบทุกแอปพลิเคชันจะต้องจำไว้ว่าต้องล้างออกอย่างชัดเจนหลังจากแต่ละบรรทัดของผลลัพธ์ที่ผู้ใช้ต้องการ
Pi Delport

1
ฉันทดลองก่อนหน้านี้ด้วยfp = os.fdopen(sys.__stdout__.fileno(), 'w', 10000000)บัฟเฟอร์ด้านหลามขนาดใหญ่ (สูงถึง 10MB ) ผลกระทบเป็นศูนย์ เช่น: ยังคงล่าช้า tty ยาว นี่ทำให้ฉันคิดว่า / รู้ว่าคุณเพิ่งเลื่อนปัญหา tty ที่ช้า ... เมื่อบัฟเฟอร์ของงูใหญ่ในที่สุดก็ล้าง tty ยังดูเหมือนว่าจะทำการประมวลผลจำนวนเท่ากันทั้งหมดบนกระแสก่อนที่จะกลับมา
รัส

8
โปรดทราบว่าคำตอบนี้ทำให้เข้าใจผิดและผิด (ขออภัย!) มันผิดที่จะบอกว่า "ไม่มีที่ว่างเหลือพอที่จะทำให้เร็วขึ้น [มากกว่า 11 วินาที]" โปรดดูคำตอบของฉันสำหรับคำถามที่ฉันแสดงให้เห็นว่าเทอร์มินัล wterm ได้ผลลัพธ์ 11s เดียวกันใน 0.26 วินาที
Russ

2
รัส: ขอบคุณสำหรับข้อเสนอแนะ! ในด้านของฉันfdopenบัฟเฟอร์ที่มีขนาดใหญ่กว่า(2MB) สร้างความแตกต่างอย่างมากแน่นอน: มันใช้เวลาในการพิมพ์ลดลงจากหลายวินาทีเป็น 0.05 วินาทีเช่นเดียวกับไฟล์ที่ส่งออก (โดยใช้gnome-terminal)
Pi Delport

88

ขอบคุณสำหรับความคิดเห็นทั้งหมด! ฉันได้รับคำตอบจากคุณด้วยความช่วยเหลือของคุณเอง แต่รู้สึกสกปรกในการตอบคำถามของคุณเอง

คำถามที่ 1: ทำไมการพิมพ์ถึง stdout ช้า

คำตอบ: การพิมพ์ไปยัง stdout นั้นไม่ได้ช้าอย่างแท้จริง มันเป็นเครื่องที่คุณใช้งานช้า และมันก็ไม่มีอะไรจะเกี่ยวข้องกับการบัฟเฟอร์ I / O ทางด้านแอพพลิเคชั่น (เช่น: การบัฟเฟอร์ไฟล์หลาม) ดูด้านล่าง

คำถามที่ 2: สามารถเร่งความเร็วได้หรือไม่

คำตอบ:ใช่มันสามารถ แต่ดูเหมือนจะไม่ได้มาจากด้านโปรแกรม (ด้านที่ทำ 'การพิมพ์' เพื่อ stdout) เพื่อเพิ่มความเร็วใช้เทอร์มินัลอีมูเลเตอร์ที่แตกต่างกันเร็ว

ชี้แจง ...

ฉันลองใช้โปรแกรมเทอร์มินัล 'น้ำหนักเบา' ที่อธิบายตัวเองถูกเรียกwtermและได้ผลลัพธ์ที่ดีขึ้นอย่างมีนัยสำคัญ ด้านล่างคือผลลัพธ์ของสคริปต์ทดสอบของฉัน (ที่ด้านล่างของคำถาม) เมื่อทำงานwtermที่ 1920x1200 ในระบบเดียวกันที่ตัวเลือกการพิมพ์พื้นฐานใช้เวลา 12 วินาทีโดยใช้ gnome-terminal:

-----
สรุปเวลา (แต่ละเส้น 100k)
-----
พิมพ์: 0.261 วิ
เขียนลงไฟล์ (+ fsync): 0.110 วิ
พิมพ์ด้วย stdout = / dev / null: 0.050 s

0.26s นั้นดีกว่า 12 วินาที! ฉันไม่รู้ว่าwtermฉลาดกว่าเกี่ยวกับการแสดงผลตามวิธีที่ฉันแนะนำหรือไม่ (แสดงให้เห็นว่า 'มองเห็น' ด้วยอัตราเฟรมที่สมเหตุสมผล) หรือไม่ว่ามันจะ "น้อยลง" มากกว่าgnome-terminalกว่า แต่สำหรับคำถามของฉันฉันได้รับคำตอบแล้ว gnome-terminalช้า

ดังนั้น - หากคุณมีสคริปต์ที่ใช้งานมานานซึ่งคุณรู้สึกว่าช้าและมันพ่นข้อความจำนวนมากเพื่อ stdout ... ลองใช้เทอร์มินัลอื่นและดูว่ามันดีกว่านี้หรือไม่!

โปรดทราบว่าฉันดึงwtermจากที่เก็บ ubuntu / debian ไปโดย สุ่ม ลิงก์นี้อาจเป็นเครื่องเดียวกัน แต่ฉันไม่แน่ใจ ฉันไม่ได้ทดสอบตัวจำลองเทอร์มินัลอื่น ๆ


อัปเดต: เนื่องจากฉันต้องเกาคันฉันจึงทดสอบกองจำลองเทอร์มินัลอื่นทั้งหมดด้วยสคริปต์เดียวกันและเต็มหน้าจอ (1920x1200) สถิติที่ฉันรวบรวมด้วยตนเองอยู่ที่นี่:

wterm 0.3s
Aterm 0.3s
rxvt 0.3s
mrxvt 0.4s
konsole 0.6s
yakuake 0.7s
lxterminal 7 วินาที
xterm 9s
gnome-terminal 12s
xfce4-terminal 12s
วาลา - เทอร์มินัล 18
xvt 48s

เวลาที่บันทึกจะถูกรวบรวมด้วยตนเอง แต่ก็ค่อนข้างสอดคล้องกัน ฉันบันทึกค่าที่ดีที่สุด (ish) YMMV เห็นได้ชัด

เป็นโบนัสมันเป็นทัวร์ที่น่าสนใจของตัวจำลองเทอร์มินัลต่าง ๆ ที่มีอยู่ในนั้น! ฉันประหลาดใจที่การทดสอบ 'ทางเลือก' ครั้งแรกของฉันกลายเป็นสิ่งที่ดีที่สุดของกลุ่ม


1
คุณอาจลอง aterm นี่คือผลลัพธ์ในการทดสอบของฉันโดยใช้สคริปต์ของคุณ Aterm - พิมพ์: 0.491 s, เขียนไปยังไฟล์ (+ fsync): 0.110 วินาที, พิมพ์ด้วย stdout = / dev / null: 0.087 วินาที wterm - พิมพ์: 0.521 วินาที, เขียนไปยังไฟล์ (+ fsync): 0.105 s, พิมพ์ด้วย stdout = / dev / null: 0.085 s
frogstarr78

1
urxvt เปรียบเทียบกับ rxvt อย่างไร
Daenyth

3
นอกจากนี้screenควรรวมรายการไว้ด้วย! (หรือbyobuซึ่งเป็น wrapper สำหรับscreenการปรับปรุง) ยูทิลิตี้นี้อนุญาตให้มีเทอร์มินัลหลายอันเหมือนกับแท็บในเทอร์มินัล X ฉันคิดว่าการพิมพ์ไปยังscreenเทอร์มินัลปัจจุบันนั้นเหมือนกับการพิมพ์ไปที่เทอร์มินัล แต่สิ่งที่เกี่ยวกับการพิมพ์ในscreenเทอร์มินัลเครื่องหนึ่งแล้วสลับไปที่เครื่องอื่นโดยไม่มีกิจกรรม
Armando PérezMarqués

1
เมื่อไม่นานมานี้ฉันได้ทำการเปรียบเทียบเทอร์มินัลต่าง ๆ ในแง่ของความเร็วและ gnome-terminal นั้นออกมาดีที่สุดในการทดสอบที่ค่อนข้างจริงจังขณะที่ xterm ช้าที่สุด บางทีพวกเขาทำงานหนักกับการบัฟเฟอร์ตั้งแต่นั้นมา การรองรับ Unicode ก็สามารถสร้างความแตกต่างได้อย่างมาก
Tomas Pruzina

2
iTerm2 ใน OSX print: 0.587 s, write to file (+fsync): 0.034 s, print with stdout = /dev/null : 0.041 sให้ฉัน: และด้วย 'หน้าจอ' ที่ทำงานใน iTerm2:print: 1.286 s, write to file (+fsync): 0.043 s, print with stdout = /dev/null : 0.033 s
rkulla

13

การเปลี่ยนเส้นทางของคุณอาจไม่ทำอะไรเลยในขณะที่โปรแกรมสามารถกำหนดได้ว่าเอาต์พุต FD จะชี้ไปที่ tty หรือไม่

เป็นไปได้ว่า stdout จะถูกบัฟเฟอร์เมื่อชี้ไปที่เทอร์มินัล (เหมือนกับstdoutพฤติกรรมการสตรีมของ C )

catการทดลองสนุกลองท่อออกไป


ฉันลองการทดลองของตัวเองและนี่คือผลลัพธ์

$ python test.py 2>foo
...
$ cat foo
-----
timing summary (100k lines each)
-----
print                         : 6.040 s
write to file                 : 0.122 s
print with stdout = /dev/null : 0.121 s

$ python test.py 2>foo |cat
...
$ cat foo
-----
timing summary (100k lines each)
-----
print                         : 1.024 s
write to file                 : 0.131 s
print with stdout = /dev/null : 0.122 s

ฉันไม่คิดว่าหลามจะตรวจสอบเอฟเอสเอฟของมัน ฉันสงสัยว่าหลามดึงกลลวงอยู่เบื้องหลังหรือไม่? ฉันคาดหวังไม่ได้ แต่ไม่รู้
รัส

+1 สำหรับการชี้ให้เห็นถึงความแตกต่างที่สำคัญในการบัฟเฟอร์
Peter G.

@Russ ที่: -uกองกำลังตัวเลือกstdin, stdoutและstderrจะเป็นบัฟเฟอร์ซึ่งจะช้ากว่าถูกบล็อกบัฟเฟอร์ (เนื่องจากค่าใช้จ่าย)
Hasturkun

4

ฉันไม่สามารถพูดคุยเกี่ยวกับรายละเอียดทางเทคนิคได้เพราะฉันไม่รู้จักพวกเขา แต่สิ่งนี้ไม่ได้ทำให้ฉันแปลกใจ: เทอร์มินัลไม่ได้ออกแบบมาสำหรับการพิมพ์ข้อมูลจำนวนมากเช่นนี้ แน่นอนคุณยังให้ลิงก์ไปยังสิ่งที่โหลด GUI ที่ต้องทำทุกครั้งที่คุณต้องการพิมพ์บางอย่าง! โปรดสังเกตว่าถ้าคุณโทรหาสคริปต์ด้วยpythonwแทนจะไม่ใช้เวลา 15 วินาที นี่เป็นปัญหา GUI ทั้งหมด เปลี่ยนเส้นทางstdoutไปยังไฟล์เพื่อหลีกเลี่ยงปัญหานี้:

import contextlib, io
@contextlib.contextmanager
def redirect_stdout(stream):
    import sys
    sys.stdout = stream
    yield
    sys.stdout = sys.__stdout__

output = io.StringIO
with redirect_stdout(output):
    ...

3

การพิมพ์ไปที่เครื่องจะช้า น่าเสียดายที่การเขียนเทอร์มินัลใหม่ไม่สามารถใช้งานได้ฉันไม่สามารถเห็นได้ว่าคุณจะเพิ่มความเร็วได้มากแค่ไหน


2

นอกเหนือจากผลลัพธ์ที่อาจเป็นค่าเริ่มต้นไปยังโหมด line-buffered เอาต์พุตไปยังเทอร์มินัลยังทำให้ข้อมูลของคุณไหลเข้าสู่เทอร์มินัลและสายอนุกรมที่มีปริมาณงานสูงสุดหรือ pseudo-terminal และกระบวนการแยกที่จัดการจอแสดงผล วนรอบเหตุการณ์การแสดงผลตัวอักษรจากแบบอักษรบางส่วนย้ายการแสดงผลบิตเพื่อใช้การแสดงผลแบบเลื่อน สถานการณ์หลังอาจแพร่กระจายไปในหลาย ๆ กระบวนการ (เช่น telnet เซิร์ฟเวอร์ / ไคลเอนต์, แอปเทอร์มินัล, เซิร์ฟเวอร์ดิสเพลย์ X11) ดังนั้นจึงมีการสลับบริบทและปัญหาเวลาแฝงด้วย


ความจริง! สิ่งนี้ทำให้ฉันพยายามลดขนาดหน้าต่างเทอร์มินัลของฉัน (ใน Gnome) ให้เหลือน้อยมาก (จาก 1920x1200) แน่นอนว่า ... เวลาพิมพ์ 2.8 วินาทีเทียบกับ 11.5 วินาที ดีกว่ามาก แต่ก็ยัง ... ทำไมมันถึงหยุดนิ่ง คุณจะคิดว่า stdout buffer (hmm) สามารถรองรับ 100k line ทั้งหมดและหน้าจอเทอร์มินัลก็จะคว้าอะไรก็ตามที่มันพอดีกับหน้าจอจากปลายหางของบัฟเฟอร์และทำให้เสร็จด้วยการยิงเพียงครั้งเดียว
รัส

xterm (หรือ gterm ในกรณีนี้) จะทำให้หน้าจอสุดท้ายของคุณเร็วขึ้นหากไม่คิดว่าจะต้องแสดงผลลัพธ์อื่น ๆ ทั้งหมดไปพร้อมกัน หากพยายามไปยังเส้นทางนี้อาจทำให้กรณีทั่วไปของการอัพเดตหน้าจอเล็ก ๆ ดูเหมือนจะตอบสนองน้อยลง เมื่อเขียนซอฟต์แวร์ประเภทนี้บางครั้งคุณสามารถจัดการได้โดยมีโหมดที่แตกต่างกันและพยายามตรวจจับเมื่อคุณต้องการย้ายไป / จากโหมดการทำงานขนาดเล็กไปจนถึงขนาดใหญ่ คุณสามารถใช้cat big_file | tailหรือcat big_file | tee big_file.cpy | tailบ่อยมากสำหรับความเร็วนี้
nategoose
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.