Tôi mới sử dụng java và đã chạy một số mã tối qua và điều này thực sự làm phiền tôi. Tôi đang xây dựng một chương trình đơn giản để hiển thị mọi đầu ra X trong một vòng lặp for và tôi nhận thấy hiệu suất giảm MASSIVE, khi tôi sử dụng mô-đun là variable % variable
vs variable % 5000
hoặc không có gì. Ai đó có thể giải thích cho tôi tại sao điều này là và những gì gây ra nó? Vì vậy, tôi có thể tốt hơn ...
Đây là mã "hiệu quả" (xin lỗi nếu tôi có một chút cú pháp sai Tôi không ở trên máy tính với mã ngay bây giờ)
long startNum = 0;
long stopNum = 1000000000L;
for (long i = startNum; i <= stopNum; i++){
if (i % 50000 == 0) {
System.out.println(i);
}
}
Đây là "mã không hiệu quả"
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 50000;
for (long i = startNum; i <= stopNum; i++){
if (i % progressCheck == 0) {
System.out.println(i);
}
}
Hãy nhớ rằng tôi có một biến số ngày để đo lường sự khác biệt và một khi nó đủ dài, cái đầu tiên mất 50ms trong khi cái kia mất 12 giây hoặc tương tự. Bạn có thể phải tăng stopNum
hoặc giảm progressCheck
nếu PC của bạn hiệu quả hơn máy của tôi hoặc không.
Tôi đã tìm câu hỏi này trên web, nhưng tôi không thể tìm thấy câu trả lời, có lẽ tôi chỉ không hỏi đúng.
EDIT: Tôi không mong đợi câu hỏi của tôi sẽ phổ biến đến vậy, tôi đánh giá cao tất cả các câu trả lời. Tôi đã thực hiện một điểm chuẩn trên mỗi nửa thời gian thực hiện và mã không hiệu quả mất nhiều thời gian hơn, 1/4 giây so với 10 giây cho hoặc mất. Cứ cho là họ đang sử dụng println, nhưng cả hai đều làm cùng một số tiền, vì vậy tôi sẽ không tưởng tượng rằng nó sẽ làm lệch nó nhiều, đặc biệt là vì sự khác biệt có thể lặp lại. Về câu trả lời, vì tôi chưa quen với Java, tôi sẽ để phiếu bầu quyết định xem câu trả lời nào là tốt nhất. Tôi sẽ cố gắng chọn một vào thứ Tư.
EDIT2: Tôi sẽ thực hiện một thử nghiệm khác vào tối nay, trong đó thay vì mô-đun, nó chỉ tăng một biến và khi đạt đến tiến trình, nó sẽ thực hiện một thử nghiệm, sau đó đặt lại biến đó thành 0. cho tùy chọn thứ 3.
EDIT3,5:
Tôi đã sử dụng mã này và dưới đây tôi sẽ hiển thị kết quả của mình .. Cảm ơn TẤT CẢ vì sự giúp đỡ tuyệt vời! Tôi cũng đã thử so sánh giá trị ngắn của dài với 0, vì vậy tất cả các kiểm tra mới của tôi xảy ra bao giờ "65536" làm cho nó bằng nhau trong các lần lặp lại.
public class Main {
public static void main(String[] args) {
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 65536;
final long finalProgressCheck = 50000;
long date;
// using a fixed value
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if (i % 65536 == 0) {
System.out.println(i);
}
}
long final1 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
//using a variable
for (long i = startNum; i <= stopNum; i++) {
if (i % progressCheck == 0) {
System.out.println(i);
}
}
long final2 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using a final declared variable
for (long i = startNum; i <= stopNum; i++) {
if (i % finalProgressCheck == 0) {
System.out.println(i);
}
}
long final3 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
// using increments to determine progressCheck
int increment = 0;
for (long i = startNum; i <= stopNum; i++) {
if (increment == 65536) {
System.out.println(i);
increment = 0;
}
increment++;
}
//using a short conversion
long final4 = System.currentTimeMillis() - date;
date = System.currentTimeMillis();
for (long i = startNum; i <= stopNum; i++) {
if ((short)i == 0) {
System.out.println(i);
}
}
long final5 = System.currentTimeMillis() - date;
System.out.println(
"\nfixed = " + final1 + " ms " + "\nvariable = " + final2 + " ms " + "\nfinal variable = " + final3 + " ms " + "\nincrement = " + final4 + " ms" + "\nShort Conversion = " + final5 + " ms");
}
}
Các kết quả:
- Đã sửa = 874 ms (thường là khoảng 1000ms, nhưng nhanh hơn do nó là công suất 2)
- biến = 8590 ms
- biến cuối cùng = 1944 ms (Được ~ 1000ms khi sử dụng 50000)
- gia tăng = 1904 ms
- Chuyển đổi ngắn = 679 ms
Không đủ ngạc nhiên, do thiếu sự phân chia, Chuyển đổi ngắn nhanh hơn 23% so với cách "nhanh". Đây là điều thú vị cần lưu ý. Nếu bạn cần hiển thị hoặc so sánh một cái gì đó cứ sau 256 lần (hoặc về đó), bạn có thể làm điều này và sử dụng
if ((byte)integer == 0) {'Perform progress check code here'}
MỘT LƯU Ý QUAN TÂM CUỐI CÙNG, sử dụng mô-đun trên "Biến được khai báo cuối cùng" với 65536 (không phải là một số đẹp) là một nửa tốc độ (chậm hơn) so với giá trị cố định. Trường hợp trước khi nó được điểm chuẩn gần cùng tốc độ.
final
vào trướcprogressCheck
biến, cả hai đều chạy cùng tốc độ một lần nữa. Điều đó khiến tôi tin rằng trình biên dịch hoặc JIT quản lý để tối ưu hóa vòng lặp khi nó biết đóprogressCheck
là hằng số.