2014-12-04 17 views
5

Gần đây tôi đã được giao nhiệm vụ thực hiện một vài kiểm tra tốc độ để tôi có thể biết liệu có sử dụng php/php-cli hoặc C++ nhanh hơn để chèn một số hàng nhất định vào cơ sở dữ liệu hay không.Chèn MySQL, nhanh hơn trong PHP so với C++, điều này có được mong đợi không?

Trước khi chúng tôi bắt đầu, hãy để tôi nói cho bạn biết một vài chi tiết để mọi thứ thật rõ ràng:

  • Phần php được điều hành thông qua Apache, yêu cầu trực tiếp trong trình duyệt.
  • Các kiểm tra ổ đĩa cứng đang được chạy trên là một ổ SSD. Tôi đoán mọi thứ sẽ chậm hơn trong các ổ đĩa thông thường. Bản thân máy không có gì đặc biệt, sáu tuổi trở lên.
  • Tất cả các lần chèn được thực hiện thông qua các câu lệnh đã chuẩn bị. Chúng tôi đang sử dụng mysqli trên php và mysqlcppconn (mysql C++ connector, do Oracle cung cấp).
  • Tất cả các lần chèn được thực hiện nhập cảnh theo mục nhập. Tôi biết chúng tôi có thể xếp chúng nhưng tốt, chúng tôi đang thử nghiệm ở đây.
  • Thời gian được hiển thị qua microtime trong php và qua tiêu đề bằng C++.
  • Bản thân mã không tương đương, tất nhiên. Thêm về điều đó sau.
  • Tất cả văn bản đều ở dạng UTF-8. Có tiếng Nga, tiếng Trung Quốc, tiếng Ả Rập, tiếng Tây Ban Nha, tiếng Anh và tất cả các loại công cụ điên trong đó. Bảng mysql nằm trong utf8_4mb.
  • Các số cho mã C++ là kết quả của việc sử dụng mức std :: vector và -O2 biên dịch với g ++ (vectơ vượt trội so với bản đồ, unordered_maps và std :: arrays).

Vì vậy, đây là quá trình:

  • Kết nối với cơ sở dữ liệu.
  • Mở tệp văn bản có N dòng.
  • Đọc một dòng của tệp.
  • Tách dòng trên ký tự dấu tách.
  • Sử dụng các phần nhất định của đường phân tách để nhận giá trị chèn (ví dụ: chỉ số 0, 1 và 3).
  • Gửi các phần này cho câu lệnh đã chuẩn bị để chèn chúng.
  • Lặp lại cho đến khi tệp hoàn toàn được đọc.

Cả hai mã đều hoạt động chính xác như mong đợi. Dưới đây là những con số kết quả:

php:

  • 5000 mục: 1,42-1,27 giây.
  • 20000 mục nhập: 5.53 - 6.18 giây.
  • 50000 mục nhập: 14,43 - 15,69 giây.

C++:

  • 5000 mục: 1,78-1,81 giây.
  • 20000 mục nhập: 7,19 - 7,22 giây.
  • 50000 mục nhập: 18.52 - 18.84 giây.

php nhanh hơn so với C++ như các dòng trong tập tin tăng ... Lúc đầu, tôi nghi ngờ của hàm dòng tách: tách trong php được thực hiện với "nổ tung". Các thuật toán là ngây thơ như nó nói đến c + + ... Các container được thông qua tham chiếu và nội dung của nó được thay đổi trên bay. Vùng chứa chỉ được duyệt một lần. Tôi chắc chắn rằng container "dự trữ()" tất cả không gian cần thiết (nhớ, cuối cùng tôi chọn vector) được cố định. Vùng chứa được tạo trên hàm chính và sau đó được truyền qua tham chiếu thông qua mã. Nó không bao giờ được làm trống hoặc thay đổi kích thước: chỉ thay đổi nội dung của nó.

template<typename container> void explode(const std::string& p_string, const char p_delimiter, container& p_result) 
{ 
    auto it=p_result.begin(); 
    std::string::const_iterator beg=p_string.begin(), end=p_string.end(); 
    std::string temp; 

    while(beg < end) 
    { 
     if((*beg)==p_delimiter) 
     { 
      *(it)=temp; 
      ++it; 
      temp=""; 
     } 
     else 
     { 
      temp+=*beg; 
     } 

     ++beg; 
    } 

    *(it)=temp; 
} 

Như đã nói ở trên, tác vụ được thực hiện tương đương, nhưng mã tạo ra nó thì không. Mã C++ có các khối try-catch thông thường để kiểm soát tương tác mysql. Đối với phần còn lại, vòng lặp chính chạy cho đến khi đạt được EOF và mỗi lần lặp lại kiểm tra nếu chèn không thành công (cả trong C++ và php).

Tôi đã thấy C++ vượt trội hơn rất nhiều so với php khi làm việc với tệp và nội dung của chúng, vì vậy tôi mong đợi điều tương tự sẽ được áp dụng tại đây. Bằng cách nào đó tôi nghi ngờ của thuật toán tách nhưng có lẽ nó chỉ là kết nối cơ sở dữ liệu là chậm hơn (vẫn còn, khi tôi bị vô hiệu hóa tương tác ... Read More gprof nhổ này hiểu về C++ mã:

Each sample counts as 0.01 seconds. 
    % cumulative self    self  total   
time seconds seconds calls ns/call ns/call name  
60.00  0.03  0.03 50000 600.00 600.00 void anc_str::explotar_cadena<std::vector<std::string, std::allocator<std::string> > >(std::string const&, char, std::vector<std::string, std::allocator<std::string> >&) 
40.00  0.05  0.02        insertar(sql::PreparedStatement*, std::string const&, std::vector<std::string, std::allocator<std::string> >&) 
    0.00  0.05  0.00  1  0.00  0.00 _GLOBAL__sub_I__ZN7anc_str21obtener_linea_archivoERSt14basic_ifstreamIcSt11char_traitsIcEE 

đâu "explotar_cadena" được "phát nổ" và "insertar" là "chia dòng này và thiết lập báo cáo kết quả chuẩn bị lên". Như bạn có thể thấy 60% thời gian ở đó (không đáng ngạc nhiên ... nó chạy 50000 lần và làm điều này tách điên). "obtener_linea_archivo" chỉ là "xin vui lòng, đổ dòng tiếp theo vào chuỗi".

Nếu không có sự tương tác mysql (chỉ cần tải tập tin, đọc những dòng và tách chúng) tôi nhận được những số đo:

php

  • 5000 mục: 0,019-0,036 giây.
  • 20000 mục nhập: 0,09 - 0,10 giây.
  • 50000 mục nhập: 0,14 - 0,17 giây.

C++

  • 5000 mục: 0,07-0,10 giây.
  • 20000 mục nhập: 0,25 - 0,26 giây.
  • 50000 mục nhập: 0,49 - 0,55 giây.

Được rồi, cả hai lần đều tốt và hầu như không đáng chú ý đối với các thuật ngữ thực tế, tôi ngạc nhiên ... Vì vậy, câu hỏi ở đây là: Tôi có mong đợi điều này không ?. Bất cứ ai có kinh nghiệm trước đây sẵn sàng cho mượn một tay ?.

Xin cảm ơn trước.

Chỉnh sửa: Đây là liên kết nhanh đến phiên bản rút gọn chứa tệp đầu vào, mã C++ và mã php [http://www.datafilehost.com/d/d31034d6]. Lưu ý rằng không có tương tác sql: chỉ mở tệp, tách chuỗi và đo thời gian. Xin vui lòng, tha thứ cho các mã butchered và một nửa ý kiến ​​Tây Ban Nha và tên biến vì điều này đã được thực hiện trong một vội vàng. Ngoài ra, lưu ý các kết quả gprof ở trên: Tôi không có chuyên gia nhưng tôi nghĩ rằng chúng tôi đang cố gắng tìm một cách tốt hơn để tách chuỗi.

+0

bạn có thể thử nghiệm chương trình C++ của mình với [Rất buồn ngủ] (http://www.codersnotes.com/sleepy) và thêm kết quả tại đây hay không. –

+0

Không phải người cửa sổ ở đây, xin lỗi ... Tôi đã thử gprof. Sẽ chỉnh sửa bài đăng để phản ánh điều đó. –

+1

Xóa bộ hẹn giờ khỏi mã, sử dụng lệnh thời gian của hệ thống tại bàn điều khiển để lấy số đo. Bạn không bao gồm thời gian khởi động và tắt máy của PHP, kết quả lệch. –

Trả lời

1

Một số phần của nó có thể liên quan đến trình điều khiển/giao diện được sử dụng trong từng ngôn ngữ. Ví dụ, với PHP/MySQL, có thể bạn sẽ thấy rằng mysqli nhanh hơn mysql, nhanh hơn PDO. Đó là bởi vì các thư viện dần dần trừu tượng hơn (hoặc ít được duy trì). Bạn có thể thử định hình các truy vấn trên máy chủ cơ sở dữ liệu để xem có sự khác biệt nào trong thời gian thực thi hay không. Sau đó, một lần nữa, có thể có nhiều diễn ra, như các nhà bình luận khác đã lưu ý.

+0

Cảm ơn rất nhiều câu trả lời của bạn. Tôi nghĩ rằng tôi có thể giả định rằng việc thực hiện chính nó có nhiều lớp như vậy là chậm hơn. Tuy nhiên, không có bất kỳ tương tác cơ sở dữ liệu nào, tôi nhận được các con số tốt hơn với php (như bạn có thể thấy trong câu hỏi đã chỉnh sửa). Như đã đề cập trước đó, mã C++ dường như tạo ra nhiều hướng dẫn hơn mã php đơn giản hơn. –

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