2011-11-07 22 views
5

Tôi đang so sánh hiệu suất để đọc số lượng dòng chứa một tệp.So sánh tốc độ đếm dòng mới giữa wc và Smalltalk

tôi đã làm nó đầu tiên sử dụng công cụ dòng lệnh wc:

$ time wc -l bigFile.csv 
1673820 bigFile.csv 

real 0m0.157s 
user 0m0.124s 
sys  0m0.062s 

và sau đó trong một sạch Pharo Lõi Smalltalk mới nhất 1,3

| file lineCount | 
Smalltalk garbageCollect. 
(Duration milliSeconds: [ file := FileStream readOnlyFileNamed: 'bigFile.csv'. 
lineCount := 0. 
[ file atEnd ] whileFalse: [ 
    file nextLine. 
    lineCount := lineCount + 1 ]. 
file close. 
lineCount. ] timeToRun) asSeconds. 
15 

Làm thế nào tôi có thể tăng tốc độ mã Smalltalk được nhanh hơn hoặc gần hơn hiệu suất wc?

Trả lời

8
[ (PipeableOSProcess waitForCommand: 'wc -l /path/to/bigfile2.csv') output ] timeToRun. 

Các báo cáo trên ~ 207 mili giây, mà thời gian báo cáo:

real 0m0.160s 
user 0m0.131s 
sys  0m0.029s 

Tôi đang đùa, nhưng cũng nghiêm trọng. Không cần phải phát minh lại bánh xe. FFI, OSProcess, Zinc,… cung cấp nhiều cơ hội để sử dụng những thứ như tiện ích UNIX đã được thử nghiệm trong nhiều thập kỷ qua.

Nếu câu hỏi của bạn là thực sự thêm về Smalltalk chính nó, một sự khởi đầu sẽ là:

[ FileStream 
    readOnlyFileNamed: '/path/to/reallybigfile2.csv' 
    do: [ :file | | endings count | 
     count := 0. 
     file binary. 
     file contents do: [ :c | c = 10 ifTrue: [ count := count + 1 ] ]. 
     count ] 
] timeToRun. 

Điều đó sẽ giúp bạn có được xuống đến 2,5 giây:

  • làm cho dòng nhị phân lưu ~ 10 giây
  • readOnlyFileNamed: do: saved ~ 1 giây
  • tìm dòng kết thúc bằng tay thay vì sử dụng #nextLine saved ~ 4 seconds

Một dọn dẹp, nhưng 1/2 thứ hai op còn sẽ là:

file contents occurrencesOf: 10.

Tất nhiên, nếu hiệu suất tốt hơn là cần thiết, và bạn không muốn sử dụng FFI/OSProcess, bạn sẽ sau đó viết một plugin.

+0

Tôi đặt cược khoản tiết kiệm lớn nhất trong mã của bạn không đến từ việc tạo tệp nhị phân, nhưng từ đọc toàn bộ tệp vào bộ nhớ trước khi xử lý bằng "nội dung". Đọc các tập tin trong các khối có kích thước hợp lý nên giá vé như nhau. –

+0

Tôi đã kiểm tra lại ... #binary thực sự đã lưu 10 giây so với gọi #asciiValue hoặc so sánh với "Character lf" (ngay cả khi được lưu trong bộ nhớ tạm thời). #contents đã lưu 3,5 giây so với vòng lặp thủ công với #next. –

1

Nếu bạn có thể đủ khả năng đọc toàn bộ tập tin trong bộ nhớ, sau đó mã đơn giản nhất là

[ FileStream 
    readOnlyFileNamed: '/path/to/reallybigfile2.csv' 
    do: [ :file | file contents lineCount ] 
] timeToRun. 

này sẽ xử lý sở thú của LF (Linux), CR (Old Mac), CR-LF (bạn tên nó). Mã từ Sean chỉ xử lý LF, với cùng mức chi phí. Tôi muốn nói một yếu tố 10 cho Smalltalk vs C được mong đợi cho các hoạt động cơ bản như vậy, vì vậy tôi nghi ngờ bạn nhận được hiệu quả hơn nhiều mà không cần thêm nguyên thủy của riêng bạn.

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