ฉันยังใหม่กับ java และใช้รหัสบางคืนเมื่อคืนและนี่รบกวนฉันจริงๆ ฉันกำลังสร้างโปรแกรมง่าย ๆ เพื่อแสดงเอาต์พุต X ทุกอันในลูป for และฉันสังเกตเห็นว่าประสิทธิภาพลดลงอย่างมากเมื่อฉันใช้โมดูลัสเป็นvariable % variable
vs variable % 5000
หรือ whatnot มีคนอธิบายให้ฉันฟังได้ไหมว่าเพราะอะไรและสาเหตุคืออะไร ดังนั้นฉันจะดีกว่า ...
นี่คือรหัส "ประสิทธิภาพ" (ขออภัยถ้าฉันได้รับไวยากรณ์เล็กน้อยผิดฉันไม่ได้อยู่ในคอมพิวเตอร์ด้วยรหัสตอนนี้)
long startNum = 0;
long stopNum = 1000000000L;
for (long i = startNum; i <= stopNum; i++){
if (i % 50000 == 0) {
System.out.println(i);
}
}
นี่คือ "รหัสไม่มีประสิทธิภาพ"
long startNum = 0;
long stopNum = 1000000000L;
long progressCheck = 50000;
for (long i = startNum; i <= stopNum; i++){
if (i % progressCheck == 0) {
System.out.println(i);
}
}
โปรดทราบว่าฉันมีตัวแปรวันที่เพื่อวัดความแตกต่างและเมื่อมันนานพอตัวแรกจะใช้เวลา 50 มิลลิวินาทีในขณะที่อีกอันใช้เวลา 12 วินาทีหรืออย่างนั้น คุณอาจจะต้องเพิ่มstopNum
หรือลดระดับprogressCheck
หากพีซีของคุณมีประสิทธิภาพมากกว่าของฉันหรืออะไรก็ตาม
ฉันมองหาคำถามนี้ในเว็บ แต่ฉันไม่สามารถหาคำตอบได้บางทีฉันอาจจะไม่ได้ถามก็ได้
แก้ไข: ฉันไม่ได้คาดหวังว่าคำถามของฉันจะได้รับความนิยมฉันชื่นชมคำตอบทั้งหมด ฉันทำการวัดประสิทธิภาพในแต่ละครึ่งของเวลาและรหัสที่ไม่มีประสิทธิภาพใช้เวลานานกว่า 1/4 ของวินาทีกับ 10 วินาทีหรือให้ ได้รับพวกเขากำลังใช้ println แต่พวกเขาทั้งสองทำในปริมาณที่เท่ากันดังนั้นฉันจะไม่คิดว่ามันจะเอียงมากโดยเฉพาะอย่างยิ่งเนื่องจากความแตกต่างสามารถทำซ้ำได้ สำหรับคำตอบเนื่องจากฉันยังใหม่กับ Java ฉันจะให้คะแนนตัดสินใจตอนนี้คำตอบที่ดีที่สุด ฉันจะพยายามเลือกวันพุธ
EDIT2: ฉันจะทำการทดสอบอื่นคืนนี้แทนโมดูลัสมันแค่เพิ่มตัวแปรและเมื่อมาถึง progressCheck มันจะดำเนินการอย่างใดอย่างหนึ่งแล้วรีเซ็ตตัวแปรเป็น 0 สำหรับตัวเลือกที่ 3
EDIT3.5:
ฉันใช้รหัสนี้และด้านล่างฉันจะแสดงผลลัพธ์ของฉัน .. ขอบคุณทุกท่านสำหรับความช่วยเหลือที่ยอดเยี่ยม! ฉันยังลองเปรียบเทียบค่าสั้น ๆ ของความยาวเป็น 0 ดังนั้นเช็คใหม่ของฉันจะเกิดขึ้นตลอดเวลา "65536" ครั้งทำให้เท่ากันซ้ำ
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");
}
}
ผล:
- fixed = 874 ms (ปกติประมาณ 1,000 มิลลิวินาที แต่เร็วขึ้นเนื่องจากมันเป็นกำลัง 2)
- ตัวแปร = 8590 ms
- ตัวแปรสุดท้าย = 1944 ms (คือ ~ 1000ms เมื่อใช้ 50000)
- increment = 1904 ms
- การแปลงสั้น = 679 ms
ไม่น่าแปลกใจที่เพียงพอเนื่องจากขาดการแบ่งแยกการแปลงสั้นจึงเร็วกว่าวิธีที่ "เร็ว" 23% นี่เป็นเรื่องที่น่าสนใจ หากคุณต้องการแสดงหรือเปรียบเทียบทุก ๆ 256 ครั้ง (หรือประมาณนั้น) คุณสามารถทำได้และใช้
if ((byte)integer == 0) {'Perform progress check code here'}
หมายเหตุสุดท้ายที่น่าสนใจโดยใช้โมดูลัสของ "ตัวแปรที่ประกาศครั้งสุดท้าย" กับ 65536 (ไม่ใช่ตัวเลขที่สวย) คือความเร็วครึ่งหนึ่งของ (ช้ากว่า) กว่าค่าคงที่ ที่ไหนก่อนที่มันจะถูกเปรียบเทียบใกล้กับความเร็วเดียวกัน
final
ด้านหน้าของprogressCheck
ตัวแปรทั้งคู่ก็วิ่งด้วยความเร็วเดียวกันอีกครั้ง ที่ทำให้ฉันเชื่อว่าคอมไพเลอร์หรือ JIT จัดการเพื่อเพิ่มประสิทธิภาพการวนรอบเมื่อรู้ว่าprogressCheck
คงที่