2013-03-18 26 views
6

Tôi có một khung công cụ bao gồm các công cụ khác nhau được viết bằng python trong môi trường đa người dùng.Làm thế nào để tăng tốc độ khởi động python và/hoặc giảm tìm kiếm tệp trong khi tải thư viện?

Lần đầu tiên tôi đăng nhập vào hệ thống và bắt đầu một lệnh, chỉ mất 6 giây để hiển thị một số dòng trợ giúp. Nếu tôi ngay lập tức phát hành cùng một lệnh một lần nữa nó mất 0.1s. Sau một vài phút, nó quay trở lại 6s. (bằng chứng về bộ nhớ cache ngắn ngủi)

Hệ thống nằm trên GPFS sao cho thông lượng đĩa phải ổn, mặc dù quyền truy cập có thể thấp do số lượng tệp trong hệ thống.

strace -e open python tool | wc -l 

hiển thị 2154 tệp đang được truy cập khi khởi động công cụ.

strace -e open python tool | grep ENOENT | wc -l 

hiển thị năm 1945 tệp bị thiếu đang được tìm kiếm. (Tỷ lệ hit/miss rất xấu là bạn hỏi tôi :-)

Tôi có linh cảm rằng thời gian quá tải liên quan đến việc tải công cụ được sử dụng bằng cách truy vấn GPFS về tất cả các tệp đó. gọi (ở cả cấp độ hệ thống hoặc GPFS), mặc dù tôi không biết cách kiểm tra/chứng minh nó. Tôi không có quyền truy cập root vào hệ thống và tôi chỉ có thể ghi vào GPFS và/tmp.

Có thể cải thiện điều này python quest for missing files không?

Bất kỳ ý tưởng nào về cách kiểm tra điều này một cách đơn giản? (Cài đặt lại mọi thứ trên/tmp không đơn giản, vì có nhiều gói liên quan, virtualenv sẽ không giúp (tôi nghĩ), vì nó chỉ liên kết các tệp trên hệ thống gpfs).

Một tùy chọn sẽ là tất nhiên để có một daemon mà dĩa, nhưng đó là xa "đơn giản" và sẽ là một giải pháp nghỉ mát cuối cùng.

Cảm ơn bạn đã đọc.

Trả lời

2

Làm thế nào về việc sử dụng mô-đun imp? Đặc biệt có chức năng: imp.find_module (mô-đun, đường dẫn) tại đây http://docs.python.org/2.7/library/imp.html

Ít nhất ví dụ này (xem bên dưới) giảm số lượng() syscalls mở so với đơn giản 'nhập gọn gàng, scipy': (cập nhật: nhưng có vẻ như không thể để đạt được giảm đáng kể các syscalls theo cách này ...)

import imp 
import sys 


def loadm(name, path): 
    fp, pathname, description = imp.find_module(name,[path]) 
    try: 
     _module = imp.load_module(name, fp, pathname, description) 
     return _module 
    finally: 
     # Since we may exit via an exception, close fp explicitly. 
     if fp: 
      fp.close() 


numpy = loadm("numpy", "/home/username/py-virtual27/lib/python2.7/site-packages/") 
scipy = loadm("scipy", "/home/username/py-virtual27/lib/python2.7/site-packages/") 

Tôi đoán bạn cũng nên kiểm tra xem PYTHONPATH của bạn trống hay nhỏ, vì điều đó cũng có thể tăng thời gian tải.

+0

Thật vậy, tôi đã thử cái này và trông có vẻ hứa hẹn, mặc dù tất cả các thư viện mặc định được chạy lúc khởi động và tôi không thể nói python từ tệp nào nên tải mô-đun, nhưng hãy để nó tìm kiếm trong thư mục, gây ra 4 cuộc gọi mở() và ít nhất 2 lần bỏ lỡ. Tôi chỉ ước rằng sẽ có một cách để nói với python không làm điều đó. – estani

2

Python 2 tìm kiếm các mô-đun liên quan đến gói hiện tại trước tiên. Nếu mã thư viện của bạn có rất nhiều hàng nhập khẩu cho nhiều mô-đun cấp cao nhất thì tất cả các mô đun này đều được xem là tương đối trước. Vì vậy, nếu gói foo.bar nhập os, thì Python trước tiên sẽ tìm kiếm foo/bar/os.py. Lỗi này được lưu trữ bởi chính Python.

Trong Python 3, mặc định đã được chuyển sang nhập tuyệt đối thay thế; bạn có thể chuyển Python 2.5 và lập để sử dụng nhập khẩu tuyệt đối mỗi mô-đun với:

from __future__ import absolute_import 

Một nguồn bỏ lỡ tra cứu tập tin đang tải .pyc file bytecode cache; nếu những thứ đó bị thiếu vì một số lý do (hệ thống tập tin không thể ghi được cho quá trình Python hiện tại) thì Python sẽ tiếp tục tìm kiếm chúng trên mọi lần chạy. Bạn có thể tạo ra những bộ nhớ đệm với compileall module:

python -m compileall /path/to/directory/with/pythoncode 

miễn là bạn chạy rằng với đúng các điều khoản ghi.

+0

hmmm ... Tôi đã thử tính năng này ở cuộc gọi cấp cao nhất (tập lệnh nhập phần còn lại), nhưng nó chỉ thêm 25 tệp tìm kiếm khác cho __future__ mà không có bất kỳ lợi ích nào khác: - /. Tất cả .pyc đều có, nhưng thứ tự tìm kiếm là allways: '* .so -> * module.so -> * .py -> * .pyc', do đó, nó không có sự khác biệt. Bằng cách này, nó là absolute_import (không có s). Dù sao cũng cảm ơn! – estani

+0

Đã sửa. Có, tôi tưởng tượng Python phải tìm kiếm các phần mở rộng C trước các tệp Python, và nó sẽ phải tìm tệp '.py' để kiểm tra xem tệp' .pyc' có lẽ đã cũ. Tôi đã cố gắng cung cấp cho bạn các tùy chọn để tra cứu * có thể * tránh được. –

+0

Thật vậy, cảm ơn vì điều đó! Tôi cũng đã thử nghiệm nó với một tập tin mà chỉ cần tải os và chuyển '__future__' tùy chọn trước khi thực hiện không có sự khác biệt. Tôi nghĩ rằng tôi có thể thử điều chỉnh PYTHONPATH, mặc dù tôi muốn có một cách để cache tất cả các cuộc gọi từ một cuộc gọi python đến khác ... là nó có thể tải một mô-đun vào bộ nhớ từ một con đường nhất định? Có lẽ tôi có thể tải trước chúng ... – estani