Сообщение Re[44]: MS забило на дотнет. Питону - да, сишарпу - нет? от 04.09.2021 6:43
Изменено 04.09.2021 7:08 Sinclair
Re[44]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, vdimas, Вы писали:
V>Хотя, подозреваю, что быстродействие вызова UnmanagedCallersOnly-метода должно быть примерно на уровне DllImport.
Ну, с практической точки зрения там почти всё — бессмысленно. Вот эти все "давайте получим анменеджед указатель на менеджед делегат, и вызовем его из менеджед кода" — нулевая практическая ценность.
Удивительно то, что вызов через делегат, ещё недавно чуть ли не на порядок проигрывавший вызову через интерфейс, теперь сравнялся — у меня делегат вышел даже быстрее.
В общем, предсказуемым образом, менеджед код быстрее всего вызывать через managed func pointer, а анменеджед — через PInvoke без переключения GC.
Самый дешёвый вызов — по менеджед указателю — на моём процессоре стоит 7ns. Вызов через делегат — 16ns, в 2.3 раза дороже. Примерно в том же классе вызов через интерфейс.
Вызов простого PInvoke, который сам быстро исполняется и не лезет в менеджед-данные, стоит 22.5ns — втрое дороже, чем менеджед вызов, но всё ещё в 2.5 раза дешевле, чем обычный PInvoke через DllImport или через GetProcAddress. (73 ns). Вызовы менеджед кода как анменеджед стоят космически дорого (1мкс), но они и не нужны. Более жизненным сценарием было бы замерить вызов менеджед кода через колбэк.
Но и там основное, для чего нужно такое измерение — это чтобы понимать, какими должны быть масштабы объёма нативной работы, чтобы взаимодействие с ней было оправданым.
То есть когда мы говорим "вот тебе десять мегов данных, позови меня, когда отправишь" — это норм. А когда мы говорим: "вот тебе массив из 100 менеджед указателей, давай ты его отсортируешь, вызывая вот этот колбек для сравнения каждого из них" — это не норм, не надо так делать.
V>Хотя, подозреваю, что быстродействие вызова UnmanagedCallersOnly-метода должно быть примерно на уровне DllImport.
Ну, с практической точки зрения там почти всё — бессмысленно. Вот эти все "давайте получим анменеджед указатель на менеджед делегат, и вызовем его из менеджед кода" — нулевая практическая ценность.
Удивительно то, что вызов через делегат, ещё недавно чуть ли не на порядок проигрывавший вызову через интерфейс, теперь сравнялся — у меня делегат вышел даже быстрее.
В общем, предсказуемым образом, менеджед код быстрее всего вызывать через managed func pointer, а анменеджед — через PInvoke без переключения GC.
Method | m | Mean | Error | StdDev | Median | Overhead Ratio | |||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|
CallTest | Baseline | 173.9 μs | 3.44 μs | 9.37 μs | 173.2 μs | 0% | |||||||
CallTest | Managed func ptr | 245.1 μs | 3.37 μs | 2.63 μs | 244.9 μs | 100% | |||||||
CallTest | Delegate from MI | 335.8 μs | 3.94 μs | 3.29 μs | 336.2 μs | 227% | |||||||
CallTest | Delegate | 339.1 μs | 6.72 μs | 13.57 μs | 337.5 μs | 232% | |||||||
CallTest | Interface | 371.3 μs | 7.32 μs | 14.10 μs | 368.6 μs | 277% | |||||||
CallTest | DllImportNGC | 399.2 μs | 7.98 μs | 18.50 μs | 392.3 μs | 316% | |||||||
CallTest | DllImport | 901.5 μs | 14.52 μs | 12.12 μs | 896.8 μs | 1022% | |||||||
CallTest | DllGetProcAddr | 950.6 μs | 18.98 μs | 39.61 μs | 935.4 μs | 1091% | |||||||
CallTest | Ptr from delegate | 1,572.6 μs | 19.71 μs | 21.91 μs | 1,564.2 μs | 1964% | |||||||
CallTest | Unmanaged func ptr | 8,796.0 μs | 174.14 μs | 232.47 μs | 8,690.9 μs | 12110% | [tr]CallTest | Delegate from ptr | 10,214.0 μs | 158.16 μs | 231.83 μs | 10,140.2 μs | 14101% |
Вызов простого PInvoke, который сам быстро исполняется и не лезет в менеджед-данные, стоит 22.5ns — втрое дороже, чем менеджед вызов, но всё ещё в 2.5 раза дешевле, чем обычный PInvoke через DllImport или через GetProcAddress. (73 ns). Вызовы менеджед кода как анменеджед стоят космически дорого (1мкс), но они и не нужны. Более жизненным сценарием было бы замерить вызов менеджед кода через колбэк.
Но и там основное, для чего нужно такое измерение — это чтобы понимать, какими должны быть масштабы объёма нативной работы, чтобы взаимодействие с ней было оправданым.
То есть когда мы говорим "вот тебе десять мегов данных, позови меня, когда отправишь" — это норм. А когда мы говорим: "вот тебе массив из 100 менеджед указателей, давай ты его отсортируешь, вызывая вот этот колбек для сравнения каждого из них" — это не норм, не надо так делать.
Re[44]: MS забило на дотнет. Питону - да, сишарпу - нет?
Здравствуйте, vdimas, Вы писали:
V>Хотя, подозреваю, что быстродействие вызова UnmanagedCallersOnly-метода должно быть примерно на уровне DllImport.
Ну, с практической точки зрения там почти всё — бессмысленно. Вот эти все "давайте получим анменеджед указатель на менеджед делегат, и вызовем его из менеджед кода" — нулевая практическая ценность.
Удивительно то, что вызов через делегат, ещё недавно чуть ли не на порядок проигрывавший вызову через интерфейс, теперь сравнялся — у меня делегат вышел даже быстрее.
В общем, предсказуемым образом, менеджед код быстрее всего вызывать через managed func pointer, а анменеджед — через PInvoke без переключения GC.
Самый дешёвый вызов — по менеджед указателю — на моём процессоре стоит 7ns. Вызов через делегат — 16ns, в 2.3 раза дороже. Примерно в том же классе вызов через интерфейс.
Вызов простого PInvoke, который сам быстро исполняется и не лезет в менеджед-данные, стоит 22.5ns — втрое дороже, чем менеджед вызов, но всё ещё в 2.5 раза дешевле, чем обычный PInvoke через DllImport или через GetProcAddress. (73 ns). Вызовы менеджед кода как анменеджед стоят космически дорого (1мкс), но они и не нужны. Более жизненным сценарием было бы замерить вызов менеджед кода через колбэк.
Но и там основное, для чего нужно такое измерение — это чтобы понимать, какими должны быть масштабы объёма нативной работы, чтобы взаимодействие с ней было оправданым.
То есть когда мы говорим "вот тебе десять мегов данных, позови меня, когда отправишь" — это норм. А когда мы говорим: "вот тебе массив из 100 менеджед указателей, давай ты его отсортируешь, вызывая вот этот колбек для сравнения каждого из них" — это не норм, не надо так делать.
V>Хотя, подозреваю, что быстродействие вызова UnmanagedCallersOnly-метода должно быть примерно на уровне DllImport.
Ну, с практической точки зрения там почти всё — бессмысленно. Вот эти все "давайте получим анменеджед указатель на менеджед делегат, и вызовем его из менеджед кода" — нулевая практическая ценность.
Удивительно то, что вызов через делегат, ещё недавно чуть ли не на порядок проигрывавший вызову через интерфейс, теперь сравнялся — у меня делегат вышел даже быстрее.
В общем, предсказуемым образом, менеджед код быстрее всего вызывать через managed func pointer, а анменеджед — через PInvoke без переключения GC.
Method | m | Mean | Error | StdDev | Median | Overhead Ratio |
---|---|---|---|---|---|---|
CallTest | Baseline | 173.9 μs | 3.44 μs | 9.37 μs | 173.2 μs | 0% |
CallTest | Managed func ptr | 245.1 μs | 3.37 μs | 2.63 μs | 244.9 μs | 100% |
CallTest | Delegate from MI | 335.8 μs | 3.94 μs | 3.29 μs | 336.2 μs | 227% |
CallTest | Delegate | 339.1 μs | 6.72 μs | 13.57 μs | 337.5 μs | 232% |
CallTest | Interface | 371.3 μs | 7.32 μs | 14.10 μs | 368.6 μs | 277% |
CallTest | DllImportNGC | 399.2 μs | 7.98 μs | 18.50 μs | 392.3 μs | 316% |
CallTest | DllImport | 901.5 μs | 14.52 μs | 12.12 μs | 896.8 μs | 1022% |
CallTest | DllGetProcAddr | 950.6 μs | 18.98 μs | 39.61 μs | 935.4 μs | 1091% |
CallTest | Ptr from delegate | 1,572.6 μs | 19.71 μs | 21.91 μs | 1,564.2 μs | 1964% |
CallTest | Unmanaged func ptr | 8,796.0 μs | 174.14 μs | 232.47 μs | 8,690.9 μs | 12110% |
CallTest | Delegate from ptr | 10,214.0 μs | 158.16 μs | 231.83 μs | 10,140.2 μs | 14101% |
Вызов простого PInvoke, который сам быстро исполняется и не лезет в менеджед-данные, стоит 22.5ns — втрое дороже, чем менеджед вызов, но всё ещё в 2.5 раза дешевле, чем обычный PInvoke через DllImport или через GetProcAddress. (73 ns). Вызовы менеджед кода как анменеджед стоят космически дорого (1мкс), но они и не нужны. Более жизненным сценарием было бы замерить вызов менеджед кода через колбэк.
Но и там основное, для чего нужно такое измерение — это чтобы понимать, какими должны быть масштабы объёма нативной работы, чтобы взаимодействие с ней было оправданым.
То есть когда мы говорим "вот тебе десять мегов данных, позови меня, когда отправишь" — это норм. А когда мы говорим: "вот тебе массив из 100 менеджед указателей, давай ты его отсортируешь, вызывая вот этот колбек для сравнения каждого из них" — это не норм, не надо так делать.