Bagikan melalui


Performa Windows Workflow Foundation 4

.NET Framework 4 mencakup revisi utama Windows Workflow Foundation (WF) dengan investasi performa yang berat. Revisi baru ini memperkenalkan perubahan desain yang signifikan dari versi WF sebelumnya yang dikirim sebagai bagian dari .NET Framework 3.0 dan .NET Framework 3.5. Revisi ini telah dirancang ulang dari inti model pemrograman, runtime bahasa umum, dan alat untuk sangat meningkatkan performa dan kegunaan. Topik ini menunjukkan karakteristik performa penting dari revisi ini dan membandingkannya dengan versi sebelumnya.

Performa komponen alur kerja individu telah meningkat berdasarkan urutan ukuran antara WF3 dan WF4. Peningkatan ini menjadikan kesenjangan antara layanan Windows Communication Foundation (WCF) berkode tangan dan layanan alur kerja WCF menjadi cukup kecil. Latensi alur kerja telah berkurang secara signifikan di WF4. Performa persistensi telah meningkat dengan faktor 2,5 - 3,0. Pemantauan kesehatan melalui pelacakan alur kerja memiliki overhead yang jauh lebih sedikit. Hal ini merupakan alasan yang menarik untuk bermigrasi atau mengadopsi WF4 dalam aplikasi Anda.

Terminologi

Versi WF yang diperkenalkan di .NET Framework 4 akan disebut sebagai WF4 untuk sisa topik ini. WF diperkenalkan di .NET Framework 3.0 dan memiliki beberapa revisi kecil melalui .NET Framework 3.5 SP1. Versi .NET Framework 3.5 dari Workflow Foundation akan disebut sebagai WF3 untuk sisa topik ini. WF3 dikirim dalam .NET Framework 4 berdampingan dengan WF4. Untuk informasi selengkapnya tentang memigrasikan artefak WF3 ke WF4 lihat: Panduan Migrasi Windows Workflow Foundation 4.

Windows Communication Foundation (WCF) adalah model pemrograman terpadu Microsoft untuk membangun aplikasi berorientasi layanan. Pertama kali diperkenalkan sebagai bagian dari .NET Framework 3.0 bersama dengan WF3 dan sekarang menjadi salah satu komponen utama .NET Framework.

Windows Server AppFabric adalah seperangkat teknologi terintegrasi yang memudahkan untuk membangun, menskalakan, dan mengelola aplikasi Web dan komposit yang berjalan di IIS. Teknologi ini menyediakan alat untuk memantau dan mengelola layanan dan alur kerja. Untuk informasi selengkapnya, lihat Windows Server AppFabric 1.0.

Sasaran

Tujuan dari topik ini adalah untuk menunjukkan karakteristik performa WF4 dengan data yang diukur untuk skenario yang berbeda. Topik ini juga memberikan perbandingan terperinci antara WF4 dan WF3, dan dengan demikian menunjukkan peningkatan besar yang telah dibuat dalam revisi baru ini. Skenario dan data yang disajikan dalam artikel ini mengukur biaya yang mendasari berbagai aspek WF4 dan WF3. Data ini berguna dalam memahami karakteristik performa WF4 dan dapat membantu dalam merencanakan migrasi dari WF3 ke WF4 atau menggunakan WF4 dalam pengembangan aplikasi. Namun, perawatan harus diambil dalam kesimpulan yang diambil dari data yang disajikan dalam artikel ini. Performa aplikasi alur kerja komposit sangat bergantung pada bagaimana alur kerja diterapkan dan bagaimana komponen yang berbeda diintegrasikan. Seseorang harus mengukur setiap aplikasi untuk menentukan karakteristik performa aplikasi tersebut.

Gambaran Umum Peningkatan Performa WF4

WF4 dirancang dan diimplementasikan dengan hati-hati dengan performa dan skalabilitas tinggi yang dijelaskan di bagian berikut.

Runtime Bahasa Umum WF

Inti dari runtime bahasa umum WF adalah penjadwal asinkron yang mendorong eksekusi aktivitas dalam alur kerja. Hal ini menyediakan lingkungan eksekusi yang berkinerja dan dapat diprediksi untuk aktivitas. Lingkungan ini memiliki kontrak yang terdefinisi dengan baik untuk eksekusi, kelanjutan, penyelesaian, pembatalan, pengecualian, dan model alur yang dapat diprediksi.

Dibandingkan dengan WF3, runtime bahasa umum WF4 memiliki penjadwal yang lebih efisien. Penjadwalan ini memanfaatkan kumpulan alur I/O yang sama yang digunakan untuk WCF, yang sangat efisien dalam mengeksekusi item kerja batch. Antrean penjadwal item kerja internal dioptimalkan untuk pola penggunaan yang paling umum. Runtime bahasa umum WF4 juga mengelola status eksekusi dengan cara yang sangat ringan dengan sinkronisasi minimal dan logika penanganan peristiwa, sementara WF3 bergantung pada pendaftaran peristiwa berat dan pemanggilan untuk melakukan sinkronisasi kompleks untuk transisi status.

Microsoft Azure Storage dan Alur

Di WF3, data yang terkait dengan aktivitas dimodelkan melalui properti dependensi yang diterapkan oleh jenis DependencyProperty. Pola properti dependensi diperkenalkan di Windows Presentation Foundation (WPF). Secara umum, pola ini sangat fleksibel untuk mendukung pengikatan data yang mudah dan fitur antarmuka pengguna lainnya. Namun, pola mengharuskan properti didefinisikan sebagai bidang statis dalam definisi alur kerja. Setiap kali runtime bahasa umum WF menetapkan atau mendapatkan nilai properti, hal ini melibatkan logika pencarian yang sangat berat.

WF4 menggunakan logika cakupan data yang jelas untuk sangat meningkatkan cara data ditangani dalam alur kerja. Logika ini memisahkan penyimpanan data dalam aktivitas dari data yang mengalir di seluruh batas aktivitas dengan menggunakan dua konsep berbeda: variabel dan argumen. Dengan menggunakan cakupan hierarkis yang jelas untuk variabel dan argumen "In/Out/InOut", kompleksitas penggunaan data untuk aktivitas dikurangi secara dramatis dan masa pakai data juga secara otomatis tercakup. Aktivitas memiliki tanda tangan yang terdefinisi dengan baik yang dijelaskan oleh argumennya. Dengan hanya memeriksa aktivitas, Anda dapat menentukan data apa yang diharapkan untuk diterima dan data apa yang akan dihasilkan olehnya sebagai hasil dari eksekusinya.

Dalam aktivitas WF3 diinisialisasi saat alur kerja dibuat. Dalam aktivitas WF 4 diinisialisasi hanya saat aktivitas yang sesuai dijalankan. Inisialisasi ini memungkinkan siklus hidup aktivitas yang lebih sederhana tanpa melakukan operasi Inisialisasi/Batalkan inisialisasi saat instans alur kerja baru dibuat, dan dengan demikian telah mencapai lebih banyak efisiensi

Alur Kontrol

Sama seperti dalam bahasa pemrograman apa pun, WF menyediakan dukungan untuk alur kontrol untuk definisi alur kerja dengan memperkenalkan serangkaian aktivitas alur kontrol untuk pengurutan, perulangan, percabangan, dan pola lainnya. Dalam WF3, ketika aktivitas yang sama perlu dijalankan kembali, ActivityExecutionContext baru dibuat dan aktivitas dikloning melalui logika serialisasi dan deserialisasi berat berdasarkan BinaryFormatter. Biasanya performa untuk alur kontrol yang berulang jauh lebih lambat daripada menjalankan urutan aktivitas.

WF4 meng-handel ini dengan sangat berbeda. membutuhkan templat aktivitas, membuat objek ActivityInstance baru, dan menambahkannya ke antrean penjadwal. Seluruh proses ini hanya melibatkan pembuatan objek eksplisit dan sangat ringan.

Pemrograman Asinkron

Aplikasi biasanya memiliki performa dan skalabilitas yang lebih baik dengan pemrograman asinkron untuk operasi pemblokiran jangka panjang seperti I/O atau operasi komputasi terdistribusi. WF4 menyediakan dukungan asinkron melalui jenis aktivitas dasar AsyncCodeActivity, AsyncCodeActivity<TResult>. Runtime bahasa umum secara alami memahami aktivitas asinkron dan oleh karena itu dapat secara otomatis menempatkan instans di zona tanpa persisten sementara pekerjaan asinkron belum diproses. Aktivitas kustom dapat berasal dari jenis ini untuk melakukan pekerjaan asinkron tanpa menahan alur penjadwal alur kerja dan memblokir aktivitas apa pun yang mungkin dapat berjalan secara paralel.

Olahpesan

Awalnya WF3 memiliki dukungan olahpesan yang sangat terbatas melalui peristiwa eksternal atau pemanggilan layanan web. Dalam .NET Framework 3.5, alur kerja dapat diimplementasikan sebagai klien WCF atau diekspos sebagai layanan WCF melalui SendActivity dan ReceiveActivity. Di WF4, konsep pemrograman olahpesan berbasis alur kerja telah diperkuat lebih lanjut melalui integrasi ketat logika olahpesan WCF ke WF.

Alur pemrosesan pesan terpadu yang disediakan dalam WCF di .NET 4 membantu layanan WF4 memiliki performa dan skalabilitas yang jauh lebih baik daripada WF3. WF4 juga menyediakan dukungan pemrograman olahpesan yang lebih kaya yang dapat memodelkan Pola Pertukaran Pesan (MEP) yang kompleks. Pengembang dapat menggunakan kontrak layanan jenis untuk mencapai pemrograman yang mudah atau kontrak layanan tanpa jenis untuk mencapai performa yang lebih baik tanpa membayar biaya serialisasi. Dukungan penembolokan saluran sisi klien melalui kelas SendMessageChannelCache di WF4 membantu pengembang membangun aplikasi cepat dengan upaya minimal. Untuk informasi selengkapnya, lihat Mengubah Tingkat Berbagi Cache untuk Aktivitas Kirim.

Pemrograman Deklaratif

WF4 menyediakan kerangka kerja pemrograman deklaratif yang bersih dan sederhana untuk memodelkan proses dan layanan bisnis. Model pemrograman mendukung komposisi aktivitas yang sepenuhnya deklaratif, tanpa kode samping, sangat menyederhanakan penulisan alur kerja. Dalam .NET Framework 4, kerangka kerja pemrograman deklaratif berbasis XAML telah disatukan ke dalam rakitan tunggal System.Xaml.dll untuk mendukung WPF dan WF.

Dalam WF4, XAML memberikan pengalaman yang benar-benar deklaratif dan memungkinkan seluruh definisi alur kerja ditentukan dalam markup XML, mereferensikan aktivitas dan jenis yang dibangun menggunakan .NET. Hal ini sulit dilakukan dalam WF3 dengan format XOML tanpa melibatkan logika kode belakang kustom. Tumpukan XAML baru di .NET 4 memiliki performa yang jauh lebih baik dalam menserialisasikan/mendeserialisasi artefak alur kerja dan membuat pemrograman deklaratif lebih menarik dan solid.

Perancang Alur Kerja

Dukungan pemrograman deklaratif penuh untuk WF4 secara eksplisit memberlakukan persyaratan yang lebih tinggi untuk performa waktu desain untuk alur kerja besar. Perancang Alur Kerja di WF4 memiliki skalabilitas yang jauh lebih baik untuk alur kerja besar daripada untuk WF3. Dengan dukungan virtualisasi antarmuka pengguna, perancang dapat dengan mudah memuat alur kerja besar 1000 aktivitas dalam beberapa detik, sementara hampir tidak mungkin untuk memuat alur kerja dari beberapa ratus aktivitas dengan perancang WF3.

Perbandingan Performa Tingkat Komponen

Bagian ini berisi data tentang perbandingan langsung antara aktivitas individual dalam alur kerja WF3 dan WF4. Area utama seperti persistensi memiliki dampak yang lebih mendalam pada performa daripada komponen aktivitas individu. Peningkatan performa pada komponen individu di WF4 penting karena komponen kini cukup cepat untuk dibandingkan dengan logika orkestrasi berkode tangan. Contoh yang dibahas di bagian berikutnya: "Skenario Komposisi Layanan."

Penyiapan Lingkungan

Environment setup for workflow performance measurement

Gambar di atas menunjukkan konfigurasi komputer yang digunakan untuk pengukuran performa tingkat komponen. Satu server dan lima klien terhubung melalui satu antarmuka jaringan Ethernet 1 Gbps. Untuk pengukuran yang mudah, server dikonfigurasi untuk menggunakan satu inti dari server dual-proc/quad-core yang menjalankan Windows Server 2008 x86. Pemanfaatan CPU sistem dipertahankan hampir 100%.

Detail pengujian

CodeActivity WF3 kemungkinan adalah aktivitas paling sederhana yang dapat digunakan dalam alur kerja WF3. Aktivitas memanggil metode di kode belakang tempat programmer alur kerja dapat memasukkan kode kustom. Di WF4, tidak ada analog langsung ke CodeActivityWF3 yang menyediakan fungsionalitas yang sama. Perhatikan bahwa terdapat kelas dasar CodeActivity di WF4 yang tidak terkait dengan CodeActivity WF3. Pembuat alur kerja didorong untuk membuat aktivitas kustom dan membangun alur kerja khusus XAML. Dalam pengujian di bawah ini, aktivitas yang disebut Comment digunakan sebagai pengganti CodeActivity yang kosong di alur kerja WF4. Kode dalam aktivitas Comment adalah sebagai berikut:

[ContentProperty("Body")]
    public sealed class Comment : CodeActivity
    {
        public Comment()
            : base()
        {
        }

        [DefaultValue(null)]
        public Activity Body
        {
            get;
            set;
        }

        protected override void Execute(CodeActivityContext context)
        {
        }
    }

Alur Kerja Kosong

Pengujian ini menggunakan alur kerja urutan tanpa aktivitas turunan.

Aktivitas tunggal

Alur kerja ini adalah alur kerja urutan yang berisi satu aktivitas turunan. Aktivitas adalah CodeActivity tanpa kode dalam kasus WF3 dan aktivitas Comment dalam kasus WF4.

Sementara dengan 1000 perulangan

Alur kerja urutan berisi satu aktivitas While dengan satu aktivitas turunan dalam perulangan yang tidak melakukan pekerjaan apa pun.

Replikator dibandingkan dengan ParallelForEach

ReplicatorActivity dalam WF3 memiliki mode eksekusi paralel dan beurutan. Dalam mode berurutan, performa aktivitas mirip dengan WhileActivity. ReplicatorActivity yang paling berguna untuk eksekusi paralel. Analog WF4 untuk ini adalah aktivitas ParallelForEach<T>.

Diagram berikut menunjukkan alur kerja yang digunakan untuk pengujian ini. Alur kerja WF3 berada di sebelah kiri dan alur kerja WF4 berada di sebelah kanan.

WF3 ReplicatorActivity and WF4 ParallelForEach

Alur Kerja Berurutan dengan Lima Aktivitas

Pengujian ini dimaksudkan untuk menunjukkan efek memiliki beberapa aktivitas yang dijalankan secara berurutan. Ada lima aktivitas secara berurutan.

Cakupan Transaksi

Pengujian cakupan transaksi sedikit berbeda dari pengujian lain karena instans alur kerja baru tidak dibuat untuk setiap perulangan. Sebaliknya, alur kerja disusun dengan perulangan sementara yang berisi aktivitas TransactionScope berisi satu aktivitas yang tidak berfungsi. Setiap eksekusi batch dari 50 perulangan melalui perulangan sementara dihitung sebagai satu operasi.

Kompensasi

Alur kerja WF3 memiliki satu aktivitas yang dapat dikompensasi bernama WorkScope. Aktivitas hanya mengimplementasikan antarmuka ICompensatableActivity:

class WorkScope :
        CompositeActivity, ICompensatableActivity
    {
        public WorkScope() : base() { }

        public WorkScope(string name)
        {
            this.Name = name;
        }

        public ActivityExecutionStatus Compensate(
            ActivityExecutionContext executionContext)
        {
            return ActivityExecutionStatus.Closed;
        }
    }

Penanganan kesalahan menargetkan aktivitas WorkScope. Alur kerja WF4 sama-sama sederhana. CompensableActivity memiliki isi dan penanganan kompensasi. Kompensasi eksplisit berikutnya dalam urutan. Aktivitas isi dan aktivitas penanganan kompensasi adalah implementasi kosong:

public sealed class CompensableActivityEmptyCompensation : CodeActivity
    {
        public CompensableActivityEmptyCompensation()
            : base() { }

        public Activity Body { get; set; }

        protected override void Execute(CodeActivityContext context) { }
    }
    public sealed class CompensableActivityEmptyBody : CodeActivity
    {
        public CompensableActivityEmptyBody()
            : base() { }

        public Activity Body { get; set; }

        protected override void Execute(CodeActivityContext context) { }
    }

Diagram berikut menunjukkan alur kerja kompensasi dasar. Alur kerja WF3 berada di sebelah kiri dan alur kerja WF4 berada di sebelah kanan.

WF3 and WF4 basic compensation workflows

Hasil Pengujian Performa

Table showing performance test results data

Column chart comparing WF3 and WF4 performance test data

Semua pengujian diukur dalam alur kerja per detik dengan pengecualian pengujian cakupan transaksi. Seperti yang dapat dilihat di atas, performa runtime bahasa umum WF telah meningkat di seluruh proses, terutama di area yang memerlukan beberapa eksekusi aktivitas yang sama seperti perulangan sementara.

Skenario Komposisi Layanan

Seperti yang ditunjukkan di bagian sebelumnya, "Perbandingan Performa Tingkat Komponen," terdapat pengurangan overhead yang signifikan antara WF3 dan WF4. Layanan alur kerja WCF kini hampir dapat mencocokkan performa layanan WCF berkode tangan tetapi masih memiliki semua keuntungan runtime bahasa umum WF. Skenario pengujian ini membandingkan layanan WCF dengan layanan alur kerja WCF di WF4.

Online Store Service

Salah satu kekuatan Windows Workflow Foundation adalah kemampuan untuk menyusun proses menggunakan beberapa layanan. Untuk contoh ini, ada online store service yang mengatur dua panggilan layanan untuk membeli pesanan. Langkah pertama adalah memvalidasi pesanan menggunakan Order Validating Service. Langkah kedua adalah mengisi pesanan menggunakan Warehouse Service.

Dua layanan backend, Order Validating Service dan Warehouse Service, tetap sama untuk kedua pengujian. Bagian yang berubah adalah Online Store Service yang melakukan orkestrasi. Dalam satu kasus, layanan ini dikodekan dengan tangan sebagai layanan WCF. Untuk kasus lain, layanan ditulis sebagai layanan alur kerja WCF di WF4. Fitur khusus WF seperti pelacakan dan persistensi dinonaktifkan untuk pengujian ini.

Lingkungan

Environment setup for performance measurement

Permintaan klien dibuat ke Online Store Service melalui HTTP dari beberapa komputer. Satu komputer meng-hosting ketiga layanan. Lapisan transportasi antara Online Store Service dan layanan backend adalah TCP atau HTTP. Pengukuran operasi/detik didasarkan pada jumlah panggilan yang PurchaseOrder diselesaikan yang dilakukan ke Online Store Service. Pengumpulan saluran adalah fitur baru yang tersedia di WF4. Dalam bagian WCF dari kumpulan saluran pengujian ini tidak disediakan di luar kotak sehingga implementasi berkode tangan dari teknik pengumpulan sederhana digunakan dalam Online Store Service.

Performa

Column chart showing online Store Service performance

Menyambungkan ke layanan TCP backend tanpa pengumpulan saluran, layanan WF memiliki dampak 17,2% pada throughput. Dengan pengumpulan saluran, penaltinya sekitar 23,8%. Untuk HTTP, dampaknya jauh lebih sedikit: 4,3% tanpa pengumpulan dan 8,1% dengan pengumpulan. Penting juga untuk dicatat bahwa pengumpulan saluran memberikan keuntunganyang sangat sedikit saat menggunakan HTTP.

Meskipun ada overhead dari runtime bahasa umum WF4, dibandingkan dengan layanan WCF berkode tangan dalam pengujian ini, hal ini dapat dianggap sebagai skenario terburuk. Dua layanan backend dalam pengujian ini melakukan pekerjaan yang sangat sedikit. Dalam skenario end-to-end nyata, layanan ini akan melakukan operasi yang lebih mahal seperti panggilan database, membuat dampak performa lapisan transportasi menjadi kurang penting. Hal ini ditambah keuntungan fitur yang tersedia di WF4 menjadikan Workflow Foundation, pilihan yang layak untuk membuat layanan orkestrasi.

Pertimbangan Performa Utama

Area fitur di bagian ini, dengan pengecualian interop, telah berubah secara dramatis antara WF3 dan WF4. Hal ini memengaruhi desain aplikasi alur kerja serta performa.

Latensi Aktivasi Alur Kerja

Dalam aplikasi layanan alur kerja WCF, latensi untuk memulai alur kerja baru atau memuat alur kerja yang ada penting karena latensi dapat memblokir. Kasus pengujian ini mengukur host XOML WF3 terhadap host XAMLX WF4 dalam skenario umum.

Penyiapan Lingkungan

Environment setup for latency and throughput tests

Penyiapan Pengujian

Dalam skenario, komputer klien menghubungi layanan alur kerja WCF menggunakan korelasi berbasis konteks. Korelasi konteks memerlukan pengikatan konteks khusus dan menggunakan header konteks atau cookie untuk menghubungkan pesan dengan instans alur kerja yang benar. Korelasi konteks memiliki keuntungan performa karena Id korelasi terletak di header pesan sehingga isi pesan tidak perlu diurai.

Layanan akan membuat alur kerja baru dengan permintaan dan mengirim respons langsung sehingga pengukuran latensi tidak termasuk waktu yang dihabiskan untuk menjalankan alur kerja. Alur kerja WF3 adalah XOML dengan kode belakang dan alur kerja WF4 sepenuhnya XAML. Alur kerja WF4 terlihat seperti ini:

WF4 Correlation Scope workflow

Aktivitas Receive membuat instans alur kerja. Nilai yang diteruskan dalam pesan yang diterima digaungkan dalam pesan balasan. Urutan yang mengikuti balasan berisi sisa alur kerja. Dalam kasus di atas, hanya satu aktivitas komentar yang ditampilkan. Jumlah aktivitas komentar diubah untuk mensimulasikan kompleksitas alur kerja. Aktivitas komentar setara dengan CodeActivity WF3 yang tidak melakukan pekerjaan. Untuk informasi selengkapnya tentang aktivitas komentar, lihat sebelumnya bagian "Perbandingan Performa Tingkat Komponen" di artikel ini.

Hasil Pengujian

Latensi dingin dan hangat untuk layanan alur kerja WCF:

Column chart showing cold and warm latency for WCF workflow services using WF3 and WF4

Di bagan sebelumnya, dingin mengacu pada kasus di mana tidak ada WorkflowServiceHost untuk alur kerja yang ditentukan. Dengan kata lain, latensi dingin adalah ketika alur kerja digunakan untuk pertama kalinya dan XOML atau XAML perlu dikompilasi. Latensi hangat adalah waktu untuk membuat instans alur kerja baru ketika jenis alur kerja telah dikompilasi. Kompleksitas alur kerja membuat sangat sedikit perbedaan dalam kasus WF4 tetapi memiliki perkembangan linier dalam kasus WF3.

Throughput Korelasi

WF4 memperkenalkan fitur korelasi berbasis konten baru. WF3 hanya menyediakan korelasi berbasis konteks. Korelasi berbasis konteks hanya dapat dilakukan melalui pengikatan saluran WCF tertentu. Id alur kerja dimasukkan ke header pesan saat menggunakan pengikatan ini. Runtime bahasa umum WF3 hanya dapat mengidentifikasi alur kerja dengan Id-nya. Dengan korelasi berbasis konten, pembuat alur kerja dapat membuat kunci korelasi dari bagian data yang relevan seperti nomor akun atau Id pelanggan.

Korelasi berbasis konteks memiliki keunggulan performa karena kunci korelasi terletak di header pesan. Kunci dapat dibaca dari pesan tanpa deserialisasi/penyalinan pesan. Dalam korelasi berbasis konten, kunci korelasi disimpan dalam isi pesan. Ekspresi JalurX digunakan untuk menemukan kunci. Biaya pemrosesan tambahan ini bergantung pada ukuran pesan, kedalaman kunci dalam isi, dan jumlah kunci. Pengujian ini membandingkan korelasi berbasis konteks dan konten dan juga menunjukkan penurunan kinerja saat menggunakan beberapa kunci.

Penyiapan Lingkungan

Environment setup for workflow performance test

Penyiapan Pengujian

Correlation Throughput Workflow Test

Alur kerja sebelumnya sama dengan yang digunakan di bagian Persistensi. Untuk pengujian korelasi tanpa persistensi, tidak ada penyedia persistensi yang dipasang dalam runtime bahasa umum. Korelasi terjadi di dua tempat: CreateOrder dan CompleteOrder.

Hasil Pengujian

Correlation Throughput

Grafik ini menunjukkan penurunan performa saat jumlah kunci yang digunakan dalam korelasi berbasis konten meningkat. Kesamaan terjadi dalam kurva antara TCP dan HTTP menunjukkan overhead yang terkait dengan protokol ini.

Korelasi dengan Persistensi

Dengan alur kerja yang dipertahankan, tekanan CPU dari korelasi berbasis konten bergeser dari runtime bahasa umum alur kerja ke database SQL. Prosedur yang tersimpan di penyedia persistensi SQL melakukan pekerjaan pencocokan kunci untuk menemukan alur kerja yang sesuai.

Line chart showing correlation and persistence results

Korelasi berbasis konteks masih lebih cepat daripada korelasi berbasis konten. Namun, perbedaan korelasi ini kurang dibicarakan karena persistensi berdampak lebih pada performa daripada korelasi.

Throughput Alur Kerja Kompleks

Kompleksitas alur kerja tidak diukur hanya dengan jumlah aktivitas. Aktivitas komposit dapat mengandung banyak turunan dan turunan tersebut juga dapat menjadi aktivitas komposit. Ketika jumlah tingkat lapisan meningkat, begitu juga jumlah aktivitas yang dapat kini dalam status mengeksekusi dan jumlah variabel yang dapat berada dalam status. Pengujian ini membandingkan throughput antara WF3 dan WF4 saat menjalankan alur kerja yang kompleks.

Penyiapan Pengujian

Pengujian ini dijalankan pada komputer Intel Xeon X5355 @ 2.66GHz 4-way dengan RAM 4GB yang berjalan Windows Server 2008 x64. Kode pengujian berjalan dalam satu proses dengan satu alur per inti untuk mencapai pemanfaatan CPU 100%.

Alur kerja yang dihasilkan untuk pengujian ini memiliki dua variabel utama: kedalaman dan jumlah aktivitas di setiap urutan. Setiap tingkat kedalaman mencakup aktivitas paralel, perulangan sementara, keputusan, penugasan, dan urutan. Dalam perancang WF4 yang digambarkan di bawah ini, bagan alur tingkat atas digambarkan. Setiap aktivitas diagram alur menyerupai diagram alur utama. Ini mungkin berguna untuk memikirkan fraktal saat membayangkan alur kerja ini, di mana kedalamannya terbatas pada parameter pengujian.

Jumlah aktivitas dalam pengujian tertentu ditentukan oleh kedalaman dan jumlah aktivitas per urutan. Persamaan berikut menghitung jumlah aktivitas dalam pengujian WF4:

Equation to compute number of activities

Jumlah aktivitas pengujian WF3 dapat dihitung dengan persamaan yang sedikit berbeda karena urutan tambahan:

Equation to compute number of WF3 activities

Tempat d merupakan kedalaman dan jumlah aktivitas per urutan. Logika di balik persamaan ini adalah bahwa konstanta pertama, dikalikan dengan a, adalah jumlah urutan dan konstanta kedua adalah jumlah statis aktivitas di tingkat saat ini. Terdapat tiga aktivitas turunan diagram alur di setiap diagram alur. Pada tingkat kedalaman bawah, diagram alur ini kosong tetapi pada tingkat lain diagram alur ini adalah salinan diagram alur utama. Jumlah aktivitas dalam setiap definisi alur kerja variasi pengujian ditunjukkan dalam tabel berikut:

A table that shows the number of activities used in each test

Jumlah aktivitas dalam definisi alur kerja meningkat tajam dengan setiap tingkat kedalaman. Tetapi hanya satu jalur per titik keputusan yang dijalankan dalam instans alur kerja tertentu, sehingga hanya sebagian kecil dari aktivitas aktual yang dijalankan.

Flowchart of the complex throughput workflow

Alur kerja yang setara dibuat untuk WF3. Perancang WF3 menunjukkan seluruh alur kerja di area desain sebagi ganti lapisan, oleh karena itu terlalu besar untuk ditampilkan dalam topik ini. Cuplikan alur kerja diperlihatkan di bawah ini.

Flowchart snippet of the WF3 workflow

Untuk mengerjakan lapisan dalam kasus ekstrem, alur kerja lain yang merupakan bagian dari pengujian ini menggunakan 100 urutan berlapis. Dalam urutan terdalam adalah satu Comment atau CodeActivity.

Flowchart of a nested sequence

Pelacakan dan persistensi tidak digunakan sebagai bagian dari pengujian ini.

Hasil Pengujian

Column chart showing throughput performance results

Bahkan dengan alur kerja yang kompleks dengan banyak kedalaman dan jumlah aktivitas yang tinggi, hasil performa konsisten dengan angka throughput lain yang ditunjukkan sebelumnya dalam artikel ini. Throughput WF4 adalah urutan besarnya lebih cepat dan harus dibandingkan pada skala logaritma.

Memori

Overhead memori Windows Workflow Foundation diukur dalam dua area utama: kompleksitas alur kerja dan jumlah definisi alur kerja. Pengukuran memori diambil pada stasiun kerja Windows 7 64-bit. Ada banyak cara untuk mendapatkan pengukuran ukuran rangkaian kerja seperti memantau penghitung performa, polling Environment.WorkingSet, atau menggunakan alat seperti VMMap yang tersedia dari VMMap. Kombinasi metode digunakan untuk mendapatkan dan memverifikasi hasil setiap pengujian.

Uji Kompleksitas Alur Kerja

Pengujian kompleksitas alur kerja mengukur perbedaan rangkaian kerja berdasarkan kompleksitas alur kerja. Selain alur kerja kompleks yang digunakan di bagian sebelumnya, variasi baru ditambahkan untuk mencakup dua kasus dasar: satu alur kerja aktivitas dan urutan dengan 1000 aktivitas. Untuk pengujian ini, alur kerja diinisialisasi dan dijalankan hingga selesai dalam satu perulangan seri untuk periode waktu satu menit. Setiap variasi pengujian dijalankan tiga kali dan data yang direkam adalah rata-rata dari ketiga eksekusi tersebut.

Dua pengujian dasar baru memiliki alur kerja yang terlihat seperti yang ditunjukkan di bawah ini:

Complex workflow for both WF3 and WF4

Dalam alur kerja WF3 yang diperlihatkan di atas, aktivitas CodeActivity kosong digunakan. Alur kerja WF4 di atas menggunakan aktivitas Comment. Aktivitas Comment dijelaskan di bagian Perbandingan Performa Tingkat Komponen sebelumnya di artikel ini.

Column chart showing complex workflow memory usage for WF3 and WF4 workflows

Salah satu tren yang jelas untuk diperhatikan dalam grafik ini adalah bahwa lapisan memiliki dampak yang relatif minimal pada penggunaan memori di WF3 dan WF4. Dampak memori yang paling signifikan berasal dari jumlah aktivitas dalam alur kerja tertentu. Mengingat data dari urutan 1000, kedalaman kompleks 5 urutan 5, dan variasi kedalaman kompleks 7 urutan 1, jelas bahwa saat jumlah aktivitas memasuki ribuan, peningkatan penggunaan memori menjadi lebih terlihat. Dalam kasus ekstrem (kedalaman 7 urutan 1) di mana terdapat aktivitas ~29K, WF4 menggunakan memori hampir 79% lebih sedikit daripada WF3.

Pengujian Definisi Beberapa Alur Kerja

Mengukur definisi memori per alur kerja dibagi menjadi dua pengujian berbeda karena opsi yang tersedia untuk meng-hosting alur kerja di WF3 dan WF4. Pengujian dijalankan dengan cara yang berbeda dari pengujian kompleksitas alur kerja di mana alur kerja tertentu di-instans dan dijalankan hanya sekali per definisi. Pengujian ini karena definisi alur kerja dan host-nya tetap berada dalam memori selama masa pakai AppDomain. Memori yang digunakan dengan menjalankan instans alur kerja tertentu harus dibersihkan selama pengumpulan sampah. Panduan migrasi untuk WF4 berisi informasi lebih rinci tentang opsi hosting. Untuk informasi selengkapnya, lihat Buku Panduan Migrasi WF: Hosting Alur Kerja.

Membuat banyak definisi alur kerja untuk pengujian definisi alur kerja dapat dilakukan dengan beberapa cara. Misalnya, seseorang dapat menggunakan pembuatan kode untuk membuat rangkaian 1000 alur kerja yang identik kecuali dalam nama dan menyimpan masing-masing alur kerja tersebut ke dalam file terpisah. Pendekatan ini diambil untuk pengujian yang dihosting konsol. Di WF3, kelas WorkflowRuntime digunakan untuk menjalankan definisi alur kerja. WF4 dapat menggunakan baik WorkflowApplication untuk membuat satu instans alur kerja maupun langsung menggunakan WorkflowInvoker untuk menjalankan aktivitas seolah-olah merupakan panggilan metode. WorkflowApplication adalah host dari instans alur kerja tunggal dan memiliki paritas fitur yang lebih dekat ke WorkflowRuntime sehingga digunakan dalam pengujian ini.

Saat meng-hosting alur kerja di IIS, memungkinkan untuk menggunakan VirtualPathProvider untuk membuat WorkflowServiceHost baru alih-alih menghasilkan semua file XAMLX atau XOML. VirtualPathProvider meng-handel permintaan masuk dan merespons dengan "file virtual" yang dapat dimuat dari database atau, dalam kasus ini, dihasilkan dengan cepat. Oleh karena itu, tidak perlu membuat 1000 file fisik.

Definisi alur kerja yang digunakan dalam pengujian konsol adalah alur kerja berurutan sederhana dengan satu aktivitas. Aktivitas tunggal adalah CodeActivity kosong untuk kasus WF3 dan aktivitas Comment untuk kasus WF4. Kasus yang dihosting IIS digunakan alur kerja yang mulai menerima pesan dan mengakhiri pengiriman balasan:

Gambar berikut menunjukkan alur kerja WF3 dengan ReceiveActivity dan alur kerja WF4 dengan pola permintaan/respons:

Workflow Services in WF3 and WF4

Tabel berikut ini menunjukkan delta dalam rangkaian kerja antara definisi alur kerja tunggal dan definisi 1001:

Opsi Hosting Delta Rangkaian Kerja WF3 Delta Rangkaian Kerja WF4
Alur Kerja yang Dihosting Aplikasi Konsol 18 MB 9 MB
Layanan Alur Kerja yang Dihosting IIS 446 MB 364 MB

Definisi alur kerja Hosting di IIS menggunakan lebih banyak memori karena WorkflowServiceHost, artefak layanan WCF terperinci, dan logika pemrosesan pesan yang terkait dengan host.

Untuk hosting konsol di WF3, alur kerja diterapkan dalam kode, bukan XOML. Di WF4, defaultnya adalah menggunakan XAML. XAML disimpan sebagai sumber daya yang disematkan di rakitan dan dikompilasi selama runtime bahasa umum untuk menyediakan implementasi alur kerja. Terdapat beberapa overhead yang terkait dengan proses ini. Untuk membuat perbandingan yang adil antara WF3 dan WF4, alur kerja berkode digunakan alih-alih XAML. Contoh salah satu alur kerja WF4 diperlihatkan di bawah ini:

public class Workflow1 : Activity
{
    protected override Func<Activity> Implementation
    {
        get
        {
            return new Func<Activity>(() =>
            {
                return new Sequence
                {
                    Activities = {
                        new Comment()
                    }
                };
            });
        }
        set
        {
            base.Implementation = value;
        }
    }
}

Ada banyak faktor lain yang dapat memengaruhi pemakaian memori. Saran yang sama untuk semua program terkelola masih berlaku. Di lingkungan yang dihosting IIS, objek WorkflowServiceHost yang dibuat untuk definisi alur kerja tetap berada dalam memori hingga kumpulan aplikasi didaur ulang. Hal ini harus diingat saat menulis ekstensi. Selain itu, yang terbaik adalah menghindari variabel "global" (variabel yang terlingkup ke seluruh alur kerja) dan membatasi cakupan variabel sebisa mungkin.

Layanan Runtime Bahasa Umum Alur Kerja

Persistensi

WF3 dan WF4 keduanya mengirim dengan penyedia persistensi SQL. Penyedia persistensi SQL WF3 adalah implementasi sederhana yang menserialisasikan instans alur kerja dan menyimpannya dalam blob. Untuk alasan ini, performa penyedia ini sangat bergantung pada ukuran instans alur kerja. Dalam WF3, ukuran instans dapat meningkat karena berbagai alasan, seperti yang dibahas sebelumnya dalam artikel ini. Banyak pelanggan memilih untuk tidak menggunakan penyedia persistensi SQL default karena menyimpan instans yang diserialisasi dalam database tidak memberikan visibilitas ke dalam status alur kerja. Untuk menemukan alur kerja tertentu tanpa mengetahui id alur kerja, seseorang harus mendeserialisasi setiap instans yang bertahan dan memeriksa konten. Banyak pengembang lebih suka menulis penyedia persistensi mereka sendiri untuk mengatasi hambatan ini.

Penyedia persistensi SQL WF4 telah mencoba mengatasi beberapa masalah ini. Tabel persistensi mengekspos informasi tertentu seperti marka buku aktif dan properti yang dapat diproyeksikan. Fitur korelasi berbasis konten baru di WF4 tidak akan berkinerja baik menggunakan pendekatan persistensi SQL WF3, yang telah mendorong beberapa perubahan dalam organisasi instans alur kerja yang bertahan. Hal ini membuat pekerjaan penyedia persistensi lebih kompleks dan memberi tekanan ekstra pada database.

Penyiapan Lingkungan

Environment setup for workflow performance test

Penyiapan Pengujian

Bahkan dengan serangkaian fitur yang ditingkatkan dan penanganan konkurensi yang lebih baik, penyedia persistensi SQL di WF4 lebih cepat daripada penyedia di WF3. Untuk menampilkan ini, dua alur kerja yang pada dasarnya melakukan operasi yang sama di WF3 dan WF4 dibandingkan di bawah ini.

Persistence workflow in WF3 on left and WF4 on right

Dua alur kerja keduanya dibuat oleh pesan yang diterima. Setelah mengirim balasan awal, alur kerja tetap ada. Dalam kasus WF3, TransactionScopeActivity kosong digunakan untuk memulai persistensi. Hal yang sama dapat dicapai di WF3 dengan menandai aktivitas sebagai "bertahan dalam jarak dekat." Pesan kedua yang berkorelasi menyelesaikan alur kerja. Alur kerja tetap ada tetapi tida dibongkar.

Hasil Pengujian

Column chart showing throughput persistence

Ketika transportasi antara klien dan tingkat menengah adalah HTTP, persistensi di WF4 menunjukkan peningkatan 2,6 kali. Transportasi TCP meningkatkan faktor tersebut menjadi 3,0 kali. Dalam semua kasus, pemanfaatan CPU pada tingkat menengah adalah 98% atau lebih tinggi. Alasan bahwa throughput WF4 lebih besar adalah karena runtime bahasa umum alur kerja yang lebih cepat. Ukuran instans yang diserialisasi bersifat rendah untuk kedua kasus dan bukan elemen berkontribusi utama dalam situasi ini.

Alur kerja WF3 dan WF4 dalam pengujian ini menggunakan aktivitas untuk secara eksplisit menunjukkan kapan persistensi harus terjadi. Aktivitas ini memiliki keuntungan mempertahankan alur kerja tanpa membongkarnya. Di WF3, memungkinkan juga untuk bertahan menggunakan fitur TimeToUnload, tetapi fitur ini membongkar instans alur kerja dari memori. Jika pengembang yang menggunakan WF3 ingin memastikan alur kerja tetap ada di titik tertentu, mereka harus mengubah definisi alur kerja atau membayar biaya untuk membongkar dan memuat ulang instans alur kerja. Fitur baru di WF4 memungkinkan untuk bertahan tanpa membongkar: TimeToPersist. Fitur ini memungkinkan instans alur kerja tetap diam dan tetap dalam memori hingga ambang TimeToUnload terpenuhi atau eksekusi dilanjutkan.

Perhatikan bahwa penyedia persistensi SQL WF4 melakukan lebih banyak pekerjaan di tingkat database. Database SQL dapat menjadi hambatan sehingga penting untuk memantau penggunaan CPU dan disk di sana. Pastikan untuk menyertakan penghitung performa berikut dari database SQL saat pengujian performa aplikasi alur kerja:

  • Waktu Baca PhysicalDisk\%Disk

  • Waktu Disk PhysicalDisk%

  • Waktu Penulisan Disk PhysicalDisk\%

  • Panjang Antrean Disk Rata-Rata PhysicalDisk\%

  • Panjang Antrean Pembacaan Disk PhysicalDisk\Avg.

  • Panjang Antrean Penulisan Disk PhysicalDisk\Avg.

  • Panjang Antrean Disk PhysicalDisk\Current

  • Waktu Prosesor Information\%

  • SQLServer:Latch\Waktu Tunggu Latch Rata-Rata (ms)

  • SQLServer:Latch\Latch Menunggu/sec

Pelacakan

Pelacakan alur kerja dapat digunakan untuk melacak kemajuan alur kerja. Informasi yang disertakan dalam peristiwa pelacakan ditentukan oleh profil pelacakan. Semakin kompleks profil pelacakan, semakin mahal pelacakannya.

WF3 dikirim dengan layanan pelacakan berbasis SQL. Layanan ini dapat berfungsi dalam mode batch dan non-batch. Dalam mode non-batch, peristiwa pelacakan ditulis langsung ke database. Dalam mode batch, peristiwa pelacakan dikumpulkan ke dalam batch yang sama dengan status instans alur kerja. Mode batch memiliki performa terbaik untuk berbagai desain alur kerja terluas. Namun, batching dapat memiliki dampak performa negatif jika alur kerja menjalankan banyak aktivitas tanpa persistensi dan aktivitas tersebut dilacak. Hal ini biasanya akan terjadi dalam perulangan dan cara terbaik untuk menghindari skenario ini adalah dengan merancang perulangan besar untuk berisi titik persistensi. Memperkenalkan titik persistensi ke dalam perulangan dapat juga berdampak negatif pada performa sehingga penting untuk mengukur biaya masing-masing dan membuat keseimbangan.

WF4 tidak dikirim dengan layanan pelacakan SQL. Merekam informasi pelacakan ke database SQL dapat di-handel dengan lebih baik dari server aplikasi daripada dibangun ke dalam .NET Framework. Oleh karena itu, pelacakan SQL kini dihandel oleh AppFabric. Penyedia pelacakan default di WF4 didasarkan pada Pelacakan Peristiwa untuk Windows (ETW).

ETW adalah sistem peristiwa tingkat kernel dan latensi rendah yang dibangun ke dalam Windows. ETW menggunakan model penyedia/konsumen yang memungkinkan untuk hanya dikenakan penalti untuk pelacakan peristiwa saat benar-benar ada konsumen. Selain peristiwa kernel seperti prosesor, disk, memori, dan penggunaan jaringan, banyak aplikasi juga memanfaatkan ETW. Peristiwa ETW lebih kuat daripada penghitung performa dalam peristiwa tersebut dapat disesuaikan dengan aplikasi. Peristiwa dapat berisi teks seperti ID alur kerja atau pesan informasi. Selain itu, peristiwa dikategorikan dengan bitmask sehingga menggunakan subset peristiwa tertentu akan memiliki dampak performa yang lebih sedikit daripada menangkap semua peristiwa.

Keuntungan pendekatan menggunakan ETW untuk pelacakan daripada SQL meliputi:

  • Koleksi peristiwa pelacakan dapat dipisahkan ke proses lain. Pendekatan ini memberikan fleksibilitas yang lebih besar dalam cara peristiwa direkam.

  • Peristiwa pelacakan ETW mudah dikombinasikan dengan peristiwa ETW WCF atau penyedia ETW lainnya seperti SQL Server atau penyedia kernel.

  • Pembuat alur kerja tidak perlu mengubah alur kerja untuk bekerja lebih baik dengan implementasi pelacakan tertentu, seperti mode batch layanan pelacakan SQL WF3.

  • Administrator dapat mengaktifkan atau menonaktifkan pelacakan tanpa mendaur ulang proses host.

Keuntungan performa untuk pelacakan ETW disertai dengan kelemahan. Peristiwa ETW dapat hilang jika sistem berada di bawah tekanan sumber daya yang intens. Pemrosesan peristiwa tidak dimaksudkan untuk memblokir eksekusi program normal dan oleh karena itu tidak dijamin bahwa semua peristiwa ETW akan disiarkan kepada pelanggan mereka. Hal ini membuat pelacakan ETW sangat bagus untuk pemantauan kesehatan tetapi tidak cocok untuk audit.

Meskipun WF4 tidak memiliki penyedia pelacakan SQL, AppFabric melakukannya. Pendekatan pelacakan SQL AppFabric adalah untuk berlangganan ke peristiwa ETW dengan Layanan Windows yang mengumpulkan peristiwa dan menulisnya ke tabel SQL yang dirancang untuk penyisipan cepat. Pekerjaan terpisah menguras data dari tabel ini dan mereformasinya menjadi tabel pelaporan yang dapat dilihat di dasbor AppFabric. Hal ini berarti bahwa batch peristiwa pelacakan di-handel secara independen dari alur kerja asalnya dan oleh karena itu tidak perlu menunggu titik persistensi sebelum direkam.

Peristiwa ETW dapat direkam dengan alat seperti logman atau xperf. File ETL ringkas dapat dilihat dengan alat seperti xperfview atau dikonversi ke format yang lebih mudah dibaca, seperti XML, dengan tracerpt. Di WF3, satu-satunya opsi untuk mendapatkan peristiwa pelacakan tanpa database SQL adalah membuat layanan pelacakan kustom. Untuk informasi selengkapnya tentang ETW, lihat Layanan WCF dan Pelacakan Peristiwa untuk Windows dan Pelacakan Peristiwa - aplikasi Windows.

Mengaktifkan pelacakan alur kerja akan memengaruhi performa dalam berbagai tingkat. Tolok ukur di bawah ini menggunakan alat logman untuk menggunakan peristiwa pelacakan ETW dan merekamnya ke file ETL. Biaya pelacakan SQL di AppFabric tidak berada dalam cakupan artikel ini. Profil pelacakan dasar, juga digunakan dalam AppFabric, ditampilkan dalam tolok ukur ini. Juga termasuk biaya pelacakan hanya peristiwa pemantauan kesehatan. Peristiwa ini berguna untuk memecahkan masalah dan menentukan throughput rata-rata sistem.

Penyiapan Lingkungan

Environment setup for workflow performance test

Hasil Pengujian

Column chart showing workflow tracking costs

Pemantauan kesehatan berdampak sekitar 3% pada throughput. Biaya profil dasar sekitar 8%.

Interop

WF4 hampir merupakan penulisan ulang lengkap WF dan oleh karena itu alur kerja dan aktivitas WF3 tidak kompatibel langsung dengan WF4. Banyak pelanggan yang mengadopsi Windows Workflow Foundation lebih awal akan memiliki definisi alur kerja internal atau pihak ketiga dan aktivitas kustom untuk WF3. Salah satu cara untuk memudahkan transisi ke WF4 adalah dengan menggunakan aktivitas Interop, yang dapat menjalankan aktivitas WF3 dari dalam alur kerja WF4. Disarankan agar aktivitas Interop hanya digunakan jika perlu. Untuk informasi selengkapnya tentang migrasi ke WF4, lihat Panduan Migrasi WF4.

Penyiapan Lingkungan

Environment setup for workflow performance test

Hasil Pengujian

Tabel berikut ini memperlihatkan hasil menjalankan alur kerja yang berisi lima aktivitas secara berurutan dalam berbagai konfigurasi.

Uji Throughput (alur kerja/dtk)
Urutan WF3 dalam runtime bahasa umum WF3 1,576
Urutan WF3 dalam runtime bahasa umum WF4 menggunakan Interop 2,745
Urutan WF4 153,582

Terdapat peningkatan performa penting untuk menggunakan Interop langsung melalui WF3. Namun, jika dibandingkan dengan aktivitas WF4, peningkatannya dapat diabaikan.

Ringkasan

Investasi berat dalam performa untuk WF4 telah terbayar di banyak bidang penting. Performa komponen alur kerja individu dalam beberapa kasus ratusan kali lebih cepat di WF4 dibandingkan dengan WF3 karena runtime bahasa umum WF yang lebih ramping. Angka latensi juga jauh lebih baik. Hal ini berarti penalti performa untuk menggunakan WF dibandingkan dengan layanan orkestrasi WCF pengodean tangan sangat kecil mengingat keuntungan tambahan menggunakan WF. Performa persistensi telah meningkat dengan faktor 2,5 - 3,0. Pemantauan kesehatan melalui pelacakan alur kerja sekarang memiliki overhead yang sangat sedikit. Serangkaian panduan migrasi yang komprehensif tersedia bagi mereka yang mempertimbangkan untuk pindah dari WF3 ke WF4. Semua ini harus menjadikan WF4 pilihan yang menarik untuk menulis aplikasi yang kompleks.