2009-10-19 37 views
11

Tôi đã viết một chương trình cơ bản Hippity Hop trong C, Python và OCaml. Cấp, điều này có lẽ không phải là một điểm chuẩn rất tốt của ba ngôn ngữ này. Nhưng kết quả tôi nhận được là một cái gì đó như thế này:Tại sao chương trình OCaml này nhanh hơn chương trình C của tôi?

  • Python: 0,350 giây
  • C: 0,050 giây
  • giải thích OCaml: 0,040 giây
  • biên soạn OCaml: 0,010

Hiệu suất trăn không thực sự gây ngạc nhiên cho tôi, nhưng tôi khá sốc khi thấy OCaml nhanh như thế nào (đặc biệt là phiên bản phiên dịch). Để so sánh, tôi sẽ đăng phiên bản C và phiên bản OCaml.

C

#include <stdio.h> 
#include <stdlib.h> 
#include <assert.h> 

long get_count(char *name); 

int main(int argc, char *argv[]) 
{ 
    if (argc != 2){ 
    printf("Filename must be specified as a positional argument.\n"); 
    exit(EXIT_FAILURE); 
    } 

    long count_no = get_count(argv[1]); 

    int i; 
    for (i = 1; i <= count_no; i++){ 
    if (((i % 3) == 0) && ((i % 5) == 0)){ 
     printf("Hop\n"); 
     continue; 
    } 
    if ((i % 3) == 0){ 
     printf("Hoppity\n"); 
    } 
    if ((i % 5) == 0){ 
     printf("Hophop\n"); 
    } 
    } 
    return 0; 
} 

long get_count(char *name){ 
    FILE *fileptr = fopen(name, "r"); 
    if (!fileptr){ 
    printf("Unable to open file %s.\n", name); 
    exit(EXIT_FAILURE); 
    } 
    size_t text_len = 20; 
    char *file_text = calloc(text_len, sizeof(char)); 
    while (!feof(fileptr)){ 
    fread(file_text, sizeof(char), text_len, fileptr); 
    assert(!ferror(fileptr)); 
    text_len += 20; 
    file_text = realloc(file_text, text_len * sizeof(char)); 
    } 
    long file_as_int = strtol(file_text, NULL, 10); 

    free(file_text); 
    return file_as_int; 
} 

OCaml

open String;; 

let trim str = 
    if str = "" then "" else 
    let search_pos init p next = 
    let rec search i = 
     if p i then raise(Failure "empty") else 
     match str.[i] with 
     | ' ' | '\n' | '\r' | '\t' -> search (next i) 
     | _ -> i 
    in 
    search init 
    in 
    let len = String.length str in 
    try 
    let left = search_pos 0 (fun i -> i >= len) (succ) 
    and right = search_pos (len - 1) (fun i -> i < 0) (pred) 
    in 
    String.sub str left (right - left + 1) 
    with 
    | Failure "empty" -> "" 
;; 

let rec iterate_over_numbers curr_num max_num = 
    (
    if curr_num <= max_num then (
    if ((curr_num mod 3) == 0) && ((curr_num mod 5) == 0) then 
     print_endline "Hop" 
    else if (curr_num mod 3) == 0 then 
     print_endline "Hoppity" 
    else if (curr_num mod 5) == 0 then 
     print_endline "Hophop"; 
    iterate_over_numbers (curr_num + 1) max_num 
    )) 
;; 


let fname = Sys.argv.(1);; 
let infile = open_in fname;; 
let file_text = trim (input_line infile);; 
close_in infile;; 
let input_number = int_of_string file_text;; 
iterate_over_numbers 1 input_number;; 

Nhưng tôi tò mò muốn biết lý do tại sao tôi nhận được những kết quả này. Tôi đang làm điều gì đó câm trong chương trình C của tôi, hay đây chỉ là một cái gì đó OCaml nhanh hơn? Dường như với tôi một chút lạ rằng một chương trình giải thích đang chạy nhanh hơn một chút so với phiên bản C, và chương trình biên dịch chạy nhanh gấp 5 lần.

+0

Trình chuyển đổi trình biên dịch nào bạn đã sử dụng cho phiên bản C? –

+0

@ Jonathan - Tôi chỉ làm một 'gcc -o hoppity main.c'. Tôi không nghĩ về việc thiết lập một mức độ tối ưu để trung thực. :-) –

+0

Số trong tệp khi thử nghiệm được chạy là gì? Và đầu ra có được chuyển hướng đến một tệp hoặc một đường ống giống nhau cho tất cả các thử nghiệm không? Và thật thú vị khi biết hiệu suất tương đối với 'gcc' và 'gcc -O'. –

Trả lời

8

mã C của bạn không phải là tương đương với mã OCaml - bạn sử dụng 'else if' trong OCaml để tránh phải recompute môđun khá nhiều.

Có nhiều mã khủng khiếp trong đó 'đọc số nguyên dài'. Tại sao không chỉ sử dụng fscanf(); Tôi không thường khuyên bạn nên sử dụng fscanf(), nhưng điều này trông giống như một thiết lập cho nó - một dòng duy nhất, có thể với không gian hai bên, không có công cụ vui nhộn.


Sự tò mò giết chết con mèo - nhưng trong trường hợp này, không phải là Leopard.

Tôi đã tải xuống OCaml 3.11.1 cho MacOS X Intel và sao chép mã OCaml từ câu hỏi vào xxx.ml (OCaml) và biên dịch thành một tệp đối tượng xxx (sử dụng "ocamlc -o xxx xxx.ml") ; Tôi đã sao chép nguyên văn mã C vào yyy.c và tạo một biến thể zzz.c bằng cách sử dụng fscanf()fclose() và biên dịch chúng bằng cách sử dụng "gcc -O -o yyy yyy.c" và "gcc -O -o zzz zzz.c". Tôi đã tạo một tệp 'file3' chứa: "987654" cộng với dòng mới. Tôi tạo ra một kịch bản shell runthem.sh như được hiển thị. Lưu ý rằng 'thời gian' là một lệnh pesky mà nghĩ rằng đầu ra của nó phải đi đến stderr ngay cả khi bạn muốn nó không - bạn phải làm việc khá khó khăn để có được sản lượng mà bạn muốn nó đi. (Lệnh phạm vi tạo ra con số trong phạm vi nhất định, bao gồm -. Vì thế 11 giá trị cho mỗi chương trình)

Osiris JL: cat runthem.sh 
for prog in "ocaml xxx.ml" ./xxx ./yyy ./zzz 
do 
    for iter in $(range 0 10) 
    do 
     r=$(sh -c "time $prog file3 >/dev/null" 2>&1) 
     echo $prog: $r 
    done 
done 
Osiris JL: 

tôi chạy tất cả điều này trên MacBook Pro hiện đại (3 GHz Core 2 Duo vv, 4GB RAM) chạy Leopard (10.5.8). Thời gian tôi nhận được hiển thị theo:

Osiris JL: sh runthem.sh 
ocaml xxx.ml: real 0m0.961s user 0m0.524s sys 0m0.432s 
ocaml xxx.ml: real 0m0.953s user 0m0.516s sys 0m0.430s 
ocaml xxx.ml: real 0m0.959s user 0m0.517s sys 0m0.431s 
ocaml xxx.ml: real 0m0.951s user 0m0.517s sys 0m0.430s 
ocaml xxx.ml: real 0m0.952s user 0m0.516s sys 0m0.431s 
ocaml xxx.ml: real 0m0.952s user 0m0.514s sys 0m0.431s 
ocaml xxx.ml: real 0m0.951s user 0m0.515s sys 0m0.431s 
ocaml xxx.ml: real 0m0.959s user 0m0.515s sys 0m0.431s 
ocaml xxx.ml: real 0m0.950s user 0m0.515s sys 0m0.431s 
ocaml xxx.ml: real 0m0.956s user 0m0.516s sys 0m0.431s 
ocaml xxx.ml: real 0m0.952s user 0m0.514s sys 0m0.432s 
./xxx: real 0m0.928s user 0m0.494s sys 0m0.430s 
./xxx: real 0m0.938s user 0m0.494s sys 0m0.430s 
./xxx: real 0m0.927s user 0m0.494s sys 0m0.430s 
./xxx: real 0m0.928s user 0m0.492s sys 0m0.430s 
./xxx: real 0m0.928s user 0m0.493s sys 0m0.430s 
./xxx: real 0m0.927s user 0m0.493s sys 0m0.430s 
./xxx: real 0m0.928s user 0m0.492s sys 0m0.430s 
./xxx: real 0m0.933s user 0m0.497s sys 0m0.428s 
./xxx: real 0m0.926s user 0m0.494s sys 0m0.429s 
./xxx: real 0m0.921s user 0m0.492s sys 0m0.428s 
./xxx: real 0m0.925s user 0m0.494s sys 0m0.428s 
./yyy: real 0m0.027s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.031s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.029s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.029s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.031s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./yyy: real 0m0.030s user 0m0.026s sys 0m0.002s 
./yyy: real 0m0.028s user 0m0.026s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
./zzz: real 0m0.029s user 0m0.027s sys 0m0.001s 
./zzz: real 0m0.030s user 0m0.027s sys 0m0.002s 
Osiris JL: 

Tôi không thấy mã OCaml chạy nhanh hơn mã C. Tôi chạy cái test với số lượng nhỏ trong file đã được đọc, và kết quả là tương tự ủng hộ của mã C:

Dừng số: 345

ocaml xxx.ml: real 0m0.027s user 0m0.020s sys 0m0.005s 
ocaml xxx.ml: real 0m0.021s user 0m0.016s sys 0m0.005s 
ocaml xxx.ml: real 0m0.025s user 0m0.016s sys 0m0.004s 
ocaml xxx.ml: real 0m0.020s user 0m0.015s sys 0m0.003s 
ocaml xxx.ml: real 0m0.022s user 0m0.016s sys 0m0.004s 
ocaml xxx.ml: real 0m0.019s user 0m0.015s sys 0m0.003s 
ocaml xxx.ml: real 0m0.021s user 0m0.016s sys 0m0.004s 
ocaml xxx.ml: real 0m0.020s user 0m0.015s sys 0m0.004s 
ocaml xxx.ml: real 0m0.021s user 0m0.016s sys 0m0.004s 
ocaml xxx.ml: real 0m0.020s user 0m0.015s sys 0m0.004s 
ocaml xxx.ml: real 0m0.021s user 0m0.016s sys 0m0.004s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.002s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.002s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.005s user 0m0.001s sys 0m0.002s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.002s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./xxx: real 0m0.003s user 0m0.001s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.003s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.001s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.002s user 0m0.000s sys 0m0.001s 
./yyy: real 0m0.003s user 0m0.000s sys 0m0.002s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.001s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.003s user 0m0.000s sys 0m0.002s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 
./zzz: real 0m0.002s user 0m0.000s sys 0m0.001s 

Dừng số: 87654

ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.041s 
ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.101s user 0m0.060s sys 0m0.040s 
ocaml xxx.ml: real 0m0.103s user 0m0.059s sys 0m0.041s 
ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.041s 
ocaml xxx.ml: real 0m0.101s user 0m0.059s sys 0m0.041s 
ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.103s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.101s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.102s user 0m0.059s sys 0m0.040s 
ocaml xxx.ml: real 0m0.105s user 0m0.059s sys 0m0.041s 
./xxx: real 0m0.092s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.087s user 0m0.044s sys 0m0.039s 
./xxx: real 0m0.085s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.084s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.085s user 0m0.044s sys 0m0.039s 
./xxx: real 0m0.086s user 0m0.045s sys 0m0.039s 
./xxx: real 0m0.085s user 0m0.044s sys 0m0.039s 
./xxx: real 0m0.085s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.084s user 0m0.044s sys 0m0.038s 
./xxx: real 0m0.084s user 0m0.044s sys 0m0.039s 
./xxx: real 0m0.083s user 0m0.044s sys 0m0.038s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.005s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.005s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.004s user 0m0.003s sys 0m0.001s 
./yyy: real 0m0.006s user 0m0.003s sys 0m0.002s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.005s user 0m0.003s sys 0m0.002s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.004s user 0m0.003s sys 0m0.001s 
./zzz: real 0m0.005s user 0m0.003s sys 0m0.001s 

Rõ ràng, YMMV - nhưng dường như OCaml chậm hơn C bằng một biên độ đáng kể, nhưng nếu số trong tệp đã cho đủ nhỏ, thì bắt đầu và đọc tệp chiếm ưu thế trong thời gian xử lý.

Thời gian C, đặc biệt là ở các số nhỏ hơn, quá nhanh đến nỗi chúng không đáng tin cậy lắm.

+0

FYI, không một trong số này dường như đã tạo ra sự khác biệt lớn về hiệu suất. Mặc dù sử dụng fscanf không làm cho mã dễ đọc hơn nhiều! –

+0

Thú vị: như tôi đã hỏi trong phần bình luận cho câu hỏi chính - số lượng lớn mà bạn được đưa ra là bao nhiêu?Và điều gì sẽ xảy ra nếu bạn lặp lại N lần (trong đó N là một số đủ lớn để có được chương trình nhanh nhất để mất một khoảng thời gian của giây)? Đừng quên bạn sẽ cần phải đóng tập tin nếu bạn làm 10.000 lần lặp lại. –

8

Thời gian dưới 0,05 có thể là một tiếng ồn đơn giản. Lặp lại chương trình chính đủ thời gian để thực sự nhận được ~ 1s thời gian thực hiện trong C. (Tôi có nghĩa là lặp lại nó trong một vòng lặp trong chương trình, không phải bằng cách chạy lại nó)

Bạn đã biên dịch mã của bạn với tối ưu hóa chưa? Bạn đã thử giảm số lượng chi nhánh? (và so sánh)

if (i % 3 == 0) { 
    if (i % 5 == 0) { 
    printf("Hop\n"); 
    continue; 
    } 
    printf("Hoppity\n"); 
} else if (i % 5 == 0){ 
    printf("Hophop\n"); 
} 

Bạn đã thử xem đầu ra của bộ kết hợp?

Cũng printf khá chậm. Thay vào đó, hãy thử puts("Hop") vì bạn không sử dụng anyways định dạng.

+0

Điều đó có thể, nhưng bạn phải thử nghiệm nó . Thời gian bạn lưu vào mỗi lần thử 15 '(bạn chỉ thực hiện 1 lần kiểm tra) có thể không cân bằng thời gian bạn thua trên những con số thực hiện 3 lần kiểm tra. Chỉ thử nghiệm mới có thể biết điều đó :) (nhận xét về đề xuất kiểm tra i% 15, i% 3, i% 5 - nó đã bị xóa sau) – viraptor

+0

Vâng, tôi đã xóa nó vì lỗi đánh máy, sau đó nhận ra nó sẽ không hiệu quả hơn, vì vậy tôi đã xóa nó. –

+0

Cho đến nay, có vẻ như * * nhanh hơn nếu tôi bật cấp độ tối ưu hóa. –

1

Tôi muốn biết số tiền được chi tiêu trong get_count().

Tôi không chắc nó sẽ quan trọng như thế nào, nhưng bạn đang đọc trong một chuỗi dài, có nghĩa là chuỗi không được lớn hơn 20 byte hoặc 10 byte (2^64 = khoảng 20 ký tự số thập phân, hoặc 2^32 = một số số thập phân dài 10 ký tự), vì vậy bạn không cần vòng lặp while trong get_count. Ngoài ra, bạn có thể phân bổ file_text trên stack, thay vì gọi calloc - nhưng tôi đoán bạn vẫn cần phải zero nó ra, hoặc nếu không tìm thấy độ dài và đặt byte cuối cùng thành null.

file_length = lseek(fileptr, 0, SEEK_END); 
+0

Điểm thú vị. Tôi cho rằng bộ nhớ tái phân bổ lặp đi lặp lại sẽ khá không hiệu quả. Tôi cho rằng tôi chỉ cần làm quen với trình biên dịch C. :-) –

+0

Sử dụng đề xuất fscanf của Jonathan ở trên cho biến cục bộ, có vẻ như điều này không tạo ra sự khác biệt lớn. –

1

Bất kỳ chương trình nào chủ yếu liên quan đến việc mở tệp và đọc tệp bị giới hạn bởi tốc độ mở tệp và đọc tệp. Các tính toán C bạn đang thực hiện ở đây sẽ mất từ ​​một phần triệu đến một phần nghìn thời gian mở tệp và đọc nó.

Tôi nghĩ trang web này hữu ích: http://norvig.com/21-days.html#answers

+0

Nếu điều này đúng, sẽ không có sự khác biệt nào giữa C và OCaml (vì cả hai đều bị ràng buộc bởi đĩa IO). OP đã chỉ ra rằng mã C đã nhanh hơn nhiều khi anh ta bật mức tối ưu hóa, vì vậy tôi nghi ngờ rằng đây có thể là vấn đề. –

+0

Nhưng thời gian cần để truy cập tệp là hoàn toàn ngẫu nhiên. Nếu tệp vẫn được lưu trong bộ nhớ cache, nó sẽ tốn ít thời gian hơn nếu chương trình bắt đầu lạnh. Nếu anh ta chạy OCaml đầu tiên và C giây, C có lẽ sẽ thắng. Nếu anh ta chạy chương trình C hơn một triệu lần, thời gian trung bình sẽ giảm đáng kể. –

+0

@Kinopiko - Tôi thực sự đang chạy các bản sao này đối với các bản sao trùng lặp của cùng một tệp. –

2

Trong một chương trình nhỏ như thế này, rất khó để đoán tại sao mọi thứ hoạt động theo cách họ làm. Tôi nghĩ rằng nếu tôi đã làm việc đó, tôi muốn viết mã như thế này (bỏ đi kiểm tra lỗi cho thời điểm hiện tại):

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) { 
    static char buffer[20]; 
    int limit, i; 

    freopen(argv[1], "r", stdin); 
fgets(buffer, sizeof(buffer), stdin); 
    limit = atoi(buffer); 

    for (i=1; i<=limit; i++) { 
     int div3=i%3==0; 
     int div5=i%5==0; 
     if (div3 && div5) 
      puts("Hop"); 
     else if (div3) 
      puts("Hoppity"); 
     else if (div5) 
      puts("HopHop"); 
    } 
    return 0; 
} 

Sử dụng freopen tránh tạo ra một dòng tập tin, và thay vào đó chỉ cần kết nối đầu vào tiêu chuẩn để xác định tập tin. Không đảm bảo rằng nó nhanh hơn, nhưng nó không có bất kỳ chậm hơn nào. Tương tự như vậy, một trình biên dịch tốt có thể lưu ý rằng i là không đổi trong toàn bộ vòng lặp, và đưa ra hai hoạt động còn lại để nó chỉ hoạt động mỗi lần một lần. Ở đây tôi đã làm điều đó bằng tay, có thể không nhanh hơn, nhưng gần như chắc chắn sẽ không chậm hơn.

Sử dụng puts thay vì printf tương đối giống nhau - có thể không nhanh hơn, nhưng gần như chắc chắn sẽ không chậm hơn.Bằng cách sử dụng printf theo cách bạn có, nó phải quét qua toàn bộ chuỗi tìm kiếm '%', trong trường hợp bạn yêu cầu chuyển đổi, nhưng vì puts không thực hiện bất kỳ chuyển đổi nào, nó không phải thực hiện điều đó .

Với một chương trình nhỏ như vậy, có một yếu tố khác có thể đáng kể hơn: puts thường nhỏ hơn đáng kể so với printf. Bạn đã không nói làm thế nào bạn đang làm thời gian, nhưng nếu nó bao gồm thời gian để tải mã, mã thực sự nhỏ cũng có thể làm cho sự khác biệt nhiều hơn thời gian thực hiện.

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