Profiling and Refactoring

Rizal Diantoro
Sulang
Published in
4 min readMay 18, 2018

Kali ini saya akan melakukan optimizing code pada salah satu API yang ada di suling apps ini. Oke langsung aja yuk!

Berikut adalah kode yang akan kita lakukan optimizing.

class UserMahasiswaAPIView(ListAPIView):
queryset = UserMahasiswa.objects.all()
serializer_class = UserMahasiswaSerializer
permission_classes = (permissions.IsAuthenticated, )
@silk_profile(name='User Mahasiswa List')
def list(self, request):
queryset = self.get_queryset()
serializer = UserMahasiswaSerializer(queryset, many=True)
data = serializer.data
return Response(data)

Yang pertama kita lakukan sekarang adalah mendapatkan running time dari API tersebut. Hal tersebut bisa dilakukan dengan menggunakan library silky yang dapat diakses disini. Setelah terinstall dengan baik, maka kita dapat menggunakannya dengan hanya membuka link apps kita dengan endpoint ke /silk contohnya:

http://localhost:8000/silk

Lalu yang kita dapatkan adalah sebuah halaman seperti gambar berikut ini.

Analisa terhadap API List User Mahasiswa

Bisa kita lihat bahwa api ini melakukan banyak sekali Query, ada 3001 Queries hanya untuk satu API. Hal ini terjadi karena ada join table pada Query ini, dikarenakan model yang kami buat merupakan OneToOneField ke model User yang dimiliki oleh django.

class UserMahasiswa(models.Model):
user = models.OneToOneField(
User,
on_delete=models.CASCADE,
related_name='user_mahasiswa',
)
nama_lengkap = models.CharField(max_length=128)
npm = models.CharField(max_length=20, blank=True, null=True)
angkatan = models.CharField(max_length=10, blank=True, null=True)
is_valid = models.BooleanField(default=False)
def __str__(self):
return self.nama_lengkap
class Meta:
pass

Next..

Ini adalah Profile Graph yang dihasilkan oleh silky. Warna diatas memberikan informasi bahwa, hijau itu waktu eksekusinya cepat dan semakin menuju merah waktu eksekusinya menjadi lambat.

Ternyata warna merah yang ada disebelah kirim image tadi adalah eksekusi waktu dalam membuat serializing data. Hal bisa terjadi karena serializer yang kami buat juga akan mengambil data User, dan User pun memiliki serializer tersendiri dan juga data user cukup banyak. Hal tersebut membuat waktu eksekusi serializer pada metode ini menjadi cukup berat dan lama. Berikut adalah serializer kami.

class UserMahasiswaSerializer(serializers.ModelSerializer):
user = UserSerializer()
class Meta:
model = UserMahasiswa
fields = ('id', 'nama_lengkap', 'npm', 'angkatan', 'user')

Caching Refactoring

Karena kebutuhan, hal tersebut sebenarnya memang sulit untuk dihindari. Namun masih ada hal yang dapat dilakukan, yaitu melakukan caching refactoring. Query hanya dilakukan sekali dan sisanya akan diambil dari Cache saja yang waktunya akan relatif lebih cepat. Apalagi jika data yang kita simpan di Cache merupakan data serializer, sehingga kita hanya tinggal membuatkan responsenya saja.

class UserMahasiswaAPIView(ListAPIView):
queryset = UserMahasiswa.objects.all()
serializer_class = UserMahasiswaSerializer
permission_classes = (permissions.IsAuthenticated, )
@silk_profile(name='User Mahasiswa List')
def list(self, request):
# Note the use of `get_queryset()` instead of `self.queryset`
data = cache.get('users_mahasiswa')
if data is None:
queryset = self.get_queryset()
serializer = UserMahasiswaSerializer(queryset, many=True)
data = serializer.data
cache.set('users_mahasiswa', data, 86400)

return Response(data)

Dan mari kita lihat perubahannya.

Ini adalah perbandingan setelah dilakukan Refactoring. Dapat dilihat bawha nilai yang berada pada ujung kiri adalah nilai setelah dilakukan Refactoring, dan menjadi sangat cepat karena tidak dilakukan Query sama sekali.

Lalu kita lihat juga Graph yang dihasilkan menjadi

Dan jika kita amati lebih dekat, kita lagi mendapati warna merah karena serializer, melainkan karena function bawaan dari django itu sendiri.

Dengan menerapkan strategi diatas, API ini dapat memberikan hasil yang sama, namun dengan waktu eksekusi yang jauh lebih cepat.

Oke, segitu dulu yaa pembahasan mengenai profiling dan refactoring kali ini. Terimakasih

--

--