Chi phí sử dụng subshells là gì?


9

Hy vọng rằng câu hỏi này không quá chung chung. Tôi rất mới với shell scripting và tôi đến từ một nền tảng lập trình máy tính / không kịch bản. Tôi đã nhận thấy trên các tập lệnh trong công việc của tôi rằng hiếm khi các tập lệnh được viết bằng cách tạo một lớp vỏ phụ xung quanh toàn bộ tập lệnh. Trong các kịch bản tôi đang viết, khi tôi có thể bao bọc nó bằng một vỏ phụ tôi vì nó giữ cho nó không bị rối với các tập lệnh khác gọi là của tôi (Chỉ trong trường hợp). Đây có phải là một thực tế phổ biến vì một số chi phí liên quan đến phương pháp này? Tôi đang có một thời gian khó khăn để tìm thấy điều này trực tuyến.

Thí dụ:

#!/bin/bash
( #Start of subshell
echo "Some stuff here"
) #End of subshell

1
Làm thế nào là những kịch bản khác gọi kịch bản của bạn? Ví dụ, họ đang sử dụng một source, hoặc thay vào đó họ đang thực thi tập lệnh của bạn?
giờ 32 phút

1
Xuất phát từ một nền tảng lập trình, có một bài đăng trên trang web này nên được đọc giới thiệu bắt buộc để viết kịch bản shell - nó bao gồm sự khác biệt về khái niệm giữa bashvà ví dụ C. Câu trả lời thực sự cho câu hỏi "trên cao" này thực sự là không có câu trả lời: Nếu bạn lo lắng về hiệu suất hoạt động, bạn không nên sử dụng tập lệnh shell.
tự đại diện

Bạn có thể vui lòng làm rõ những gì bạn có nghĩa là "một subshell xung quanh toàn bộ kịch bản"? somefunction() ( ... ) (chú ý các parens thay vì curlies) để xác định rằng việc somefunctionluôn tạo một subshell không phải là hiếm, tuy nhiên tôi không nghĩ rằng cần phải đặt các tập lệnh thực tế trong ngoặc đơn.
PSkocik

1
@PSkocik Đã thêm một ví dụ
LinuxLearner

1
Hãy xem xét quá trình thay thế quy trình so với đường ốngpython so với các vòng lặp shell nếu bạn tò mò về hiệu suất trong shell nói chung.
Sergiy Kolodyazhnyy

Câu trả lời:


7

Subshells làm gì có phí.

Trên hệ thống của tôi, chi phí thực hiện fork tối thiểu (khi bạn chạy chương trình từ đĩa khi tệp không lạnh) 2msvà chi phí rèn tối thiểu là khoảng 1ms.

Với subshells, bạn đang nói về chi phí rèn một mình, vì không có tệp nào cần phải chỉnh sửa exec. Nếu các khung con được giữ ở mức thấp hợp lý, 1msthì không đáng kể trong các chương trình đối mặt với con người. Tôi tin rằng con người không thể nhận thấy bất cứ điều gì xảy ra nhanh hơn 50ms(và đó là mất bao lâu để các phiên dịch ngôn ngữ kịch bản hiện đại bắt đầu (tôi đang nói pythonvà ruby ​​ở rvmđây) với những gì mới nhất nodejsdiễn ra xung quanh 100ms).

Tuy nhiên, nó bổ sung các vòng lặp, và sau đó bạn có thể muốn thay thế ví dụ như bactick hoặc $()mẫu khá phổ biến trong đó bạn lấy returnmột cái gì đó từ một hàm bằng cách in nó ra stdout cho shell cha để tạo ra các bashism như printf -v(hoặc sử dụng bên ngoài nhanh chương trình xử lý toàn bộ lô).

Các bash hoàn thành gói đặc biệt tránh chi phí subshell này bằng cách quay qua tên biến thông qua sử dụng một kỹ thuật được mô tả tại http://fvue.nl/wiki/Bash:_Passing_variables_by_reference


So sánh

time for((i=0;i<10000;i++)); do echo "$(echo hello)"; done >/dev/null 

với

time for((i=0;i<10000;i++)); do echo hello; done >/dev/null 

sẽ cung cấp cho bạn một ước tính tốt về forkchi phí hệ thống của bạn là gì.


1
Cảm ơn bạn. Điều này thực sự hữu ích. Tôi đang viết kịch bản trên máy tính xách tay cũ. Nếu tôi đang viết một kịch bản được gọi nhiều lần, tôi sẽ tránh sử dụng các chuỗi con. Ngay cả khi nó không đáng kể, tôi đang cố gắng phát triển các thực hành mã hóa tốt ngay từ đầu.
LinuxLearner

Nếu bạn đang viết kịch bản cho máy tính xách tay cũ, hãy cho Perl 5 một cái nhìn thực tế. Perl sẽ hoạt động trên hầu hết mọi hệ thống cũ, nếu bạn sử dụng cú pháp 5,008 hoặc 5,010, bạn có quyền truy cập vào tốc độ và sức mạnh lớn hơn so với hệ vỏ. Tôi đã thực hiện lộ trình shell trong nhiều năm, vì những lý do chính đáng, nhưng cuối cùng, do một phần là do luôn cần phải trả về hàm thông qua các lớp con và thiếu cấu trúc dữ liệu comlex, tôi đã quyết định rằng nếu tôi cần một cách nhất quán, tôi sẽ sử dụng Perl. Chi phí rèn là rất lớn khi bạn đạt được vòng lặp thực sự, nó không được đánh giá thấp. Perl nhanh hơn gần gấp đôi, khoảng.
Lizardx

1
Gần đây tôi đã thay thế một số $(echo $text | cut ...)cuộc gọi (ví dụ) trích xuất chuỗi con từ văn bản bằng ${text##substr}các cuộc gọi và nó giảm đáng kể thời gian thực hiện.
dùng208145

1

Chạy mã xuất sắc được cung cấp bởi PSkocik trên hệ thống của tôi cho thấy kết quả không đáng kể.

Tuy nhiên, ví dụ này thực sự đánh vào các lệnh nhà - lệnh gốc so với các lệnh con:

MyPath="path/name.ext" 
# this takes forever
time for((i=0;i<10000;i++)); do echo "$(basename ${MyPath} )"; done >/dev/null 
#this is over 100x less time 
time for((i=0;i<10000;i++)); do echo "${MyPath##*/}"; done >/dev/null     
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.