Bagikan melalui


Pertimbangan Performa untuk Interop (C++)

Topik ini menyediakan panduan untuk mengurangi efek transisi interop terkelola/tidak terkelola pada performa run-time.

Visual C++ mendukung mekanisme interoperabilitas yang sama dengan bahasa .NET lainnya seperti Visual Basic dan C# (P/Invoke), tetapi juga menyediakan dukungan interop yang khusus untuk Visual C++ (interop C++). Untuk aplikasi penting performa, penting untuk memahami implikasi performa dari setiap teknik interop.

Terlepas dari teknik interop yang digunakan, urutan transisi khusus, yang disebut thunks, diperlukan setiap kali fungsi terkelola memanggil fungsi yang tidak dikelola dan sebaliknya. Thunk ini dimasukkan secara otomatis oleh pengkompilasi Microsoft C++, tetapi penting untuk diingat bahwa secara kumulatif, transisi ini bisa mahal dalam hal performa.

Mengurangi Transisi

Salah satu cara untuk menghindari atau mengurangi biaya jempol interop adalah dengan merefaktor antarmuka yang terlibat untuk meminimalkan transisi terkelola/tidak terkelola. Peningkatan performa dramatis dapat dilakukan dengan menargetkan antarmuka yang cerewet, yaitu yang sering melibatkan panggilan di seluruh batas terkelola/tidak terkelola. Fungsi terkelola yang memanggil fungsi yang tidak dikelola dalam perulangan yang ketat, misalnya, adalah kandidat yang baik untuk refaktor. Jika perulangan itu sendiri dipindahkan ke sisi yang tidak dikelola, atau jika alternatif terkelola untuk panggilan yang tidak dikelola dibuat (mungkin mengantre data di sisi terkelola dan kemudian marshaling ke API yang tidak dikelola sekaligus setelah perulangan), jumlah transisi dapat dikurangi secara signifikan.

P/Invoke vs. C++ Interop

Untuk bahasa .NET, seperti Visual Basic dan C#, metode yang ditentukan untuk beroperasi dengan komponen asli adalah P/Invoke. Karena P/Invoke didukung oleh .NET Framework, Visual C++ juga mendukungnya, tetapi Visual C++ juga menyediakan dukungan interoperabilitasnya sendiri, yang disebut sebagai C++ Interop. C++ Interop lebih disukai daripada P/Invoke karena P/Invoke tidak aman untuk jenis. Akibatnya, kesalahan terutama dilaporkan pada run time, tetapi C++ Interop juga memiliki keunggulan performa daripada P/Invoke.

Kedua teknik memerlukan beberapa hal untuk terjadi setiap kali fungsi terkelola memanggil fungsi yang tidak dikelola:

  • Argumen panggilan fungsi dinaungi dari CLR ke jenis asli.

  • Thunk terkelola ke tidak terkelola dijalankan.

  • Fungsi yang tidak dikelola dipanggil (menggunakan versi asli argumen).

  • Thunk yang tidak dikelola ke dikelola dijalankan.

  • Jenis pengembalian dan argumen "out" atau "in,out" apa pun dinamai dari jenis asli ke CLR.

Thunk terkelola/tidak terkelola diperlukan agar interop berfungsi sama sekali, tetapi marshaling data yang diperlukan tergantung pada jenis data yang terlibat, tanda tangan fungsi, dan bagaimana data akan digunakan.

Marshaling data yang dilakukan oleh C++ Interop adalah bentuk yang paling sederhana: parameter hanya disalin di seluruh batas terkelola/tidak terkelola dengan cara bitwise; tidak ada transformasi yang dilakukan. Untuk P/Invoke, ini hanya benar jika semua parameter sederhana, jenis yang dapat di-blittable. Jika tidak, P/Invoke melakukan langkah-langkah yang sangat kuat untuk mengonversi setiap parameter terkelola ke jenis asli yang sesuai, dan sebaliknya jika argumen ditandai sebagai "out", atau "in,out".

Dengan kata lain, C++ Interop menggunakan metode marshaling data tercepat, sedangkan P/Invoke menggunakan metode yang paling kuat. Ini berarti bahwa Interop C++ (dengan cara yang khas untuk C++) memberikan performa optimal secara default, dan programmer bertanggung jawab untuk mengatasi kasus di mana perilaku ini tidak aman atau sesuai.

Oleh karena itu C++ Interop mengharuskan marshaling data harus disediakan secara eksplisit, tetapi keuntungannya adalah bahwa programmer bebas untuk memutuskan apa yang sesuai, mengingat sifat data, dan bagaimana hal itu akan digunakan. Selain itu, meskipun perilaku marshaling data P/Invoke dapat dimodifikasi sesuai derajat, C++ Interop memungkinkan marshaling data disesuaikan berdasarkan panggilan demi panggilan. Ini tidak dimungkinkan dengan P/Invoke.

Untuk informasi selengkapnya tentang Interop C++, lihat Menggunakan Interop C++ (PInvoke Implisit).

Baca juga

Rakitan Campuran (Asli dan Terkelola)