Tôi đã thực hiện một số kiểm tra (trong .Net 3.5 ... sau này tôi sẽ kiểm tra tại nhà bằng cách sử dụng .Net 4). Thực tế là: Nhận đối tượng dưới dạng giao diện và sau đó thực hiện phương thức nhanh hơn nhận đại biểu từ phương thức, sau đó gọi cho đại biểu.
Xem xét biến đã ở đúng loại (giao diện hoặc đại biểu) và đơn giản gọi nó làm cho đại biểu giành chiến thắng.
Vì lý do nào đó, việc ủy quyền qua phương thức giao diện (có thể trên bất kỳ phương thức ảo nào) sẽ chậm hơn. Và, xem xét có những trường hợp khi chúng tôi đơn giản không thể lưu trữ trước đại biểu (như trong Dispatches, ví dụ), có thể biện minh cho lý do tại sao giao diện nhanh hơn.
Dưới đây là kết quả:
Để có được kết quả thực sự, biên dịch này trong chế độ Release và chạy nó bên ngoài Visual Studio.
Kiểm tra các cuộc gọi trực tiếp hai lần
00: 00: 00.5834988
00: 00: 00,5997071
Kiểm tra cuộc gọi giao diện, nhận giao diện tại mỗi cuộc gọi
00: 00: 05,8998212
Kiểm tra cuộc gọi giao diện, nhận giao diện một lần
00:00:05.3163224
Kiểm tra Action (đại biểu) gọi, nhận được hành động ở mọi cuộc gọi
00: 00: 17,1807980
Kiểm tra Action (đại biểu) gọi, nhận được hành động một lần
00: 00: 05,3163224
Kiểm tra Action (đại biểu) trên một phương pháp giao diện, nhận cả ở mỗi cuộc gọi
00: 03: 50,7326056
Kiểm tra Action (đại biểu) trên một n phương pháp giao diện, nhận giao diện một lần, các đại biểu tại mỗi cuộc gọi
00: 03: 48,9141438
Kiểm tra Action (đại biểu) trên một phương pháp giao diện, nhận được cả hai một lần
00: 00: 04,0036530
Như bạn có thể thấy, các cuộc gọi trực tiếp thực sự nhanh chóng. Lưu trữ giao diện hoặc ủy quyền trước đó, và sau đó chỉ gọi nó là rất nhanh. Nhưng phải có được một đại biểu là chậm hơn so với việc phải có được một giao diện. Có để có được một đại biểu trên một phương pháp giao diện (hoặc phương pháp ảo, không chắc chắn) là thực sự chậm (so sánh 5 giây nhận được một đối tượng như một giao diện đến gần 4 phút làm như vậy để có được hành động).
Các mã mà tạo ra những kết quả là đây:
using System;
namespace ActionVersusInterface
{
public interface IRunnable
{
void Run();
}
public sealed class Runnable:
IRunnable
{
public void Run()
{
}
}
class Program
{
private const int COUNT = 1700000000;
static void Main(string[] args)
{
var r = new Runnable();
Console.WriteLine("To get real results, compile this in Release mode and");
Console.WriteLine("run it outside Visual Studio.");
Console.WriteLine();
Console.WriteLine("Checking direct calls twice");
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
r.Run();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
r.Run();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking interface calls, getting the interface at every call");
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
IRunnable interf = r;
interf.Run();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking interface calls, getting the interface once");
{
DateTime begin = DateTime.Now;
IRunnable interf = r;
for (int i = 0; i < COUNT; i++)
{
interf.Run();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) calls, getting the action at every call");
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
Action a = r.Run;
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) calls, getting the Action once");
{
DateTime begin = DateTime.Now;
Action a = r.Run;
for (int i = 0; i < COUNT; i++)
{
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) over an interface method, getting both at every call");
{
DateTime begin = DateTime.Now;
for (int i = 0; i < COUNT; i++)
{
IRunnable interf = r;
Action a = interf.Run;
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) over an interface method, getting the interface once, the delegate at every call");
{
DateTime begin = DateTime.Now;
IRunnable interf = r;
for (int i = 0; i < COUNT; i++)
{
Action a = interf.Run;
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.WriteLine();
Console.WriteLine("Checking Action (delegate) over an interface method, getting both once");
{
DateTime begin = DateTime.Now;
IRunnable interf = r;
Action a = interf.Run;
for (int i = 0; i < COUNT; i++)
{
a();
}
DateTime end = DateTime.Now;
Console.WriteLine(end - begin);
}
Console.ReadLine();
}
}
}
Tôi không rõ ràng về những gì bạn đang yêu cầu ... callbacks giao diện _are_ đại biểu. –
Xem http://stackoverflow.com/questions/1269452/is-using-delegates-excessively-a-bad-idea-for-performance và http://stackoverflow.com/questions/304770/does-using-delegates- các chương trình chạy chậm-mạng-của tôi - các bản sao có thể có? – itowlson
đại biểu là cần thiết nếu bạn đang chạy chủ đề riêng biệt và cần phải giao diện với các chủ đề giao diện người dùng .. vì vậy bạn cần phải tinh chỉnh câu hỏi của bạn nhiều hơn để được bản địa hóa hơn và ít chung chung hơn. –