2009-04-13 28 views
18

Tôi có một vài tệp nhật ký rất lớn và tôi cần phải phân tích cú pháp chúng. Dễ thực hiện rõ ràng chỉ cho tôi để Perl và combo regex (trong đó tôi vẫn còn là một người mới). Nhưng tốc độ thì sao? Nó sẽ nhanh hơn để thực hiện nó trong C? Mỗi tệp nhật ký nằm trong thứ tự 2 GB.Có phải Perl hoặc C nhanh hơn khi phân tích cú pháp không?

+0

@LFSR, tôi đã hoàn nguyên từ "trình phân tích cú pháp" trở lại "nó" vì thay đổi đó thay đổi toàn bộ câu hỏi, mà tôi cho là đã sử dụng công cụ C RE như PCRE chứ không phải mã hóa bằng tay FSM. @Alphaneo, bạn nên làm rõ điều này để đảm bảo ý định của bạn rõ ràng. – paxdiablo

Trả lời

41

Tôi rất nghi ngờ C sẽ nhanh hơn so với Perl, trừ khi bạn là để tay biên dịch RE.

Bằng tay biên dịch, tôi có nghĩa là mã hóa máy trạng thái hữu hạn (FSM) trực tiếp thay vì sử dụng công cụ RE để biên dịch nó. Cách tiếp cận này có nghĩa là bạn có thể tối ưu hóa nó cho trường hợp cụ thể của bạn mà thường có thể nhanh hơn dựa trên động cơ có mục đích chung hơn.

Nhưng đó không phải là điều tôi từng đề xuất với bất kỳ ai chưa từng viết trình biên dịch hoặc phân tích cú pháp trước đây mà không có lợi ích của lex, yacc, bison hoặc các công cụ tương tự khác.

Các công cụ tổng quát, như PCRE, thường đủ mạnh và đủ nhanh (cho nhu cầu của tôi, và những nhu cầu đó thường là rất yêu cầu).

Khi sử dụng công cụ RE chung, nó cần có khả năng xử lý tất cả các trường hợp cho dù được viết bằng C hoặc Perl. Khi bạn nghĩ về điều đó nhanh hơn, bạn chỉ phải so sánh những gì các công cụ RE được viết trong cả hai trường hợp (gợi ý: động cơ Perl RE là không phải được viết bằng Perl).

Cả hai đều được viết bằng chữ C nên bạn sẽ tìm thấy rất ít sự khác biệt về tốc độ phù hợp.

Bạn có thể tìm sự khác biệt trong mã hỗ trợ xung quanh RE nhưng điều này sẽ tối thiểu, đặc biệt nếu đó là vòng lặp đọc/kết hợp/đầu ra đơn giản.

+1

Thực hiện một máy trạng thái thực tế ("biên dịch tay RE") là chính xác những gì bạn sẽ làm trong C, vì vậy nó gần như chắc chắn sẽ nhanh hơn. Bạn cũng có quyền kiểm soát nhiều hơn đối với hành vi đệm tệp trong C, đó sẽ là yếu tố quyết định chính của tốc độ bất kể ngôn ngữ nào được sử dụng. –

+0

Nhanh hơn để chạy nhưng chậm hơn để viết :-). Tôi có xu hướng sử dụng PCRE hoặc một cái gì đó tương tự như một nỗ lực đầu tiên. Nếu hiệu suất trở thành một vấn đề, sau đó tôi sẽ xem xét việc tạo FSM của riêng tôi. – paxdiablo

+0

Có phải viết một FSM tùy chỉnh có khả năng giúp đỡ trong tình huống như thế này không? Tôi có nghĩa là, là thời gian CPU thường sẽ là nút cổ chai trong tình huống này, hoặc tập tin I/O? Giả sử, chỉ vì mục đích đơn giản, một bộ xử lý đơn và một ổ cứng tiêu dùng thông thường. – intuited

4

Trong quá khứ, tôi đã tìm thấy C là nhanh hơn, nhưng không đến mức lựa chọn là một kết luận bỏ qua.

Bạn đã nghĩ về việc sử dụng một công cụ Log Parser chung chung, chẳng hạn như Log Parser:

Log phân tích cú pháp là một mạnh mẽ, linh hoạt công cụ cung cấp truy vấn phổ quyền truy cập vào dữ liệu dựa trên văn bản như log file , Tệp XML và tệp CSV, dưới dạng cũng như nguồn dữ liệu chính trên hệ điều hành Windows chẳng hạn như Nhật ký sự kiện, Cơ quan đăng ký, tệp hệ thống và Active Directory®.

site liệt kê một vài trình phân tích cú pháp nhật ký chung.

20

Trình so khớp regex Perl được tối ưu hóa rất nhiều. Đây là nơi Perl tỏa sáng, bạn sẽ không gặp khó khăn khi làm việc với một tệp 2GB trong Perl và hiệu suất nên dễ dàng so sánh với phiên bản C. Nhân tiện: Bạn đã thử tìm một trình phân tích cú pháp đăng nhập đã hoàn thành chưa? Có rất nhiều người trong số họ.

+0

Trình phân tích cú pháp tệp nhật ký là tin tức với tôi, Cảm ơn bạn, tôi sẽ tìm kiếm. – Alphaneo

2

Nếu bạn thành thạo Perl, hãy sử dụng nó. Nếu không, hãy sử dụng AWK và SED.

Parsing văn bản không phải là những gì bạn muốn làm với C.

+0

Trừ khi bạn có PCRE :-) – paxdiablo

+0

+1 cho tham chiếu AWK và SED.Tính hirerarchy của ngôn ngữ của tôi (đi từ trái sang phải cho đến khi bạn có thể xử lý vấn đề tốt) là grep -> sed -> awk -> đầy đủ biên dịch ngôn ngữ. –

4

Perl rõ ràng có một số chi phí so với C.Nhưng chi phí này có thể không đáng kể nếu bạn dành phần lớn thời gian bên trong các chức năng Perl Regex được thực hiện trong C.

12

Nếu bạn thực sự cần để sử dụng regexes, thì công cụ regex Perl khó đánh bại. Tuy nhiên, nhiều vấn đề phân tích cú pháp có thể được giải quyết hiệu quả hơn nếu không có chúng - ví dụ, nếu bạn chỉ cần chia một dòng tại một ký tự nhất định, trong trường hợp này C có thể sẽ nhanh hơn.

Nếu hiệu suất có tầm quan trọng quan trọng, thì bạn nên thử cả hai ngôn ngữ và đo lường sự khác biệt về tốc độ. Nếu không, chỉ cần sử dụng cái bạn cảm thấy thoải mái nhất.

8

Tôi đoán (thay vì điểm chuẩn so với dữ liệu thực tế của Alphaneo, mà tôi không có) rằng xử lý I/O sẽ là yếu tố giới hạn ở đây. Và tôi mong đợi một triển khai Perl trên một perl với usefaststdio được kích hoạt để phù hợp hoặc đánh bại một C cơ bản thực hiện, nhưng đáng chú ý là chậm hơn mà không có usefaststdio. (usefaststdio được bật theo mặc định trong perl 5.8 trở lên cho hầu hết các nền tảng và tắt theo mặc định trong perl 5.10.)

+0

Cảm ơn bạn đã tìm hiểu thông tin về nút cổ chai IO. Nó thực sự quan trọng. – Alphaneo

7

Tốc độ thực sự là một yếu tố ở đây? Bạn có thực sự quan tâm việc phân tích cú pháp có được thực hiện sau 5 hoặc 10 phút không?

Tìm kiếm ngôn ngữ hoặc công cụ cung cấp các tính năng phân tích cú pháp tốt nhất và bạn rất hài lòng với nó.

+0

Khi hoàn thành thử nghiệm, nhật ký được tạo, tệp nhật ký này được phân tích cú pháp cho bất kỳ vấn đề nào. Và nếu có bất kỳ vấn đề nào, chúng tôi ngay lập tức bắt đầu làm việc về vấn đề này. Nó sẽ thực sự hữu ích ngay cả khi nó tiết kiệm nói một vài giây. – Alphaneo

3

Một phần của điều này phụ thuộc vào cách phân tích cú pháp sẽ được tích hợp vào một ứng dụng. Nếu ứng dụng IS là trình phân tích cú pháp, thì Perl sẽ ổn, chỉ vì nó sẽ xử lý tất cả mọi thứ xung quanh nó, nhưng nếu nó được tích hợp TRỰC TIẾP vào một ứng dụng lớn hơn, thì hoàn toàn có thể là bạn muốn nhìn vào một cái gì đó giống như Lex (hoặc Flex những ngày này): http://en.wikipedia.org/wiki/Lex_(software) Công cụ này tạo trình phân tích cú pháp cho bạn và bạn có thể tích hợp mã C/C++ trực tiếp vào phần mềm của bạn.

Đối với những cân nhắc về tốc độ, tôi đồng ý với hầu hết những người trả lời khác ở đây rằng sự trưởng thành của thư viện được sử dụng sẽ là yếu tố chi phối và Perl's RẤT trưởng thành. Tôi không biết làm thế nào trưởng thành một số các thư viện khác (như một regex có sẵn cho C + + từ Boost), nhưng là như hầu hết thời gian xử lý của bạn sẽ được trong thư viện, mối quan tâm ngôn ngữ có thể thứ cấp.

Điểm mấu chốt: sử dụng những gì bạn cảm thấy thoải mái nhất và làm càng nhiều công việc càng tốt trong thư viện vì nó gần như luôn luôn nhanh hơn những gì bạn có thể tự sản xuất, bằng bất kỳ ngôn ngữ nào.

21
  • Trình phân tích cú pháp dựa trên regex được viết một cách ngây thơ sẽ nhanh hơn trình phân tích cú pháp dựa trên regex C được viết một cách ngây thơ.
  • Trình phân tích cú pháp dựa trên regex Perl được viết tốt sẽ là nhanh hơn nhanh hơn trình phân tích cú pháp dựa trên regex C được viết một cách ngây thơ.
  • Trình phân tích cú pháp dựa trên regex C được viết tốt sẽ nhanh hơn một chút so với trình phân tích cú pháp dựa trên regex Perl được viết tốt. (Nó cũng sẽ khó gấp đôi và khó hơn gấp mười lần.)
+1

Ai nói anh ta đang sử dụng một trình phân tích cú pháp dựa trên regex trong C? Nếu tốc độ là một mối quan tâm (do đó lái xe một người nào đó đến C), tại sao trên trái đất ai đó sẽ sử dụng phân tích cú pháp regex chậm? –

+2

(1) regex là cách nhanh nhất để phân tích cú pháp mọi thứ ... đặc biệt là nhật ký. (2) một trình phân tích cú pháp dựa trên regex c viết bằng văn bản sẽ khó hơn 100 lần để viết/gỡ lỗi hơn trình phân tích cú pháp perl ... vì perl regexen "Just Work (TM)" – Massa

+1

Vâng, nó không nhanh hơn thiết kế FSM để phân tích cú pháp trường hợp cụ thể của bạn. Nó có thể là cơ chế nhanh nhất với bất kỳ tính tổng quát nào, vì vậy nó nhanh hơn * viết * một regex hơn là viết một trình phân tích cú pháp tương đương. Trong khó khăn gỡ lỗi, tôi giả định một thư viện regex C sẽ được sử dụng, không phải là một công cụ regex tùy chỉnh được xây dựng. – chaos

3

Có, bạn có thể tạo trình phân tích cú pháp nhanh hơn trong C nếu bạn biết mình đang làm gì.

Tuy nhiên, đối với đại đa số mọi người, điều thông minh hơn phải lo lắng sẽ dễ thực hiện và bảo trì mã. Một trình phân tích cú pháp nhanh mà bạn không thể làm việc đúng không ai tốt cả.

1

Nếu bạn phân tích nhật ký ở định dạng nhật ký chung Apache, visitors, được viết bằng C sẽ đánh bại bất kỳ trình phân tích cú pháp nhật ký perl nào có thể so sánh được ít nhất một yếu tố 2.

Vì vậy, hãy tìm các trình phân tích cú pháp hiện có và đánh giá chúng nếu định dạng nhật ký phổ biến.

Trình phân tích cú pháp nhật ký được viết đúng cách trong C sẽ luôn nhanh hơn đáng kể so với trình phân tích cú pháp nhật ký được viết đúng cách trong Perl, dựa trên kinh nghiệm trong quá khứ của tôi.

17

Nếu bạn không kém lành nghề trong C và Perl, câu trả lời rất đơn giản:

  1. Viết nó trong Perl.
  2. Nếu quá chậm, hãy chỉnh sửa và sửa lỗi.
  3. Nếu nó vẫn còn quá chậm, và vấn đề là quá CPU hoặc sử dụng RAM, hãy xem xét cách viết nó trong C.

Nói chung, tôi muốn nói điều này được áp dụng trừ khi bạn là một số loại C godlet rằng có thể khéo léo thao túng các nền tảng của thực tế thông qua thao túng bạo lực của con trỏ và các kiểu chữ.

Nghiêm túc, việc triển khai regex trong perl rất nhanh, linh hoạt và được kiểm tra tốt. Bất kỳ mã nào bạn viết có thể nhanh và linh hoạt, nhưng nó không bao giờ được kiểm tra kỹ lưỡng.

Vì bạn là người mới đối với Perl và regex, điều quan trọng cần nhớ là có resources có thể provide bạn với excellent help nếu bạn cần. Thậm chí còn có một số nice tutorials trong số fine manual.

Dù bạn làm gì, không làm điều này:

for my $line (<$log>) { 
    # parse line here. 
} 

Bạn sẽ đọc toàn bộ tập tin log vào bộ nhớ và nó sẽ mất mãi mãi như hoán đổi hệ thống và giao dịch hoán đổi (và có thể bị treo) của bạn.

Thay vì sử dụng một vòng lặp while:

while (defined(my $line = <$log>)) { 
    # parse line here. 
} 
+2

Tôi không phải là chuyên gia của Perl. Tại sao chính xác cho đoạn mã đang đọc toàn bộ tệp? Liệu nó có liên quan gì đến việc phải biết trước bao nhiêu lần để quay, nhưng trong khi kiểm tra mỗi lần? –

+0

@ Ignas, tôi đã bỏ lỡ nhận xét của bạn, vì vậy bạn có thể không bao giờ thấy điều này. Trong trường hợp bạn tìm đường trở lại đây: 'for' lần đọc đánh giá nội dung của các parens trong ngữ cảnh danh sách. '<>' trong ngữ cảnh danh sách lấy toàn bộ tập tin. 'while' đánh giá mã trong các parens trong ngữ cảnh vô hướng. Trong ngữ cảnh vô hướng, '<>' đọc một dòng tại một thời điểm. – daotoad

+0

vòng lặp while sẽ dừng ở dòng trống đầu tiên, hoặc bất kỳ thứ gì khác mà perl coi là sai. sử dụng trong khi (được xác định (my $ line = <$log>)) thay thế. –

1

Nếu bạn đang đi để được áp dụng biểu thức chính quy cùng với mỗi dòng, đừng quên rằng bạn rất có thể tối ưu hóa việc thực hiện bằng cách thêm các/o cờ mô hình, tức là

if (/ [a-zA-Z] +/o)

Điều này sẽ gây ra các biểu hiện được biên dịch trong nội bộ chỉ một lần và cho kết quả là được sau đó tái sử dụng, thay vì trên mọi vòng lặp lặp liên tiếp.

Được trang bị tính năng nâng cao đó, tôi sẽ rất ngạc nhiên nếu trình phân tích cú pháp Perl của bạn không thực hiện bất kỳ việc triển khai C nào mà bạn có thể thực hiện trong một khoảng thời gian thực tế.

+2

Điều này không đúng (thêm nữa). Trong một thời gian dài, tùy chọn/o cho các biểu thức chính quy hầu như không cần thiết. Nó chỉ có tác dụng nếu bạn nội suy các biến thành cụm từ thông dụng. Nếu không, nó sẽ chỉ được biên dịch một lần. Xem "perldoc perlre". – tsee

+0

Tôi đồng ý. Có vẻ như tác giả muốn nội suy các biến. –

1

Nếu bạn muốn đọc 2 Gb theo perl, tốt hơn nên sử dụng sysread (với kích thước khối lớn, ví dụ: 256k hoặc 512k). PerlIO sử dụng kích thước khối quá nhỏ - 4k, nó không hiệu quả. Xem PerlMonks để biết thêm thông tin về kích thước khối PerlIO.

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