2015-04-22 24 views
8

Đối với dự án WPF của tôi, tôi phải tính tổng kích thước tệp trong một thư mục duy nhất (có thể có các thư mục phụ).Tại sao EnumerateFiles nhanh hơn nhiều so với việc tính toán các kích thước

Sample 1

DirectoryInfo di = new DirectoryInfo(path); 
var totalLength = di.EnumerateFiles("*.*", SearchOption.AllDirectories).Sum(fi => fi.Length); 

if (totalLength/1000000 >= size) 
    return true; 

Sample 2

var sizeOfHtmlDirectory = Directory.GetFiles(path, "*.*", SearchOption.AllDirectories); 
long totalLength = 0; 
foreach (var file in sizeOfHtmlDirectory) 
{ 
    totalLength += new FileInfo(file).Length; 
    if (totalLength/1000000 >= size) 
     return true; 
} 

Cả hai mẫu làm việc.

Mẫu 1 hoàn thành trong thời gian nhanh hơn. Tôi đã không định thời gian này chính xác nhưng trên PC của tôi, sử dụng cùng một thư mục có cùng kích thước nội dung/tệp, Mẫu 1 mất vài giây, Mẫu 2 mất vài phút.

EDIT

Tôi phải chỉ ra, cổ chai trong mẫu 2 là trong vòng lặp foreach! Nó đọc GetFiles một cách nhanh chóng và nhanh chóng đi vào vòng lặp foreach.

Câu hỏi của tôi là, làm cách nào để tìm hiểu lý do tại sao lại xảy ra trường hợp này?

+0

Có thể là do với 'GetFiles', trước tiên bạn phải liệt kê tất cả các tệp trước khi trả về một kết quả. Hãy thử thêm một 'ToArray()' trước '.Sum' – xanatos

+0

Và bạn thậm chí có thể thử' Directory.EnumerateFiles'/'DirectorInfo.GetFiles' – xanatos

+1

Bạn cũng đã so sánh nó với phương pháp tiếp cận mà bạn sử dụng một' DirectoryInfo' làm gốc và 'dirInfo.GetFiles' để nhận tất cả các đối tượng' FileInfo'? –

Trả lời

8

Trái với những gì các câu trả lời khác chỉ ra sự khác biệt chính không phải là EnumerateFiles vs GetFiles - đó là DirectoryInfo vs Directory - trong trường hợp này bạn chỉ có chuỗi và phải tạo FileInfo trường mới riêng biệt mà là rất tốn kém.

DirectoryInfo lợi nhuận FileInfo trường hợp sử dụng thông tin được lưu trữ trực tiếp vs tạo FileInfo trường mới mà không - biết thêm chi tiết herehere.

quote liên quan (thông qua "The Old New Thing"):

Trong NTFS, hệ thống tập tin siêu dữ liệu là một tài sản không phải của mục nhập thư mục mà là của tập tin, với một số các siêu dữ liệu sao chép vào mục nhập thư mục làm tinh chỉnh để cải thiện điều tra danh bạ hiệu suất. Các hàm như FindFirstFile báo cáo mục nhập và bằng cách đặt siêu dữ liệu mà người dùng FAT đã quen với việc nhận được "miễn phí", họ có thể tránh bị chậm hơn FAT trong danh sách thư mục . Các hàm liệt kê thư mục báo cáo siêu dữ liệu được cập nhật lần cuối, có thể không tương ứng với siêu dữ liệu thực tế nếu mục nhập thư mục cũ.

+1

Trong khi tôi có [cùng suy nghĩ] (http://stackoverflow.com/questions/29800121/why-is-enumeratefiles-much-quicker-than-calculating-the-sizes/29800250#comment47728570_29800121), làm cách nào bạn biết rằng 'EnumerateFiles' không cần phải làm như vậy dưới mui xe? Các thể hiện 'FileInfo' cũng phải được khởi tạo. Có lẽ có một số chi phí IO nếu bạn sử dụng 'FileInfo (tập tin) .Length' bởi vì các tập tin phải được tìm kiếm đầu tiên. –

+0

Nó có thể là ... FileInfoResultHandler.CreateObject khởi tạo FileInfo phải được trả về trực tiếp bởi một Win32Native.WIN32_FIND_DATA – xanatos

+0

@TimSchmelter cuối cùng, tất cả đều kết thúc bằng cách sử dụng cùng một [FileSystemEnumerator] (http://referencesource.microsoft.com/ # mscorlib/system/io/filesystemenumerable.cs, e9aaa9fc3bf05462) lớp. Do đó, nút cổ chai rất có thể là một thực tế là một cuộc gọi thêm vào 'FileInfo' trong quá trình lặp. – James

-1

EnumerateFiles là không đồng bộ trong khi GetFiles đợi cho đến khi tất cả các tệp đã được liệt kê trước khi trả về tập hợp tệp. Điều này sẽ có ảnh hưởng lớn đến kết quả của bạn.

+1

Không, đó không phải là lý do vì OP muốn xử lý tất cả các tệp. –

Các vấn đề liên quan