บน Windows CLR สำหรับสายการโทรที่มีความลึก 8 การโยนข้อยกเว้นจะช้ากว่าการตรวจสอบและเผยแพร่ค่าส่งคืน 750 เท่า (ดูด้านล่างสำหรับมาตรฐาน)
นี้ค่าใช้จ่ายสูงสำหรับข้อยกเว้นเป็นเพราะทำงานร่วมหน้าต่าง CLR กับสิ่งที่เรียกว่าWindows ที่มีโครงสร้างการจัดการข้อยกเว้น สิ่งนี้ทำให้ข้อยกเว้นถูกจับและโยนอย่างถูกต้องในช่วงเวลาและภาษาที่ต่างกัน อย่างไรก็ตามมันช้ามาก
ข้อยกเว้นใน Mono runtime (บนแพลตฟอร์มใด ๆ ) นั้นเร็วกว่ามากเนื่องจากไม่ได้รวมเข้ากับ SEH อย่างไรก็ตามมีการสูญเสียการทำงานเมื่อส่งข้อยกเว้นข้ามหลายครั้งเนื่องจากไม่ได้ใช้อะไรอย่าง SEH
นี่คือผลลัพธ์โดยย่อจากเกณฑ์มาตรฐานของฉันยกเว้นค่าส่งคืนสำหรับ Windows CLR
baseline: recurse_depth 8, error_freqeuncy 0 (0), time elapsed 13.0007 ms
baseline: recurse_depth 8, error_freqeuncy 0.25 (0), time elapsed 13.0007 ms
baseline: recurse_depth 8, error_freqeuncy 0.5 (0), time elapsed 13.0008 ms
baseline: recurse_depth 8, error_freqeuncy 0.75 (0), time elapsed 13.0008 ms
baseline: recurse_depth 8, error_freqeuncy 1 (0), time elapsed 14.0008 ms
retval_error: recurse_depth 5, error_freqeuncy 0 (0), time elapsed 13.0008 ms
retval_error: recurse_depth 5, error_freqeuncy 0.25 (249999), time elapsed 14.0008 ms
retval_error: recurse_depth 5, error_freqeuncy 0.5 (499999), time elapsed 16.0009 ms
retval_error: recurse_depth 5, error_freqeuncy 0.75 (999999), time elapsed 16.001 ms
retval_error: recurse_depth 5, error_freqeuncy 1 (999999), time elapsed 16.0009 ms
retval_error: recurse_depth 8, error_freqeuncy 0 (0), time elapsed 20.0011 ms
retval_error: recurse_depth 8, error_freqeuncy 0.25 (249999), time elapsed 21.0012 ms
retval_error: recurse_depth 8, error_freqeuncy 0.5 (499999), time elapsed 24.0014 ms
retval_error: recurse_depth 8, error_freqeuncy 0.75 (999999), time elapsed 24.0014 ms
retval_error: recurse_depth 8, error_freqeuncy 1 (999999), time elapsed 24.0013 ms
exception_error: recurse_depth 8, error_freqeuncy 0 (0), time elapsed 31.0017 ms
exception_error: recurse_depth 8, error_freqeuncy 0.25 (249999), time elapsed 5607.3208 ms
exception_error: recurse_depth 8, error_freqeuncy 0.5 (499999), time elapsed 11172.639 ms
exception_error: recurse_depth 8, error_freqeuncy 0.75 (999999), time elapsed 22297.2753 ms
exception_error: recurse_depth 8, error_freqeuncy 1 (999999), time elapsed 22102.2641 ms
และนี่คือรหัส ..
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace ConsoleApplication1 {
public class TestIt {
int value;
public class TestException : Exception { }
public int getValue() {
return value;
}
public void reset() {
value = 0;
}
public bool baseline_null(bool shouldfail, int recurse_depth) {
if (recurse_depth <= 0) {
return shouldfail;
} else {
return baseline_null(shouldfail,recurse_depth-1);
}
}
public bool retval_error(bool shouldfail, int recurse_depth) {
if (recurse_depth <= 0) {
if (shouldfail) {
return false;
} else {
return true;
}
} else {
bool nested_error = retval_error(shouldfail,recurse_depth-1);
if (nested_error) {
return true;
} else {
return false;
}
}
}
public void exception_error(bool shouldfail, int recurse_depth) {
if (recurse_depth <= 0) {
if (shouldfail) {
throw new TestException();
}
} 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 = 1000000;
// (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;
DateTime start_time = DateTime.Now;
t.reset();
for (i = 1; i < ITERATION_COUNT; i++) {
bool shoulderror = (i % EXCEPTION_MOD) == 0;
t.baseline_null(shoulderror,recurse_depth);
}
double elapsed_time = (DateTime.Now - start_time).TotalMilliseconds;
Console.WriteLine(
String.Format(
"baseline: recurse_depth {0}, error_freqeuncy {1} ({2}), time elapsed {3} ms",
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;
DateTime start_time = DateTime.Now;
t.reset();
for (i = 1; i < ITERATION_COUNT; i++) {
bool shoulderror = (i % EXCEPTION_MOD) == 0;
if (!t.retval_error(shoulderror,recurse_depth)) {
failures++;
}
}
double elapsed_time = (DateTime.Now - start_time).TotalMilliseconds;
Console.WriteLine(
String.Format(
"retval_error: recurse_depth {0}, error_freqeuncy {1} ({2}), time elapsed {3} ms",
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;
DateTime start_time = DateTime.Now;
t.reset();
for (i = 1; i < ITERATION_COUNT; i++) {
bool shoulderror = (i % EXCEPTION_MOD) == 0;
try {
t.exception_error(shoulderror,recurse_depth);
} catch (TestException e) {
failures++;
}
}
double elapsed_time = (DateTime.Now - start_time).TotalMilliseconds;
Console.WriteLine(
String.Format(
"exception_error: recurse_depth {0}, error_freqeuncy {1} ({2}), time elapsed {3} ms",
recurse_depth, exception_freq, failures,elapsed_time)); }
}
}
}
}