जावा और C # में अपवाद प्रदर्शन वांछित होने के लिए बहुत कुछ छोड़ देता है।
प्रोग्रामर के रूप में यह हमें नियम के अनुसार जीने के लिए मजबूर करता है "अपवादों को बार-बार होना चाहिए", बस व्यावहारिक प्रदर्शन कारणों से।
हालांकि, कंप्यूटर वैज्ञानिकों के रूप में, हमें इस समस्याग्रस्त स्थिति के खिलाफ विद्रोह करना चाहिए। किसी फ़ंक्शन को लिखने वाले व्यक्ति को अक्सर पता नहीं होता है कि इसे कितनी बार कहा जाएगा, या सफलता या असफलता की संभावना अधिक है। केवल कॉल करने वाले के पास यह जानकारी होती है। अपवादों से बचने की कोशिश करने से एपीआई मुहावरों का पता नहीं चलता है जहां कुछ मामलों में हमारे पास केवल स्वच्छ-लेकिन-धीमी अपवाद वाले संस्करण हैं, और अन्य मामलों में हमारे पास तेजी से-लेकिन-क्लूनी वापसी-मूल्य त्रुटियां हैं, और अभी भी अन्य मामलों में हम दोनों के साथ समाप्त होते हैं । पुस्तकालय कार्यान्वयनकर्ता को एपीआई के दो संस्करणों को लिखना और बनाए रखना पड़ सकता है, और कॉल करने वाले को यह तय करना होगा कि प्रत्येक स्थिति में दो संस्करणों में से किसका उपयोग करना है।
यह एक तरह से गड़बड़ी है। यदि अपवादों का प्रदर्शन बेहतर था, तो हम इन भद्दे मुहावरों से बच सकते हैं और अपवादों का उपयोग कर सकते हैं क्योंकि उनका उपयोग किया जाना था ... एक संरचित त्रुटि वापसी सुविधा के रूप में।
मैं वास्तव में रिटर्न-वैल्यू के करीब तकनीकों का उपयोग करके लागू किए गए अपवाद तंत्र को देखना चाहता हूं, इसलिए हम प्रदर्शन मूल्यों के करीब प्रदर्शन कर सकते हैं .. क्योंकि यह वही है जो हम प्रदर्शन संवेदनशील कोड में वापस करते हैं।
यहां एक कोड-नमूना है जो अपवाद प्रदर्शन की तुलना त्रुटि-वापसी-मूल्य प्रदर्शन से करता है।
पब्लिक क्लास टेस्ट {
int value;
public int getValue() {
return value;
}
public void reset() {
value = 0;
}
public boolean baseline_null(boolean shouldfail, int recurse_depth) {
if (recurse_depth <= 0) {
return shouldfail;
} else {
return baseline_null(shouldfail,recurse_depth-1);
}
}
public boolean retval_error(boolean shouldfail, int recurse_depth) {
if (recurse_depth <= 0) {
if (shouldfail) {
return false;
} else {
return true;
}
} else {
boolean nested_error = retval_error(shouldfail,recurse_depth-1);
if (nested_error) {
return true;
} else {
return false;
}
}
}
public void exception_error(boolean shouldfail, int recurse_depth) throws Exception {
if (recurse_depth <= 0) {
if (shouldfail) {
throw new Exception();
}
} else {
exception_error(shouldfail,recurse_depth-1);
}
}
public static void main(String[] args) {
int i;
long l;
TestIt t = new TestIt();
int failures;
int ITERATION_COUNT = 100000000;
// (0) baseline null workload
for (int recurse_depth = 2; recurse_depth <= 10; recurse_depth+=3) {
for (float exception_freq = 0.0f; exception_freq <= 1.0f; exception_freq += 0.25f) {
int EXCEPTION_MOD = (exception_freq == 0.0f) ? ITERATION_COUNT+1 : (int)(1.0f / exception_freq);
failures = 0;
long start_time = System.currentTimeMillis();
t.reset();
for (i = 1; i < ITERATION_COUNT; i++) {
boolean shoulderror = (i % EXCEPTION_MOD) == 0;
t.baseline_null(shoulderror,recurse_depth);
}
long elapsed_time = System.currentTimeMillis() - start_time;
System.out.format("baseline: recurse_depth %s, exception_freqeuncy %s (%s), time elapsed %s ms\n",
recurse_depth, exception_freq, failures,elapsed_time);
}
}
// (1) retval_error
for (int recurse_depth = 2; recurse_depth <= 10; recurse_depth+=3) {
for (float exception_freq = 0.0f; exception_freq <= 1.0f; exception_freq += 0.25f) {
int EXCEPTION_MOD = (exception_freq == 0.0f) ? ITERATION_COUNT+1 : (int)(1.0f / exception_freq);
failures = 0;
long start_time = System.currentTimeMillis();
t.reset();
for (i = 1; i < ITERATION_COUNT; i++) {
boolean shoulderror = (i % EXCEPTION_MOD) == 0;
if (!t.retval_error(shoulderror,recurse_depth)) {
failures++;
}
}
long elapsed_time = System.currentTimeMillis() - start_time;
System.out.format("retval_error: recurse_depth %s, exception_freqeuncy %s (%s), time elapsed %s ms\n",
recurse_depth, exception_freq, failures,elapsed_time);
}
}
// (2) exception_error
for (int recurse_depth = 2; recurse_depth <= 10; recurse_depth+=3) {
for (float exception_freq = 0.0f; exception_freq <= 1.0f; exception_freq += 0.25f) {
int EXCEPTION_MOD = (exception_freq == 0.0f) ? ITERATION_COUNT+1 : (int)(1.0f / exception_freq);
failures = 0;
long start_time = System.currentTimeMillis();
t.reset();
for (i = 1; i < ITERATION_COUNT; i++) {
boolean shoulderror = (i % EXCEPTION_MOD) == 0;
try {
t.exception_error(shoulderror,recurse_depth);
} catch (Exception e) {
failures++;
}
}
long elapsed_time = System.currentTimeMillis() - start_time;
System.out.format("exception_error: recurse_depth %s, exception_freqeuncy %s (%s), time elapsed %s ms\n",
recurse_depth, exception_freq, failures,elapsed_time);
}
}
}
}
और यहाँ परिणाम हैं:
baseline: recurse_depth 2, exception_freqeuncy 0.0 (0), time elapsed 683 ms
baseline: recurse_depth 2, exception_freqeuncy 0.25 (0), time elapsed 790 ms
baseline: recurse_depth 2, exception_freqeuncy 0.5 (0), time elapsed 768 ms
baseline: recurse_depth 2, exception_freqeuncy 0.75 (0), time elapsed 749 ms
baseline: recurse_depth 2, exception_freqeuncy 1.0 (0), time elapsed 731 ms
baseline: recurse_depth 5, exception_freqeuncy 0.0 (0), time elapsed 923 ms
baseline: recurse_depth 5, exception_freqeuncy 0.25 (0), time elapsed 971 ms
baseline: recurse_depth 5, exception_freqeuncy 0.5 (0), time elapsed 982 ms
baseline: recurse_depth 5, exception_freqeuncy 0.75 (0), time elapsed 947 ms
baseline: recurse_depth 5, exception_freqeuncy 1.0 (0), time elapsed 937 ms
baseline: recurse_depth 8, exception_freqeuncy 0.0 (0), time elapsed 1154 ms
baseline: recurse_depth 8, exception_freqeuncy 0.25 (0), time elapsed 1149 ms
baseline: recurse_depth 8, exception_freqeuncy 0.5 (0), time elapsed 1133 ms
baseline: recurse_depth 8, exception_freqeuncy 0.75 (0), time elapsed 1117 ms
baseline: recurse_depth 8, exception_freqeuncy 1.0 (0), time elapsed 1116 ms
retval_error: recurse_depth 2, exception_freqeuncy 0.0 (0), time elapsed 742 ms
retval_error: recurse_depth 2, exception_freqeuncy 0.25 (24999999), time elapsed 743 ms
retval_error: recurse_depth 2, exception_freqeuncy 0.5 (49999999), time elapsed 734 ms
retval_error: recurse_depth 2, exception_freqeuncy 0.75 (99999999), time elapsed 723 ms
retval_error: recurse_depth 2, exception_freqeuncy 1.0 (99999999), time elapsed 728 ms
retval_error: recurse_depth 5, exception_freqeuncy 0.0 (0), time elapsed 920 ms
retval_error: recurse_depth 5, exception_freqeuncy 0.25 (24999999), time elapsed 1121 ms
retval_error: recurse_depth 5, exception_freqeuncy 0.5 (49999999), time elapsed 1037 ms
retval_error: recurse_depth 5, exception_freqeuncy 0.75 (99999999), time elapsed 1141 ms
retval_error: recurse_depth 5, exception_freqeuncy 1.0 (99999999), time elapsed 1130 ms
retval_error: recurse_depth 8, exception_freqeuncy 0.0 (0), time elapsed 1218 ms
retval_error: recurse_depth 8, exception_freqeuncy 0.25 (24999999), time elapsed 1334 ms
retval_error: recurse_depth 8, exception_freqeuncy 0.5 (49999999), time elapsed 1478 ms
retval_error: recurse_depth 8, exception_freqeuncy 0.75 (99999999), time elapsed 1637 ms
retval_error: recurse_depth 8, exception_freqeuncy 1.0 (99999999), time elapsed 1655 ms
exception_error: recurse_depth 2, exception_freqeuncy 0.0 (0), time elapsed 726 ms
exception_error: recurse_depth 2, exception_freqeuncy 0.25 (24999999), time elapsed 17487 ms
exception_error: recurse_depth 2, exception_freqeuncy 0.5 (49999999), time elapsed 33763 ms
exception_error: recurse_depth 2, exception_freqeuncy 0.75 (99999999), time elapsed 67367 ms
exception_error: recurse_depth 2, exception_freqeuncy 1.0 (99999999), time elapsed 66990 ms
exception_error: recurse_depth 5, exception_freqeuncy 0.0 (0), time elapsed 924 ms
exception_error: recurse_depth 5, exception_freqeuncy 0.25 (24999999), time elapsed 23775 ms
exception_error: recurse_depth 5, exception_freqeuncy 0.5 (49999999), time elapsed 46326 ms
exception_error: recurse_depth 5, exception_freqeuncy 0.75 (99999999), time elapsed 91707 ms
exception_error: recurse_depth 5, exception_freqeuncy 1.0 (99999999), time elapsed 91580 ms
exception_error: recurse_depth 8, exception_freqeuncy 0.0 (0), time elapsed 1144 ms
exception_error: recurse_depth 8, exception_freqeuncy 0.25 (24999999), time elapsed 30440 ms
exception_error: recurse_depth 8, exception_freqeuncy 0.5 (49999999), time elapsed 59116 ms
exception_error: recurse_depth 8, exception_freqeuncy 0.75 (99999999), time elapsed 116678 ms
exception_error: recurse_depth 8, exception_freqeuncy 1.0 (99999999), time elapsed 116477 ms
रिटर्न-वैल्यूज़ की जाँच और प्रचार करना, बेसलाइन-नल कॉल के विरुद्ध कुछ लागत जोड़ देता है, और यह लागत कॉल-डेप्थ के समानुपाती होती है। 8 की कॉल-चेन डेप्थ पर, बेसलाइन संस्करण की तुलना में एरर-रिटर्न-वैल्यू चेकिंग संस्करण लगभग 27% धीमा था, जिसने रिटर्न वैल्यूज़ की जाँच नहीं की।
अपवाद प्रदर्शन, तुलना में, कॉल-डेप्थ का कार्य नहीं है, बल्कि अपवाद आवृत्ति का है। हालांकि, अपवाद आवृत्ति बढ़ जाती है के रूप में degredation बहुत अधिक नाटकीय है। केवल 25% त्रुटि आवृत्ति पर, कोड 24-TIMES धीमा चला गया। 100% की त्रुटि आवृत्ति पर, अपवाद संस्करण लगभग 100-TIMES धीमा है।
इससे मुझे पता चलता है कि शायद हमारे अपवाद कार्यान्वयन में गलत तरीके से व्यापार कर रहे हैं। अपवाद अधिक महंगा हो सकता है, या तो महंगा डंठल-चाल से बचने के द्वारा, या सीधे उन्हें संकलक समर्थित रिटर्न-वैल्यू जाँच में बदलकर। जब तक वे ऐसा नहीं करते, हम उनसे बचते हैं जब हम चाहते हैं कि हमारा कोड तेजी से चले।