ہاں، ورجینیا، وہاں *ہے* اے سانتا کلاز 2023 میں ویب فریم ورک کے درمیان فرق

مارکیٹ کے دباؤ اور تکنیکی قرض کا شکار ہونے سے پہلے ایک منحرف پروگرامر کا تیز رفتار کارکردگی کا مظاہرہ کرنے والا ویب سرور کوڈ تلاش کرنے کا سفر
2023-03-24 11:52:06
👁️ 779
💬 0

مشمولات

  1. تعارف
  2. ٹیسٹ
  3. PHP/Laravel
  4. خالص پی ایچ پی
  5. Laravel کا دوبارہ جائزہ لینا
  6. جینگو
  7. فلاسک
  8. سٹارلیٹ
  9. Node.js/ExpressJS
  10. مورچا/ایکٹکس
  11. تکنیکی قرض
  12. وسائل

تعارف

اپنے حالیہ ملازمت کے انٹرویوز میں سے ایک کے بعد، مجھے یہ جان کر حیرت ہوئی کہ میں نے جس کمپنی کے لیے درخواست دی تھی وہ ابھی تک لاراول استعمال کر رہی تھی، ایک پی ایچ پی فریم ورک جسے میں نے تقریباً ایک دہائی قبل آزمایا تھا۔ یہ اس وقت کے لیے مہذب تھا، لیکن اگر ٹیکنالوجی اور فیشن میں ایک ہی مستقل ہے، تو یہ طرزوں اور تصورات کی مسلسل تبدیلی اور دوبارہ سرفہرست ہے۔ اگر آپ جاوا اسکرپٹ پروگرامر ہیں، تو آپ شاید اس پرانے لطیفے سے واقف ہوں گے۔

پروگرامر 1: "مجھے یہ نیا JavaScript فریم ورک پسند نہیں ہے!"

پروگرامر 2: "پریشان ہونے کی ضرورت نہیں ہے۔ بس چھ مہینے انتظار کریں اور اس کی جگہ کوئی اور آئے گا!"

تجسس کی وجہ سے، میں نے یہ دیکھنے کا فیصلہ کیا کہ جب ہم پرانے اور نئے کو جانچتے ہیں تو کیا ہوتا ہے۔ یقینا، ویب بینچ مارکس اور دعووں سے بھرا ہوا ہے، جن میں سے سب سے زیادہ مقبول شاید ہے TechEmpower ویب فریم ورک بینچ مارکس یہاں . اگرچہ ہم آج ان کی طرح پیچیدہ کچھ نہیں کرنے جا رہے ہیں۔ ہم چیزوں کو اچھی اور سادہ رکھیں گے تاکہ یہ مضمون تبدیل نہ ہو جنگ اور امن , اور یہ کہ جب آپ پڑھ چکے ہوں گے تب تک آپ کے جاگنے کا تھوڑا سا موقع ہوگا۔ معمول کے انتباہات لاگو ہوتے ہیں: یہ آپ کی مشین پر ایک جیسا کام نہیں کر سکتا، سافٹ ویئر کے مختلف ورژن کارکردگی کو متاثر کر سکتے ہیں، اور شروڈنگر کی بلی دراصل ایک زومبی بلی بن گئی تھی جو عین وقت پر آدھی زندہ اور آدھی مردہ تھی۔

ٹیسٹ

ٹیسٹنگ ماحول

اس ٹیسٹ کے لیے، میں اپنا لیپ ٹاپ استعمال کروں گا جس میں ایک پنی i5 چل رہا ہے جو یہاں دکھایا گیا ہے۔

╰─➤  uname -a
Linux jimsredmi 5.10.174-1-MANJARO #1 SMP PREEMPT Tuesday Mar 21 11:15:28 UTC 2023 x86_64 GNU/Linux

╰─➤  cat /proc/cpuinfo
processor : 0
vendor_id : GenuineIntel
cpu family  : 6
model   : 126
model name  : Intel(R) Core(TM) i5-1035G1 CPU @ 1.00GHz
stepping  : 5
microcode : 0xb6
cpu MHz   : 990.210
cache size  : 6144 KB

ہاتھ میں کام

ہمارے کوڈ میں ہر درخواست کے لیے تین آسان کام ہوں گے:

  1. کوکی سے موجودہ صارف کی سیشن ID پڑھیں
  2. ڈیٹا بیس سے اضافی معلومات لوڈ کریں۔
  3. وہ معلومات صارف کو واپس کریں۔

آپ پوچھ سکتے ہیں کہ یہ کس قسم کا احمقانہ امتحان ہے؟ ٹھیک ہے، اگر آپ اس صفحہ کے لیے نیٹ ورک کی درخواستوں پر نظر ڈالیں گے، تو آپ سیشنvars.js نامی ایک دیکھیں گے جو بالکل وہی کام کرتا ہے۔

sessionvars.js کے مواد

آپ دیکھتے ہیں، جدید ویب صفحات پیچیدہ مخلوق ہیں، اور سب سے عام کاموں میں سے ایک پیچیدہ صفحات کو محفوظ کرنا ہے تاکہ ڈیٹا بیس سرور پر اضافی بوجھ سے بچا جا سکے۔

اگر ہم ایک پیچیدہ صفحہ کو ہر بار رینڈر کرتے ہیں جب کوئی صارف اس کی درخواست کرتا ہے، تو ہم فی سیکنڈ صرف 600 صارفین کی خدمت کر سکتے ہیں۔

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1/system/index.en.html      
Running 10s test @ http://127.0.0.1/system/index.en.html
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   186.83ms  174.22ms   1.06s    81.16%
    Req/Sec   166.11     58.84   414.00     71.89%
  6213 requests in 10.02s, 49.35MB read
Requests/sec:    619.97
Transfer/sec:      4.92MB

لیکن اگر ہم اس صفحہ کو ایک جامد HTML فائل کے طور پر کیش کرتے ہیں اور Nginx کو تیزی سے اسے ونڈو سے باہر صارف کے سامنے ٹاس کرنے دیتے ہیں، تو ہم فی سیکنڈ 32,000 صارفین کی خدمت کر سکتے ہیں، جس سے کارکردگی میں 50x اضافہ ہو گا۔

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1/system/index.en.html
Running 10s test @ http://127.0.0.1/system/index.en.html
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.03ms  511.95us   6.87ms   68.10%
    Req/Sec     8.20k     1.15k   28.55k    97.26%
  327353 requests in 10.10s, 2.36GB read
Requests/sec:  32410.83
Transfer/sec:    238.99MB

static index.en.html وہ حصہ ہے جو ہر کسی کو جاتا ہے، اور صرف وہی حصے جو صارف کے لحاظ سے مختلف ہوتے ہیں sessionvars.js میں بھیجے جاتے ہیں۔ اس سے نہ صرف ڈیٹا بیس کا بوجھ کم ہوتا ہے اور ہمارے صارفین کے لیے ایک بہتر تجربہ پیدا ہوتا ہے، بلکہ ان کوانٹم امکانات کو بھی کم کر دیتا ہے کہ کلنگنز کے حملے کے وقت ہمارا سرور خود بخود ایک وارپ کور بریک میں بخارات بن جائے گا۔

کوڈ کے تقاضے

ہر فریم ورک کے لیے واپس کیے گئے کوڈ کی ایک سادہ ضرورت ہوگی: صارف کو دکھائیں کہ انہوں نے کتنی بار "Count is x" کہہ کر صفحہ کو ریفریش کیا ہے۔ چیزوں کو آسان رکھنے کے لیے، ہم ابھی کے لیے Redis queues، Kubernetes اجزاء، یا AWS Lambdas سے دور رہیں گے۔

یہ دکھا رہا ہے کہ آپ نے کتنی بار صفحہ ملاحظہ کیا ہے۔

ہر صارف کے سیشن کا ڈیٹا PostgreSQL ڈیٹا بیس میں محفوظ کیا جائے گا۔

صارفین کے سیشنز کی میز

اور یہ ڈیٹا بیس ٹیبل ہر ٹیسٹ سے پہلے تراشا جائے گا۔

تراشے جانے کے بعد میز

سادہ لیکن موثر ہے Pafera کا نعرہ... بہرحال تاریک ترین ٹائم لائن سے باہر...

اصل ٹیسٹ کے نتائج

PHP/Laravel

ٹھیک ہے، تو اب ہم آخر کار اپنے ہاتھوں کو گندا کرنا شروع کر سکتے ہیں۔ ہم Laravel کے سیٹ اپ کو چھوڑ دیں گے کیونکہ یہ صرف کمپوزر اور کاریگر کا ایک گروپ ہے احکامات

سب سے پہلے، ہم اپنے ڈیٹا بیس کی ترتیبات .env فائل میں ترتیب دیں گے۔

DB_CONNECTION=pgsql
DB_HOST=127.0.0.1
DB_PORT=5432
DB_DATABASE=sessiontest
DB_USERNAME=sessiontest
DB_PASSWORD=sessiontest

پھر ہم ایک واحد فال بیک روٹ سیٹ کریں گے جو ہمارے کنٹرولر کو ہر درخواست بھیجتا ہے۔

Route::fallback(SessionController::class);

اور گنتی ظاہر کرنے کے لیے کنٹرولر سیٹ کریں۔ Laravel، بطور ڈیفالٹ، ڈیٹا بیس میں سیشنز کو اسٹور کرتا ہے۔ یہ بھی فراہم کرتا ہے session() ہمارے سیشن ڈیٹا کے ساتھ انٹرفیس کرنے کے لیے فنکشن، اس لیے ہمارے صفحہ کو رینڈر کرنے کے لیے کوڈ کی چند لائنیں لگیں۔

class SessionController extends Controller
{
  public function __invoke(Request $request)
  {
    $count  = session('count', 0);

    $count  += 1;

    session(['count' => $count]);

    return 'Count is ' . $count;
  }
}

php-fpm اور Nginx ترتیب دینے کے بعد، ہمارا صفحہ کافی اچھا لگتا ہے...

╰─➤  php -v
PHP 8.2.2 (cli) (built: Feb  1 2023 08:33:04) (NTS)
Copyright (c) The PHP Group
Zend Engine v4.2.2, Copyright (c) Zend Technologies
    with Xdebug v3.2.0, Copyright (c) 2002-2022, by Derick Rethans

╰─➤  sudo systemctl restart php-fpm
╰─➤  sudo systemctl restart nginx

کم از کم اس وقت تک جب تک کہ ہم اصل میں ٹیسٹ کے نتائج نہیں دیکھتے...

PHP/Laravel

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1
Running 10s test @ http://127.0.0.1
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.08s   546.33ms   1.96s    65.71%
    Req/Sec    12.37      7.28    40.00     56.64%
  211 requests in 10.03s, 177.21KB read
  Socket errors: connect 0, read 0, write 0, timeout 176
Requests/sec:     21.04
Transfer/sec:     17.67KB

نہیں، یہ کوئی ٹائپنگ نہیں ہے۔ ہماری ٹیسٹ مشین 600 درخواستیں فی سیکنڈ سے ایک پیچیدہ صفحہ پیش کرتی ہے... سے 21 درخواستیں فی سیکنڈ رینڈرنگ "گنتی 1 ہے"

تو کیا غلط ہوا؟ کیا ہماری پی ایچ پی کی تنصیب میں کچھ غلط ہے؟ کیا php-fpm کے ساتھ انٹرفیس کرتے وقت Nginx کسی طرح سست ہو رہا ہے؟

خالص پی ایچ پی

آئیے اس صفحہ کو خالص پی ایچ پی کوڈ میں دوبارہ کریں۔

<?php

// ====================================================================
function uuid4() 
{
  return sprintf(
    '%04x%04x-%04x-%04x-%04x-%04x%04x%04x',
    mt_rand(0, 0xffff), mt_rand(0, 0xffff),
    mt_rand(0, 0xffff),
    mt_rand(0, 0x0fff) | 0x4000,
    mt_rand(0, 0x3fff) | 0x8000,
    mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0xffff)
  );
}

// ====================================================================
function Query($db, $query, $params = [])
{
  $s  = $db->prepare($query);
  
  $s->setFetchMode(PDO::FETCH_ASSOC);
  $s->execute(array_values($params));
  
  return $s;
}

// ********************************************************************
session_start();

$sessionid  = 0;

if (isset($_SESSION['sessionid']))
{
  $sessionid  = $_SESSION['sessionid'];
}

if (!$sessionid)
{
  $sessionid              = uuid4();
  $_SESSION['sessionid']  = $sessionid;
}

$db   = new PDO('pgsql:host=127.0.0.1 dbname=sessiontest user=sessiontest password=sessiontest');
$data = 0;

try
{
  $result = Query(
    $db,
    'SELECT data FROM usersessions WHERE uid = ?',
    [$sessionid]
  )->fetchAll();
  
  if ($result)
  {
    $data = json_decode($result[0]['data'], 1);
  } 
} catch (Exception $e)
{
  echo $e;

  Query(
    $db,
    'CREATE TABLE usersessions(
      uid     TEXT PRIMARY KEY,
      data    TEXT
    )'
  );
}

if (!$data)
{
  $data = ['count'  => 0];
}

$data['count']++;

if ($data['count'] == 1)
{
  Query(
    $db,
    'INSERT INTO usersessions(uid, data)
    VALUES(?, ?)',
    [$sessionid, json_encode($data)]
  );
} else
{
  Query(
    $db,
    'UPDATE usersessions
      SET data = ?
      WHERE uid = ?',
    [json_encode($data), $sessionid]
  );
}

echo 'Count is ' . $data['count'];

اب ہم نے کوڈ کی 98 لائنیں استعمال کی ہیں جو Laravel میں کوڈ کی چار لائنوں (اور کنفیگریشن کے کام کا ایک پورا گروپ) نے کیا تھا۔ (یقیناً، اگر ہم نے غلطی کو درست طریقے سے سنبھالا اور صارف کو پیغامات کا سامنا کرنا پڑا، تو یہ لائنوں کی تعداد سے تقریباً دوگنا ہوگا۔) شاید ہم اسے 30 درخواستیں فی سیکنڈ تک پہنچا سکتے ہیں؟

PHP/Pure PHP

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1                  
Running 10s test @ http://127.0.0.1
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   140.79ms   27.88ms 332.31ms   90.75%
    Req/Sec   178.63     58.34   252.00     61.01%
  7074 requests in 10.04s, 3.62MB read
Requests/sec:    704.46
Transfer/sec:    369.43KB

واہ! ایسا لگتا ہے کہ ہماری پی ایچ پی کی تنصیب میں کوئی بھی حرج نہیں ہے۔ خالص پی ایچ پی ورژن 700 درخواستیں فی سیکنڈ کر رہا ہے۔

اگر پی ایچ پی میں کچھ غلط نہیں ہے، تو شاید ہم نے لاراول کو غلط کنفیگر کیا ہے؟

Laravel کا دوبارہ جائزہ لینا

کنفیگریشن ایشوز اور پرفارمنس ٹپس کے لیے ویب کو اسکور کرنے کے بعد، دو سب سے مشہور تکنیکیں ہر درخواست کے لیے ان پر کارروائی کرنے سے بچنے کے لیے کنفیگریشن اور روٹ ڈیٹا کو کیش کرنا تھیں۔ لہذا، ہم ان کے مشورہ لیں گے اور ان تجاویز کو آزمائیں گے.

╰─➤  php artisan config:cache

   INFO  Configuration cached successfully.  

╰─➤  php artisan route:cache

   INFO  Routes cached successfully.  

کمانڈ لائن پر سب کچھ اچھا لگتا ہے۔ آئیے بینچ مارک کو دوبارہ کریں۔

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1
Running 10s test @ http://127.0.0.1
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.13s   543.50ms   1.98s    61.90%
    Req/Sec    25.45     13.39    50.00     55.77%
  289 requests in 10.04s, 242.15KB read
  Socket errors: connect 0, read 0, write 0, timeout 247
Requests/sec:     28.80
Transfer/sec:     24.13KB

ٹھیک ہے، اب ہم نے کارکردگی کو 21.04 سے بڑھا کر 28.80 درخواست فی سیکنڈ کر دیا ہے، جو تقریباً 37% کی ڈرامائی ترقی ہے! یہ کسی بھی سافٹ ویئر پیکج کے لیے کافی متاثر کن ہوگا... سوائے اس حقیقت کے کہ ہم ابھی بھی خالص پی ایچ پی ورژن کی درخواستوں کی تعداد کا صرف 1/24 حصہ کر رہے ہیں۔

اگر آپ سوچ رہے ہیں کہ اس ٹیسٹ میں کچھ غلط ہونا چاہیے، تو آپ کو لوسینڈا پی ایچ پی فریم ورک کے مصنف سے بات کرنی چاہیے۔ اس کے ٹیسٹ کے نتائج میں، اس نے لوسنڈا لاراول کو مار رہی ہے۔ HTML درخواستوں کے لیے 36x اور JSON درخواستوں کے لیے 90x۔

Apache اور Nginx دونوں کے ساتھ میری اپنی مشین پر جانچ کرنے کے بعد، میرے پاس اس پر شک کرنے کی کوئی وجہ نہیں ہے۔ Laravel واقعی انصاف ہے کہ سست! PHP بذات خود اتنا برا نہیں ہے، لیکن ایک بار جب آپ Laravel کی ہر درخواست میں اضافی پروسیسنگ شامل کر لیتے ہیں، تو مجھے 2023 میں Laravel کو انتخاب کے طور پر تجویز کرنا بہت مشکل لگتا ہے۔

جینگو

پی ایچ پی/ورڈپریس اکاؤنٹس کے لیے ویب پر موجود تمام ویب سائٹس کا تقریباً 40% ، اسے اب تک کا سب سے غالب فریم ورک بناتا ہے۔ اگرچہ ذاتی طور پر، میں نے محسوس کیا کہ مقبولیت کا معیار میں ترجمہ کرنا ضروری نہیں ہے جتنا کہ میں اپنے آپ کو اس غیر معمولی لذیذ کھانے کے لیے اچانک بے قابو خواہش محسوس کرتا ہوں۔ دنیا کا سب سے مشہور ریستوراں ... میکڈونلڈز چونکہ ہم پہلے ہی خالص PHP کوڈ کا تجربہ کر چکے ہیں، اس لیے ہم خود ورڈپریس کو جانچنے نہیں جا رہے ہیں، کیونکہ ورڈپریس کو شامل کرنے والی کوئی بھی چیز بلاشبہ 700 درخواستوں فی سیکنڈ سے کم ہو گی جو ہم نے خالص PHP کے ساتھ دیکھی ہیں۔

جینگو ایک اور مقبول فریم ورک ہے جو ایک طویل عرصے سے موجود ہے۔ اگر آپ نے اسے ماضی میں استعمال کیا ہے، تو آپ شاید اس کے شاندار ڈیٹا بیس ایڈمنسٹریشن انٹرفیس کو شوق سے یاد کر رہے ہوں گے اور ساتھ ہی ہر چیز کو جس طرح آپ چاہتے تھے ترتیب دینا کتنا پریشان کن تھا۔ آئیے دیکھتے ہیں کہ Django 2023 میں کتنی اچھی طرح سے کام کرتا ہے، خاص طور پر نئے ASGI انٹرفیس کے ساتھ جسے اس نے ورژن 4.0 میں شامل کیا ہے۔

جیانگو کو ترتیب دینا خاص طور پر لاراول کو ترتیب دینے کے مترادف ہے، کیونکہ یہ دونوں اس زمانے سے تھے جہاں MVC فن تعمیر سجیلا اور درست تھے۔ ہم بورنگ کنفیگریشن کو چھوڑ دیں گے اور ویو سیٹ اپ کرنے کے لیے سیدھے جائیں گے۔

from django.shortcuts import render
from django.http import HttpResponse

# =====================================================================
def index(request):
  count = request.session.get('count', 0)
  count += 1
  request.session['count']  = count 
  return HttpResponse(f"Count is {count}")

کوڈ کی چار لائنیں Laravel ورژن کی طرح ہی ہیں۔ آئیے دیکھتے ہیں کہ یہ کیسے کام کرتا ہے۔

╰─➤  python --version
Python 3.10.9

Python/Django
╰─➤  gunicorn --access-logfile - -k uvicorn.workers.UvicornWorker -w 4 djangotest.asgi
[2023-03-21 15:20:38 +0800] [2886633] [INFO] Starting gunicorn 20.1.0

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1:8000/sessiontest/
Running 10s test @ http://127.0.0.1:8000/sessiontest/
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   277.71ms  142.84ms 835.12ms   69.93%
    Req/Sec    91.21     57.57   230.00     61.04%
  3577 requests in 10.06s, 1.46MB read
Requests/sec:    355.44
Transfer/sec:    148.56KB

فی سیکنڈ 355 درخواستوں پر بالکل بھی برا نہیں ہے۔ یہ خالص پی ایچ پی ورژن کی صرف نصف کارکردگی ہے، لیکن یہ لاراول ورژن سے 12 گنا زیادہ ہے۔ Django بمقابلہ Laravel ایسا لگتا ہے کہ کوئی مقابلہ نہیں ہے۔

فلاسک

بڑی ہر چیز کے علاوہ-بشمول باورچی خانے کے سنک فریم ورک کے علاوہ، چھوٹے فریم ورک بھی ہیں جو آپ کو باقی کو سنبھالنے دیتے ہوئے صرف کچھ بنیادی سیٹ اپ کرتے ہیں۔ استعمال کرنے کے لیے بہترین میں سے ایک فلاسک اور اس کا ASGI ہم منصب کوارٹ ہے۔ میرا اپنا PaferaPy فریم ورک فلاسک کے اوپر بنایا گیا ہے، لہذا میں اس بات سے بخوبی واقف ہوں کہ کارکردگی کو برقرار رکھتے ہوئے کام کرنا کتنا آسان ہے۔

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Session benchmark test

import json
import psycopg
import uuid

from flask import Flask, session, redirect, url_for, request, current_app, g, abort, send_from_directory
from flask.sessions import SecureCookieSessionInterface

app = Flask('pafera')

app.secret_key  = b'secretkey'

dbconn  = 0

# =====================================================================
@app.route('/', defaults={'path': ''}, methods = ['GET', 'POST'])
@app.route('/<path:path>', methods = ['GET', 'POST'])
def index(path):
  """Handles all requests for the server. 
  
  We route all requests through here to handle the database and session
  logic in one place.
  """
  global dbconn
  
  if not dbconn:
    dbconn  = psycopg.connect('dbname=sessiontest user=sessiontest password=sessiontest')
    
    cursor  = dbconn.execute('''
      CREATE TABLE IF NOT EXISTS usersessions(
        uid     TEXT PRIMARY KEY,
        data    TEXT
      )
    ''')
    cursor.close()
    dbconn.commit()
      
  sessionid = session.get('sessionid', 0)
  
  if not sessionid:
    sessionid = uuid.uuid4().hex
    session['sessionid']  = sessionid
  
  cursor  = dbconn.execute("SELECT data FROM usersessions WHERE uid = %s", [sessionid])
  row     = cursor.fetchone()
  
  count = json.loads(row[0])['count'] if row else 0
  
  count += 1
  
  newdata = json.dumps({'count': count})
  
  if count == 1:
    cursor.execute("""
        INSERT INTO usersessions(uid, data)
        VALUES(%s, %s)
      """,
      [sessionid, newdata]
    )
  else:
    cursor.execute("""
        UPDATE usersessions
        SET data = %s
        WHERE uid = %s
      """,
      [newdata, sessionid]
    )
  
  cursor.close()
  
  dbconn.commit()
  
  return f'Count is {count}'

جیسا کہ آپ دیکھ سکتے ہیں، فلاسک اسکرپٹ خالص پی ایچ پی اسکرپٹ سے چھوٹا ہے۔ مجھے معلوم ہوا کہ ان تمام زبانوں میں سے جو میں نے استعمال کی ہیں، Python غالباً ٹائپ کیے گئے کی اسٹروکس کے لحاظ سے سب سے زیادہ اظہار خیال کرنے والی زبان ہے۔ منحنی خطوط وحدانی اور قوسین کی کمی، فہرست اور ڈکٹ کی سمجھ، اور سیمیکولنز کی بجائے انڈینٹیشن پر مبنی بلاکنگ Python کو اپنی صلاحیتوں میں سادہ لیکن طاقتور بناتی ہے۔

بدقسمتی سے، Python وہاں کی سب سے سست عام مقصد کی زبان بھی ہے، باوجود اس کے کہ اس میں کتنا سافٹ ویئر لکھا گیا ہے۔ دستیاب Python لائبریریوں کی تعداد ملتے جلتے زبانوں کے مقابلے میں تقریباً چار گنا زیادہ ہے اور ڈومینز کی ایک بڑی مقدار کا احاطہ کرتی ہے، پھر بھی کوئی یہ نہیں کہے گا کہ Python تیز ہے اور نہ ہی NumPy جیسے طاقوں سے باہر ہے۔

آئیے دیکھتے ہیں کہ ہمارا فلاسک ورژن ہمارے پچھلے فریم ورک سے کیسے موازنہ کرتا ہے۔

Python/Flask

╰─➤  gunicorn --access-logfile - -w 4 flasksite:app
[2023-03-21 15:32:49 +0800] [2856296] [INFO] Starting gunicorn 20.1.0

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1:8000
Running 10s test @ http://127.0.0.1:8000
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    91.84ms   11.97ms 149.63ms   86.18%
    Req/Sec   272.04     39.05   380.00     74.50%
  10842 requests in 10.04s, 3.27MB read
Requests/sec:   1080.28
Transfer/sec:    333.37KB

ہمارا فلاسک اسکرپٹ دراصل ہمارے خالص پی ایچ پی ورژن سے تیز ہے!

اگر آپ اس سے حیران ہیں، تو آپ کو یہ سمجھ لینا چاہیے کہ جب ہم گنی کارن سرور کو سٹارٹ کرتے ہیں تو ہماری فلاسک ایپ اپنی تمام شروعات اور کنفیگریشن کرتی ہے، جبکہ پی ایچ پی ہر بار جب کوئی نئی درخواست آتی ہے تو اسکرپٹ کو دوبارہ عمل میں لاتی ہے۔ فلاسک ایک نوجوان، شوقین ٹیکسی ڈرائیور کے مترادف ہے جس نے پہلے ہی کار اسٹارٹ کر رکھی ہے اور سڑک کے کنارے انتظار کر رہا ہے، جبکہ پی ایچ پی وہ بوڑھا ڈرائیور ہے جو اپنے گھر پر کال آنے کا انتظار کرتا ہے اور تبھی گاڑی چلاتا ہے۔ آپ کو لینے کے لیے۔ اسکول کا ایک پرانا لڑکا ہونے کے ناطے اور ان دنوں سے آرہا ہے جہاں PHP سادہ HTML اور SHTML فائلوں میں ایک حیرت انگیز تبدیلی تھی، یہ سمجھنا قدرے افسوسناک ہے کہ کتنا وقت گزر چکا ہے، لیکن ڈیزائن میں فرق واقعی پی ایچ پی کے لیے مشکل بنا دیتا ہے۔ Python، Java، اور Node.js سرورز سے مقابلہ کریں جو صرف میموری میں رہتے ہیں اور ایک جادوگر کی فرتیلا آسانی کے ساتھ درخواست کو ہینڈل کرتے ہیں۔

سٹارلیٹ

فلاسک ہمارا اب تک کا سب سے تیز ترین فریم ورک ہوسکتا ہے، لیکن یہ حقیقت میں کافی پرانا سافٹ ویئر ہے۔ Python کمیونٹی نے کچھ سال پہلے نئے asychronous ASGI سرورز پر سوئچ کیا تھا، اور یقیناً میں نے خود بھی ان کے ساتھ سوئچ کیا ہے۔

پیفیرا فریم ورک کا تازہ ترین ورژن، PaferaPyAsync ، اسٹارلیٹ پر مبنی ہے۔ اگرچہ فلاسک کا ایک ASGI ورژن ہے جسے Quart کہتے ہیں، لیکن Quart اور Starlette کے درمیان کارکردگی کے فرق میرے لیے اس کے بجائے Starlette پر اپنے کوڈ کو ری بیس کرنے کے لیے کافی تھے۔

اسیکرونس پروگرامنگ بہت سے لوگوں کے لیے خوفزدہ ہو سکتی ہے، لیکن یہ حقیقت میں کوئی مشکل تصور نہیں ہے کیونکہ Node.js لڑکوں نے ایک دہائی قبل اس تصور کو مقبول بنایا تھا۔

ہم ملٹی تھریڈنگ، ملٹی پروسیسنگ، ڈسٹری بیوٹڈ کمپیوٹنگ، وعدے کی زنجیر، اور ان تمام تفریحی اوقات کے ساتھ ہم آہنگی کا مقابلہ کرتے تھے جو بہت سے تجربہ کار پروگرامرز کو وقت سے پہلے بوڑھے اور ناکارہ بنا دیتے تھے۔ اب، ہم صرف ٹائپ کرتے ہیں۔ async ہمارے افعال کے سامنے اور await کسی بھی کوڈ کے سامنے جس پر عمل درآمد میں کچھ وقت لگ سکتا ہے۔ یہ درحقیقت باقاعدہ کوڈ سے زیادہ لفظی ہے، لیکن مطابقت پذیری کے پرائمیٹوز، میسج پاس کرنے، اور وعدوں کو حل کرنے کے مقابلے میں استعمال کرنا بہت کم پریشان کن ہے۔

ہماری سٹارلیٹ فائل اس طرح دکھتی ہے:

#!/usr/bin/python3
# -*- coding: utf-8 -*-
#
# Session benchmark test

import json
import uuid

import psycopg

from starlette.applications import Starlette
from starlette.responses import Response, PlainTextResponse, JSONResponse, RedirectResponse, HTMLResponse
from starlette.routing import Route, Mount, WebSocketRoute
from starlette_session import SessionMiddleware

dbconn  = 0

# =====================================================================
async def index(R):
  global dbconn
  
  if not dbconn:
    dbconn  = await psycopg.AsyncConnection.connect('dbname=sessiontest user=sessiontest password=sessiontest')
    
    cursor  = await dbconn.execute('''
      CREATE TABLE IF NOT EXISTS usersessions(
        uid     TEXT PRIMARY KEY,
        data    TEXT
      )
    ''')
    await cursor.close()
    await dbconn.commit()
    
  sessionid = R.session.get('sessionid', 0)
  
  if not sessionid:
    sessionid = uuid.uuid4().hex
    R.session['sessionid']  = sessionid
  
  cursor  = await dbconn.execute("SELECT data FROM usersessions WHERE uid = %s", [sessionid])
  row     = await cursor.fetchone()
  
  count = json.loads(row[0])['count'] if row else 0
  
  count += 1
  
  newdata = json.dumps({'count': count})
  
  if count == 1:
    await cursor.execute("""
        INSERT INTO usersessions(uid, data)
        VALUES(%s, %s)
      """,
      [sessionid, newdata]
    )
  else:
    await cursor.execute("""
        UPDATE usersessions
        SET data = %s
        WHERE uid = %s
      """,
      [newdata, sessionid]
    )
  
  await cursor.close()
  await dbconn.commit()
  
  return PlainTextResponse(f'Count is {count}')

# *********************************************************************
app = Starlette(
  debug   = True, 
  routes  = [
    Route('/{path:path}', index, methods = ['GET', 'POST']),
  ],
)

app.add_middleware(
  SessionMiddleware, 
  secret_key  = 'testsecretkey', 
  cookie_name = "pafera",
)

جیسا کہ آپ دیکھ سکتے ہیں، یہ ہمارے فلاسک اسکرپٹ سے کافی حد تک کاپی اور پیسٹ کیا گیا ہے جس میں صرف چند روٹنگ تبدیلیاں ہیں اور async/await مطلوبہ الفاظ

کاپی اور پیسٹ شدہ کوڈ واقعی ہمیں کتنی بہتری دے سکتا ہے؟

Python/Starlette

╰─➤  gunicorn --access-logfile - -k uvicorn.workers.UvicornWorker -w 4 starlettesite:app                                                                                                130 ↵
[2023-03-21 15:42:34 +0800] [2856220] [INFO] Starting gunicorn 20.1.0

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1:8000
Running 10s test @ http://127.0.0.1:8000
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    21.85ms   10.45ms  67.29ms   55.18%
    Req/Sec     1.15k   170.11     1.52k    66.00%
  45809 requests in 10.04s, 13.85MB read
Requests/sec:   4562.82
Transfer/sec:      1.38MB

ہمارے پاس ایک نیا چیمپئن ہے، خواتین و حضرات! ہمارا پچھلا اعلیٰ ہمارا خالص پی ایچ پی ورژن 704 درخواستیں فی سیکنڈ تھا، جسے پھر ہمارے فلاسک ورژن نے 1080 درخواستیں فی سیکنڈ پر پیچھے چھوڑ دیا۔ ہمارا سٹارلیٹ اسکرپٹ تمام پچھلے دعویداروں کو 4562 درخواستوں فی سیکنڈ پر کچل دیتا ہے، یعنی خالص پی ایچ پی پر 6x بہتری اور فلاسک پر 4x بہتری۔

اگر آپ نے ابھی تک اپنے WSGI Python کوڈ کو ASGI میں تبدیل نہیں کیا ہے، تو اب شروع کرنے کا اچھا وقت ہو سکتا ہے۔

Node.js/ExpressJS

اب تک، ہم نے صرف PHP اور Python فریم ورک کا احاطہ کیا ہے۔ تاہم، دنیا کا ایک بڑا حصہ دراصل اپنی ویب سائٹس کے لیے Java، DotNet، Node.js، Ruby on Rails، اور اس طرح کی دیگر ٹیکنالوجیز استعمال کرتا ہے۔ یہ کسی بھی طرح سے دنیا کے تمام ماحولیاتی نظاموں اور بائیومز کا ایک جامع جائزہ نہیں ہے، لہذا نامیاتی کیمسٹری کے مساوی پروگرامنگ کرنے سے بچنے کے لیے، ہم صرف ان فریم ورک کا انتخاب کریں گے جن کے لیے کوڈ ٹائپ کرنا آسان ہے۔ جس میں سے جاوا یقینی طور پر نہیں ہے۔

جب تک کہ آپ K&R C یا Knuth's کی اپنی کاپی کے نیچے چھپا رہے ہوں کمپیوٹر پروگرامنگ کا فن پچھلے پندرہ سالوں سے، آپ نے شاید Node.js کے بارے میں سنا ہوگا۔ ہم میں سے وہ لوگ جو جاوا اسکرپٹ کے آغاز سے لے کر آج تک موجود ہیں وہ جدید جاوا اسکرپٹ کی حالت میں یا تو ناقابل یقین حد تک خوفزدہ، حیران، یا دونوں ہیں، لیکن اس سے انکار نہیں کیا جا سکتا کہ جاوا اسکرپٹ سرورز پر بھی شمار کیے جانے کی طاقت بن گیا ہے۔ براؤزر کے طور پر. بہر حال، ہمارے پاس اب زبان میں مقامی 64 بٹ انٹیجرز بھی ہیں! یہ 64 بٹ فلوٹس میں محفوظ ہونے والی ہر چیز سے کہیں بہتر ہے!

ExpressJS شاید استعمال کرنے کے لیے سب سے آسان Node.js سرور ہے، لہذا ہم اپنے کاؤنٹر کی خدمت کے لیے ایک تیز اور گندا Node.js/ExpressJS ایپ کریں گے۔

/**********************************************************************
 * Simple session test using ExpressJS.
 **********************************************************************/
var L           = console.log;

var uuid        = require('uuid4');
var express     = require('express');
var session     = require('express-session');
var MemoryStore = require('memorystore')(session);

var { Client }  = require('pg')
var db          = 0;
var app       = express();

const PORT    = 8000;

//session middleware
app.use(
  session({
    secret:             "secretkey",
    saveUninitialized:  true,
    resave:             false,
    store:              new MemoryStore({
      checkPeriod: 1000 * 60 * 60 * 24 // prune expired entries every 24h
    })
  })
);

app.get('/',
  async function(req,res)
  {
    if (!db)
    {
      db  = new Client({
        user:     'sessiontest',
        host:     '127.0.0.1',
        database: 'sessiontest',
        password: 'sessiontest'
      });
      
      await db.connect();
      
      await db.query(`
        CREATE TABLE IF NOT EXISTS usersessions(
          uid     TEXT PRIMARY KEY,
          data    TEXT
        )`,
        []
      );
    };
    
    var session = req.session;
    
    if (!session.sessionid)
    {
      session.sessionid = uuid();
    }
    
    var row = 0;
    
    let queryresult = await db.query(`
      SELECT data::TEXT
      FROM usersessions 
      WHERE uid = $1`,
      [session.sessionid]
    );
    
    if (queryresult && queryresult.rows.length)
    {
      row = queryresult.rows[0].data;
    } 
    
    var count = 0;
    
    if (row)
    {
      var data  = JSON.parse(row);
      
      data.count  += 1;
      
      count = data.count;
      
      await db.query(`
          UPDATE usersessions
          SET data = $1
          WHERE uid = $2
        `,
        [JSON.stringify(data), session.sessionid]
      );
    } else
    {
      await db.query(`
        INSERT INTO usersessions(uid, data)
          VALUES($1, $2)`,
        [session.sessionid, JSON.stringify({count: 1})]
      );
      
      count = 1;
    }
    
    res.send(`Count is ${count}`);
  }
);

app.listen(PORT, () => console.log(`Server Running at port ${PORT}`));

یہ کوڈ اصل میں ازگر کے ورژنز کے مقابلے میں لکھنا آسان تھا، حالانکہ مقامی جاوا اسکرپٹ جب ایپلی کیشنز کے بڑے ہو جاتے ہیں تو اس کی بجائے غیر مؤثر ہو جاتا ہے، اور اسے درست کرنے کی تمام کوششیں جیسے TypeScript جلد ازگر سے زیادہ لفظی ہو جاتی ہیں۔

آئیے دیکھتے ہیں کہ یہ کیسے کام کرتا ہے!

Node.js/ExpressJS

╰─➤  node --version                                                                                                                                                                     v19.6.0

╰─➤  NODE_ENV=production node nodejsapp.js                                                                                                                                             130 ↵
Server Running at port 8000

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1:8000
Running 10s test @ http://127.0.0.1:8000
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    90.41ms    7.20ms 188.29ms   85.16%
    Req/Sec   277.15     37.21   393.00     81.66%
  11018 requests in 10.02s, 3.82MB read
Requests/sec:   1100.12
Transfer/sec:    390.68KB

آپ نے Node.js&#x27; کے بارے میں قدیم (انٹرنیٹ کے معیار کے لحاظ سے قدیم...) لوک کہانیاں سنی ہوں گی۔ رفتار، اور وہ کہانیاں زیادہ تر سچ ہیں اس شاندار کام کی بدولت جو گوگل نے V8 JavaScript انجن کے ساتھ کیا ہے۔ اس معاملے میں، اگرچہ ہماری کوئیک ایپ فلاسک اسکرپٹ سے بہتر کارکردگی کا مظاہرہ کرتی ہے، لیکن اس کی سنگل تھریڈڈ نوعیت کو سٹارلیٹ نائٹ کے ذریعے چلنے والے چار async عملوں سے شکست دی جاتی ہے جو کہ "Ni!&quot; کہتی ہے۔

آئیے کچھ اور مدد حاصل کریں!

╰─➤  pm2 start nodejsapp.js -i 4 

[PM2] Spawning PM2 daemon with pm2_home=/home/jim/.pm2
[PM2] PM2 Successfully daemonized
[PM2] Starting /home/jim/projects/paferarust/nodejsapp.js in cluster_mode (4 instances)
[PM2] Done.
┌────┬──────────────┬─────────────┬─────────┬─────────┬──────────┬────────┬──────┬───────────┬──────────┬──────────┬──────────┬──────────┐
│ id │ name         │ namespace   │ version │ mode    │ pid      │ uptime │ ↺    │ status    │ cpu      │ mem      │ user     │ watching │
├────┼──────────────┼─────────────┼─────────┼─────────┼──────────┼────────┼──────┼───────────┼──────────┼──────────┼──────────┼──────────┤
│ 0  │ nodejsapp    │ default     │ N/A     │ cluster │ 37141    │ 0s     │ 0    │ online    │ 0%       │ 64.6mb   │ jim      │ disabled │
│ 1  │ nodejsapp    │ default     │ N/A     │ cluster │ 37148    │ 0s     │ 0    │ online    │ 0%       │ 64.5mb   │ jim      │ disabled │
│ 2  │ nodejsapp    │ default     │ N/A     │ cluster │ 37159    │ 0s     │ 0    │ online    │ 0%       │ 56.0mb   │ jim      │ disabled │
│ 3  │ nodejsapp    │ default     │ N/A     │ cluster │ 37171    │ 0s     │ 0    │ online    │ 0%       │ 45.3mb   │ jim      │ disabled │
└────┴──────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘

ٹھیک ہے! اب یہ چار پر چار کی جنگ ہے! آئیے بینچ مارک!

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1:8000
Running 10s test @ http://127.0.0.1:8000
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    45.09ms   19.89ms 176.14ms   60.22%
    Req/Sec   558.93     97.50   770.00     66.17%
  22234 requests in 10.02s, 7.71MB read
Requests/sec:   2218.69
Transfer/sec:    787.89KB

ابھی بھی سٹارلیٹ کی سطح پر بالکل نہیں، لیکن پانچ منٹ کی جاوا اسکرپٹ ہیک کے لیے یہ برا نہیں ہے۔ میری اپنی جانچ سے، اس اسکرپٹ کو درحقیقت ڈیٹا بیس انٹرفیسنگ کی سطح پر تھوڑا سا پیچھے رکھا جا رہا ہے کیونکہ نوڈ پوسٹگریس اتنا موثر نہیں ہے جتنا سائیکوپ جی ازگر کے لیے ہے۔ ڈیٹا بیس ڈرائیور کے طور پر sqlite پر سوئچ کرنے سے اسی ExpressJS کوڈ کے لیے فی سیکنڈ 3000 سے زیادہ درخواستیں موصول ہوتی ہیں۔

نوٹ کرنے والی اہم بات یہ ہے کہ Python کی سست رفتاری کے باوجود، ASGI فریم ورک دراصل کچھ کام کے بوجھ کے لیے Node.js حل کے ساتھ مسابقتی ہو سکتا ہے۔

مورچا/ایکٹکس

تو اب، ہم پہاڑ کی چوٹی کے قریب پہنچ رہے ہیں، اور پہاڑ سے، میرا مطلب ہے چوہوں اور مردوں کے یکساں طور پر ریکارڈ کیے گئے اعلیٰ ترین بینچ مارک سکور۔

اگر آپ ویب پر دستیاب زیادہ تر فریم ورک بینچ مارکس کو دیکھیں گے، تو آپ دیکھیں گے کہ دو زبانیں ہیں جو سب سے اوپر حاوی ہوتی ہیں: C++ اور Rust۔ میں نے 90 کی دہائی سے C++ کے ساتھ کام کیا ہے، اور MFC/ATL ایک چیز ہونے سے پہلے میرے پاس اپنا Win32 C++ فریم ورک بھی تھا، اس لیے مجھے زبان کا کافی تجربہ ہے۔ کسی چیز کے ساتھ کام کرنے میں زیادہ مزہ نہیں آتا جب آپ اسے پہلے سے جانتے ہوں، لہذا ہم اس کے بجائے ایک Rust ورژن کرنے جا رہے ہیں۔ ;)

جہاں تک پروگرامنگ زبانیں جاتی ہیں، زنگ نسبتاً نیا ہے، لیکن یہ میرے لیے تجسس کا باعث بن گیا جب لینس ٹوروالڈس نے اعلان کیا کہ وہ زنگ کو لینکس کرنل پروگرامنگ زبان کے طور پر قبول کرے گا۔ ہمارے پرانے پروگرامرز کے لیے، یہ بالکل ایسا ہی ہے جیسا کہ یہ کہنے کے لیے کہ یہ نئی دھندلی نئی عمر کی ہپی چیزی امریکی آئین میں ایک نئی ترمیم ہونے جا رہی ہے۔

اب، جب آپ ایک تجربہ کار پروگرامر ہیں، تو آپ بینڈ ویگن پر اتنی تیزی سے کودنے کا رجحان نہیں رکھتے جتنی نوجوان لوگ کرتے ہیں، ورنہ آپ زبان یا لائبریریوں میں تیزی سے تبدیلیوں سے جل سکتے ہیں۔ (کوئی بھی جس نے انگولر جے ایس کا پہلا ورژن استعمال کیا ہے وہ جان لے گا کہ میں کس کے بارے میں بات کر رہا ہوں۔) زنگ ابھی بھی کسی حد تک تجرباتی ترقی کے مرحلے میں ہے، اور مجھے یہ مضحکہ خیز لگتا ہے کہ ویب پر بہت سے کوڈ کی مثالیں بھی نہیں ملتی ہیں۔ پیکیجز کے موجودہ ورژن کے ساتھ مزید مرتب کریں۔

تاہم، Rust ایپلی کیشنز کی طرف سے دکھائی گئی کارکردگی سے انکار نہیں کیا جا سکتا۔ اگر آپ نے کبھی کوشش نہیں کی۔ ripgrep یا fd-تلاش بڑے سورس کوڈ والے درختوں پر، آپ کو یقینی طور پر ان کو گھماؤ دینا چاہیے۔ وہ زیادہ تر لینکس ڈسٹری بیوشنز کے لیے بھی صرف پیکیج مینیجر سے دستیاب ہیں۔ آپ Rust... a کے ساتھ کارکردگی کے لیے لفظوں کا تبادلہ کر رہے ہیں۔ بہت ایک کے لیے فعل کی بہت کارکردگی کی.

Rust کے لیے مکمل کوڈ تھوڑا بڑا ہے، اس لیے ہم یہاں متعلقہ ہینڈلرز پر ایک نظر ڈالیں گے:

// =====================================================================
pub async fn RunQuery(
  db:       &web::Data<Pool>,
  query:    &str,
  args:     &[&(dyn ToSql + Sync)]
) -> Result<Vec<tokio_postgres::row::Row>, tokio_postgres::Error>
{  
  let client      = db.get().await.unwrap();
  let statement   = client.prepare_cached(query).await.unwrap();
  
  client.query(&statement, args).await
}

// =====================================================================
pub async fn index(
  req:      HttpRequest,
  session:  Session,
  db:       web::Data<Pool>,
) -> Result<HttpResponse, Error> 
{
  let mut count = 1;
  
  if let Some(sessionid) = session.get::<String>("sessionid")? 
  {
    let rows  = RunQuery(
      &db, 
      "SELECT data 
        FROM usersessions 
        WHERE uid = $1", 
      &[&sessionid]
    ).await.unwrap();
    
    if rows.is_empty()
    {
      let jsondata  = serde_json::json!({
        "count": 1,
      }).to_string();
      
      RunQuery(
        &db, 
        "INSERT INTO usersessions(uid, data)
          VALUES($1, $2)", 
        &[&sessionid, &jsondata]
      ).await
      .expect("Insert failed!");
    } else
    {
      let jsonstring:&str  = rows[0].get(0);
      let countdata: CountData = serde_json::from_str(jsonstring)?;
      
      count = countdata.count;
      
      count += 1;
      
      let jsondata  = serde_json::json!({
        "count": count,
      }).to_string();
      
      RunQuery(
        &db, 
        "UPDATE usersessions
        SET data = $1
        WHERE uid = $2
        ",
        &[&jsondata, &sessionid]
      ).await
      .expect("Update failed!");
    }
  } else 
  {
    let sessionid = Uuid::new_v4().to_string();
    
    let jsondata  = serde_json::json!({
      "count": 1,
    }).to_string();
    
    RunQuery(
      &db, 
      "INSERT INTO usersessions(uid, data)
        VALUES($1, $2)", 
      &[&sessionid, &jsondata]
    ).await
    .expect("Insert failed!");
    
    session.insert("sessionid", sessionid)?;    
  }  
  
  Ok(HttpResponse::Ok().body(format!(
    "Count is {:?}",
    count
  )))
}

یہ Python/Node.js ورژن سے کہیں زیادہ پیچیدہ ہے...

Rust/Actix

╰─➤  cargo run --release
[2023-03-21T23:37:25Z INFO  actix_server::builder] starting 4 workers
Server running at http://127.0.0.1:8888/

╰─➤  wrk -d 10s -t 4 -c 100 http://127.0.0.1:8888
Running 10s test @ http://127.0.0.1:8888
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     9.93ms    3.90ms  77.18ms   94.87%
    Req/Sec     2.59k   226.41     2.83k    89.25%
  102951 requests in 10.03s, 24.59MB read
Requests/sec:  10267.39
Transfer/sec:      2.45MB

اور بہت زیادہ پرفارمنس!

Actix/deadpool_postgres کا استعمال کرنے والا ہمارا زنگ سرور ہماری سابقہ ​​چیمپئن Starlette کو +125%، ExpressJS کو +362%، اور خالص PHP کو +1366% سے ہرا دیتا ہے۔ (میں قاری کے لیے ایک مشق کے طور پر Laravel ورژن کے ساتھ کارکردگی کے ڈیلٹا کو چھوڑ دوں گا۔)

میں نے محسوس کیا ہے کہ زنگ کی زبان سیکھنا بذات خود دوسری زبانوں کے مقابلے میں زیادہ مشکل ہے کیونکہ اس میں 6502 اسمبلی کے باہر جو کچھ بھی دیکھا ہے اس سے کہیں زیادہ گٹچز ہیں، لیکن اگر آپ کا رسٹ سرور 14 گنا بڑھ سکتا ہے۔ صارفین کو آپ کے پی ایچ پی سرور کے طور پر، پھر شاید ٹیکنالوجی کو تبدیل کرنے سے حاصل کرنے کے لیے کچھ ہے۔ اسی لیے Pafera فریم ورک کا اگلا ورژن Rust پر مبنی ہوگا۔ سیکھنے کا وکر اسکرپٹنگ زبانوں سے بہت زیادہ ہے، لیکن کارکردگی اس کے قابل ہوگی۔ اگر آپ Rust سیکھنے کے لیے وقت نہیں لگا سکتے، تو Starlette یا Node.js پر اپنے ٹیک اسٹیک کو بیس کرنا بھی کوئی برا فیصلہ نہیں ہے۔

تکنیکی قرض

پچھلے بیس سالوں میں، ہم سستی سٹیٹک ہوسٹنگ سائٹس سے لے کر LAMP اسٹیک کے ساتھ مشترکہ ہوسٹنگ تک VPSes کو AWS، Azure، اور دیگر کلاؤڈ سروسز تک کرائے پر لے گئے ہیں۔ آج کل، بہت سی کمپنیاں ڈیزائن کے فیصلے کرنے سے مطمئن ہیں جس کی بنیاد پر وہ اسے دستیاب یا سب سے سستا تلاش کر سکتی ہیں کیونکہ آسان کلاؤڈ سروسز کی آمد نے سست سرورز اور ایپلیکیشنز پر مزید ہارڈ ویئر پھینکنا آسان بنا دیا ہے۔ اس سے انہیں طویل مدتی تکنیکی قرضوں کی قیمت پر مختصر مدت کے بڑے فائدے ملے ہیں۔

کیلیفورنیا کے سرجن جنرل کی وارننگ: یہ اصلی خلائی کتا نہیں ہے۔

70 سال پہلے سوویت یونین اور امریکہ کے درمیان زبردست خلائی دوڑ ہوئی تھی۔ سوویت یونین نے ابتدائی سنگ میلوں میں سے زیادہ تر جیتے۔ ان کے پاس سپوتنک میں پہلا سیٹلائٹ تھا، لائیکا میں خلا میں پہلا کتا، لونا 2 میں پہلا چاند خلائی جہاز، یوری گاگرین اور ویلنٹینا تریشکووا میں خلا میں پہلا مرد اور عورت، وغیرہ۔

لیکن وہ آہستہ آہستہ تکنیکی قرض جمع کر رہے تھے۔

اگرچہ سوویت ان کامیابیوں میں سے ہر ایک میں سب سے پہلے تھے، لیکن ان کے انجینئرنگ کے عمل اور اہداف انہیں طویل مدتی فزیبلٹی کے بجائے قلیل مدتی چیلنجوں پر توجہ مرکوز کرنے پر مجبور کر رہے تھے۔ ہر بار جب وہ چھلانگ لگاتے ہیں تو وہ جیت جاتے تھے، لیکن وہ زیادہ تھکے ہوئے اور آہستہ ہوتے جا رہے تھے جب کہ ان کے مخالفین فائنل لائن کی طرف مسلسل قدم اٹھاتے رہے۔

ایک بار جب نیل آرمسٹرانگ نے براہ راست ٹیلی ویژن پر چاند پر اپنے تاریخی قدم رکھے تو امریکیوں نے اس کی قیادت کی، اور پھر سوویت پروگرام کے زوال کے بعد وہیں ٹھہر گئے۔ یہ آج کی کمپنیوں سے مختلف نہیں ہے جنہوں نے طویل سفر کے لیے مناسب عادات اور حکمت عملی تیار کرنے میں ناکام رہتے ہوئے اگلی بڑی چیز، اگلی بڑی ادائیگی، یا اگلی بڑی ٹیک پر توجہ مرکوز کی ہے۔

مارکیٹ میں سب سے پہلے ہونے کا مطلب یہ نہیں ہے کہ آپ اس مارکیٹ میں غالب کھلاڑی بن جائیں گے۔ متبادل طور پر، چیزوں کو درست کرنے کے لیے وقت نکالنا کامیابی کی ضمانت نہیں دیتا، لیکن یقینی طور پر آپ کی طویل مدتی کامیابیوں کے امکانات کو بڑھاتا ہے۔ اگر آپ اپنی کمپنی کے لیے ٹیک لیڈ ہیں، تو اپنے کام کے بوجھ کے لیے صحیح سمت اور ٹولز کا انتخاب کریں۔ مقبولیت کو کارکردگی اور کارکردگی کی جگہ نہ لینے دیں۔

وسائل

زنگ، ایکسپریس جے ایس، فلاسک، اسٹارلیٹ اور خالص پی ایچ پی اسکرپٹس پر مشتمل 7z فائل ڈاؤن لوڈ کرنا چاہتے ہیں؟

مصنف کے بارے میں

جم 90 کی دہائی کے دوران IBM PS/2 واپس ملنے کے بعد سے پروگرامنگ کر رہا ہے۔ آج تک، وہ اب بھی ہاتھ سے HTML اور SQL لکھنے کو ترجیح دیتا ہے، اور اپنے کام میں کارکردگی اور درستگی پر توجہ دیتا ہے۔