Sea, Virginia, Tá *Tá* a Daidí na Nollag Difríocht idir Creataí Gréasáin in 2023

Turas deacair ríomhchláraitheoir amháin chun cód freastalaí gréasáin a fheidhmíonn go tapa a aimsiú sula n-éilíonn sé do bhrú an mhargaidh agus d’fhiachas teicniúil
2023-03-24 11:52:06
👁️ 796
💬 0

Clár ábhair

  1. Réamhrá
  2. An Tástáil
  3. PHP/Laravel
  4. PHP glan
  5. Athchuairt ar Laravel
  6. Django
  7. Fleascán
  8. Réaltóg
  9. Nód.js/ExpressJS
  10. Meirge/Actix
  11. Fiachas Teicniúil
  12. Acmhainní

Réamhrá

Tar éis ceann de na hagallaimh poist is déanaí a bhí agam, bhí ionadh orm a thuiscint go raibh an chuideachta ar chuir mé isteach air fós ag baint úsáide as Laravel, creat PHP a bhain mé triail as tuairim is deich mbliana ó shin. Bhí sé réasúnta go leor ag an am, ach má tá tairiseach amháin sa teicneolaíocht agus san fhaisean araon, déanann sé athrú leanúnach agus athdhromchlú ar stíleanna agus ar choincheapa. Más ríomhchláraitheoir JavaScript thú, is dócha go bhfuil cur amach agat ar an seanscéal seo

Ríomhchláraitheoir 1: "Ní maith liom an creat JavaScript nua seo!"

Ríomhchláraitheoir 2: "Ní gá a bheith buartha. Fan ar feadh sé mhí agus beidh ceann eile ina ionad!"

As fiosracht, chinn mé a fheiceáil go díreach cad a tharlaíonn nuair a chuireamar sean agus nua leis an triail. Ar ndóigh, tá an ngréasán líonta le tagarmharcanna agus éilimh, agus is dócha gurb é an ceann is mó tóir orthu Tagarmharcanna Creat Gréasáin TechEmpower anseo . Nílimid chun aon rud a dhéanamh beagnach chomh casta leo inniu áfach. Coimeádfaimid rudaí go deas simplí araon ionas nach mbeidh an t-alt seo ann Cogadh agus síocháin , agus go mbeidh seans beag agat fanacht i do dhúiseacht faoin am go mbeidh tú réidh leis an léamh. Tá feidhm ag na gnáthfhabhais: b’fhéidir nach n-oibreoidh sé seo mar an gcéanna ar do ríomhaire, is féidir le leaganacha éagsúla bogearraí cur isteach ar fheidhmíocht, agus i ndáiríre rinneadh cat zombie de cat Schrödinger a bhí leath beo agus leath marbh ag an am céanna.

An Tástáil

Timpeallacht Tástála

Don tástáil seo, beidh mé ag baint úsáide as mo ríomhaire glúine armtha le i5 puny ag rith Manjaro Linux mar a thaispeántar anseo.

╰─➤  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

An Tasc ar Láimh

Beidh trí thasc shimplí ag ár gcód do gach iarratas:

  1. Léigh aitheantas seisiúin an úsáideora reatha ó fhianán
  2. Íoslódáil bunachar sonraí breise faisnéise
  3. Seol an fhaisnéis sin ar ais don úsáideoir

Cén cineál tástála leathcheann é sin, d’fhéadfá fiafraí de? Bhuel, má fhéachann tú ar na hiarratais líonra don leathanach seo, tabharfaidh tú faoi deara ceann ar a dtugtar sessionvars.js a dhéanann an rud céanna go díreach.

Tá ábhar sessionvars.js

Feiceann tú, is créatúir casta iad leathanaigh ghréasáin nua-aimseartha, agus ceann de na tascanna is coitianta ná leathanaigh chasta a thaisceadh chun ró-ualach a sheachaint ar an bhfreastalaí bunachar sonraí.

Má dhéanaimid leathanach casta a athsholáthar gach uair a iarrann úsáideoir é, ansin ní féidir linn freastal ach ar thart ar 600 úsáideoir in aghaidh an tsoicind.

╰─➤  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

Ach má thaisceann muid an leathanach seo mar chomhad HTML statach agus má ligimid do Nginx an fhuinneog a chaitheamh amach go tapa don úsáideoir, ansin is féidir linn freastal ar 32,000 úsáideoir in aghaidh an tsoicind, ag méadú feidhmíochta faoi fhachtóir 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

Is é an t-innéacs statach.en.html an chuid a théann chuig gach duine, agus ní sheoltar ach na codanna atá éagsúil de réir úsáideora i sessionvars.js. Ní hamháin go laghdaíonn sé seo ualach an bhunachair shonraí agus cruthaíonn sé eispéireas níos fearr dár n-úsáideoirí, ach laghdaítear freisin na dóchúlachtaí chandamach go ndéanfaidh ár bhfreastalaí ghalú go spontáineach i sárú croí dlúith nuair a ionsaíonn na Klingons.

Ceanglais Chóid

Beidh ceanglas simplí amháin sa chód a sheoltar ar ais le haghaidh gach creata: taispeáin don úsáideoir cé mhéad uair a d'athnuaigh sé/sí an leathanach trí "Count is x" a rá. Chun rudaí a choinneáil simplí, fanfaimid ar shiúl ó scuainí Redis, comhpháirteanna Kubernetes, nó AWS Lambdas go ceann tamaill.

Ag taispeáint cé mhéad uair a thug tú cuairt ar an leathanach

Déanfar sonraí seisiúin gach úsáideora a shábháil i mbunachar sonraí PostgreSQL.

Tábla na seisiún úsáideora

Agus déanfar an tábla bunachar sonraí seo a theorannú roimh gach tástáil.

An tábla tar éis a bheith teasctha

Simplí ach éifeachtach is ea mana Pafera... taobh amuigh den amlíne is dorcha ar aon nós...

Na Torthaí Tástála Iarbhír

PHP/Laravel

Ceart go leor, mar sin anois is féidir linn tosú ar deireadh ag fáil ár lámha salach. Ní dhéanfaidh muid ach an socrú do Laravel a scipeáil ós rud é nach bhfuil ann ach dornán cumadóir agus ceardaí orduithe.

Ar dtús, socróimid ár socruithe bunachar sonraí sa chomhad .env

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

Ansin socróimid bealach cúltaca amháin a sheolann gach iarratas chuig ár rialtóir.

Route::fallback(SessionController::class);

Agus socraigh an rialtóir chun an comhaireamh a thaispeáint. Stórálann Laravel, de réir réamhshocraithe, seisiúin sa bhunachar sonraí. Soláthraíonn sé freisin an session() feidhmiú chun comhéadan a dhéanamh lenár sonraí seisiúin, mar sin ní raibh ach cúpla líne de chód chun ár leathanach a sholáthar.

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

    $count  += 1;

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

    return 'Count is ' . $count;
  }
}

Tar éis php-fpm agus Nginx a bhunú, tá cuma mhaith ar ár leathanach ...

╰─➤  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

Ar a laghad go dtí go bhfeicfimid torthaí na tástála...

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

Ní hea, ní clóscríobhán é sin. Tá ár n-inneall tástála imithe ó 600 iarratas in aghaidh an tsoicind ag déanamh leathanach casta... go 21 iarratas in aghaidh an tsoicind ag déanamh "Count is 1".

Mar sin, cad a chuaigh mícheart? An bhfuil rud éigin cearr lenár suiteáil PHP? An bhfuil Nginx ag moilliú ar bhealach éigin agus é ag idirphlé le php-fpm?

PHP glan

Déanaimis an leathanach seo i gcód PHP glan.

<?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'];

Tá 98 líne de chód úsáidte againn anois chun an méid a rinne ceithre líne de chód (agus cuid iomlán d'obair chumraíochta) i Laravel a dhéanamh. (Ar ndóigh, dá ndéanfaimis láimhseáil cheart earráide agus teachtaireachtaí os comhair úsáideoirí, bheadh ​​sé seo thart ar dhá oiread líon na línte.) B'fhéidir gur féidir linn é a dhéanamh go 30 iarratas in aghaidh an tsoicind?

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

Cé! Tá an chuma ar an scéal nach bhfuil aon rud cearr lenár suiteáil PHP tar éis an tsaoil. Tá an leagan PHP íon ag déanamh 700 iarratas in aghaidh an tsoicind.

Mura bhfuil aon rud cearr le PHP, b’fhéidir go ndearnamar Laravel míchumraithe?

Athchuairt ar Laravel

Tar éis sciúradh a dhéanamh ar an ngréasán le haghaidh saincheisteanna cumraíochta agus leideanna feidhmíochta, ba iad dhá cheann de na teicníochtaí is coitianta ná na sonraí cumraíochta agus bealaigh a thaisceadh chun iad a sheachaint le haghaidh gach iarratais. Mar sin, glacfaimid a gcuid comhairle agus bainfimid triail as na leideanna seo.

╰─➤  php artisan config:cache

   INFO  Configuration cached successfully.  

╰─➤  php artisan route:cache

   INFO  Routes cached successfully.  

Breathnaíonn gach rud go maith ar an líne ordaithe. Déanaimis an tagarmharc arís.

╰─➤  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

Bhuel, tá an fheidhmíocht méadaithe againn anois ó 21.04 go 28.80 iarratas in aghaidh an tsoicind, ardú suntasach de bheagnach 37%! Bheadh ​​sé seo iontach maith d’aon phacáiste bogearraí… ach amháin nach bhfuilimid ag déanamh ach 1/24ú de líon na n-iarratas ar an leagan PHP glan.

Má tá tú ag ceapadh go gcaithfidh go bhfuil rud éigin cearr leis an triail seo, ba cheart duit labhairt le húdar chreat Lucinda PHP. Ina thorthaí tástála, tá Lucinda i gcoinne Laravel faoi ​​36x le haghaidh iarratais HTML agus 90x le haghaidh iarratais JSON.

Tar éis tástáil a dhéanamh ar mo mheaisín féin le Apache agus Nginx araon, níl aon chúis agam a bheith in amhras air. Tá Laravel i ndáiríre díreach go mall! Níl PHP ann féin chomh dona sin, ach a luaithe a chuireann tú isteach an phróiseáil bhreise ar fad a chuireann Laravel le gach iarratas, ansin bíonn sé an-deacair dom Laravel a mholadh mar rogha i 2023.

Django

Cuntais PHP/Wordpress do thart ar 40% de na láithreáin ghréasáin go léir ar an ngréasán , rud a fhágann gurb é an creat is ceannasaí le fada an lá. Ach go pearsanta, is dóigh liom nach gá go n-aistríonn an tóir isteach ar cháilíocht níos mó ná mar a fheictear dom go bhfuil fonn tobann neamhrialaithe agam ar an mbia gourmet neamhghnách sin ó an bhialann is mó tóir ar domhan ... McDonald&#x27;s. Ós rud é go ndearnamar tástáil ar chód PHP íon cheana féin, nílimid chun Wordpress féin a thástáil, mar is cinnte go mbeadh aon rud a bhaineann le Wordpress níos ísle ná an 700 iarratas in aghaidh an tsoicind a thugamar faoi deara le PHP íon.

Is creat tóir eile é Django atá thart le fada an lá. Má d’úsáid tú é san am a chuaigh thart, is dócha go bhfuil tú ag cuimhneamh go fonnmhar ar a chomhéadan iontach riaracháin bunachar sonraí chomh maith le cé chomh buartha is a bhí sé gach rud a chumrú díreach mar a bhí uait. Feicfimid cé chomh maith agus a oibríonn Django in 2023, go háirithe leis an gcomhéadan ASGI nua a chuir sé leis mar leagan 4.0.

Tá bunú Django thar a bheith cosúil le bunú Laravel, mar go raibh siad araon ón aois a raibh ailtireachtaí MVC stylish agus ceart. Léimfimid an chumraíocht leadránach agus rachaimid díreach chuig an radharc a shocrú.

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}")

Tá ceithre líne de chód mar an gcéanna leis an leagan Laravel. Féachaimis conas a fheidhmíonn sé.

╰─➤  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

Ní dona ar chor ar bith le 355 iarratas in aghaidh an tsoicind. Níl ann ach leath d’fheidhmíocht an leagan PHP íon, ach tá sé 12 uair chomh maith le feidhmíocht leagan Laravel. Dealraíonn sé nach bhfuil Django vs Laravel aon chomórtas ar chor ar bith.

Fleascán

Seachas na creataí níos mó gach rud-lena n-áirítear-an-cistine-doirteal, tá creataí níos lú a dhéanamh ach roinnt socrú bunúsach agus a ligeann duit a láimhseáil an chuid eile. Ceann de na cinn is fearr le húsáid ná Flask agus a mhacasamhail ASGI Quart. Mo chuid féin Creat PaferaPy tógtha ar bharr an Fhleasc, agus mar sin tuigim go maith cé chomh héasca is atá sé rudaí a chur i gcrích agus feidhmíocht á chothabháil agam.

#!/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}'

Mar a fheiceann tú, tá an script Flask níos giorra ná an script PHP íon. Faighim amach, as na teangacha go léir a d’úsáid mé, gur dócha gurb é Python an teanga is sainráiteach i dtéarmaí eochairbhuillí a chlóscríobh mé. Mar gheall ar easpa braces agus lúibíní, tuisceana liostaí agus deachtaithe, agus blocáil bunaithe ar eangú seachas leathchoilín, tá Python sách simplí ach cumhachtach ina chumais.

Ar an drochuair, is é Python an teanga ilchuspóireach is moille amuigh ansin, in ainneoin an méid bogearraí atá scríofa ann. Tá líon na leabharlann Python atá ar fáil thart ar cheithre huaire níos mó ná teangacha comhchosúla agus clúdaíonn sé go leor fearainn, ach ní déarfadh éinne go bhfuil Python tapaigh ná feidhmiúil lasmuigh de nideoga mar NumPy.

Féachaimis ar an gcomparáid lenár leagan Fleasc agus na creataí a bhí againn roimhe seo.

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

Tá ár script Fleascán níos tapúla i ndáiríre ná ár leagan PHP íon!

Má chuireann sé seo ionadh ort, ba cheart duit a thuiscint go ndéanann ár n-aip Flask a thúsú agus a chumraíocht go léir nuair a thosaímid ar an bhfreastalaí gunicorn, agus go ndéanann PHP an script a athghníomhú gach uair a thagann iarratas nua isteach. ionann agus Flask mar an tiománaí tacsaí óg fonnmhar atá tosaithe ar an gcarr cheana féin agus atá ag fanacht in aice leis an mbóthar, agus is é PHP an seantiománaí a fhanann ina theach ag fanacht le glao chun teacht isteach agus ní thiomáineann sé ach ansin thar a phiocadh suas tú. Toisc gur seanfhear scoile é agus gur athrú iontach é PHP ar chomhaid simplí HTML agus SHTML, tá sé rud beag brónach a thuiscint cé chomh fada agus a chuaigh thart, ach cuireann na difríochtaí dearaidh go mór deacair ar PHP é. dul san iomaíocht i gcoinne freastalaithe Python, Java, agus Node.js a fhanann sa chuimhne agus a láimhseálann iarratais gan stró gan stró.

Réaltóg

Seans gurb é Flask an creat is tapúla atá againn go dtí seo, ach i ndáiríre is seanbhogearraí deasa é. D’aistrigh pobal Python go dtí na freastalaithe ASGI asycronacha níos nuaí cúpla bliain ar ais, agus ar ndóigh, tá mé féin tar éis aistriú leo.

An leagan is déanaí de Chreat Pafera, PaferaPyAsync , bunaithe ar Starlette. Cé go bhfuil leagan ASGI de Flask ar a dtugtar Quart, ba leor na difríochtaí feidhmíochta idir Quart agus Starlette dom chun mo chód a athbhunú ar Starlette ina ionad sin.

Is féidir le ríomhchlárú eischrónach a bheith scanrúil do go leor daoine, ach i ndáiríre ní coincheap deacair é a bhuíochas do na guys Node.js a raibh an-tóir ar an gcoincheap breis is deich mbliana ó shin.

Ba ghnách linn dul i ngleic le comhairgeadra le il-snáithe, ilphróiseáil, ríomhaireacht dháilte, slabhraiú geallúintí, agus na hamanna spraíúla sin ar fad a chuaigh in aois roimh am agus a dhírigh go leor sean-ríomhchláraitheoirí. Anois, ní dhéanaimid ach clóscríobh async os comhair ár bhfeidhmeanna agus await os comhair aon chód a d'fhéadfadh go dtógfadh sé tamall é a fhorghníomhú. Tá sé go deimhin níos briathartha ná cód rialta, ach i bhfad níos lú annoying a úsáid ná a bheith ag déileáil le sioncrónaithe primitives, teachtaireacht a rith, agus a réiteach geallúintí.

Breathnaíonn ár gcomhad Starlette mar seo:

#!/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",
)

Mar a fheiceann tú, tá sé beagnach cóipeála agus greamaithe ónár script Flask gan ach cúpla athrú ródaithe agus an async/await eochairfhocail.

Cé mhéad feabhsaithe is féidir cód a chóipeáil agus a ghreamú a thabhairt dúinn i ndáiríre?

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

Tá curadh nua againn, a dhaoine uaisle! Ba é an leagan is airde a bhí againn roimhe seo ná ár leagan PHP íon ag 704 iarratas in aghaidh an tsoicind, a sháraigh ár leagan Flask ag 1080 iarratas in aghaidh an tsoicind. Brúiteann ár script Starlette gach iomaitheoir roimhe seo ag 4562 iarratas in aghaidh an tsoicind, rud a chiallaíonn feabhas 6x thar PHP íon agus feabhsú 4x thar Flask.

Murar athraigh tú do chód Python WSGI go ASGI fós, seans gur am trátha é chun tosú.

Nód.js/ExpressJS

Go dtí seo, níl ach creataí PHP agus Python clúdaithe againn. Mar sin féin, úsáideann cuid mhór den domhan Java, DotNet, Node.js, Ruby on Rails, agus teicneolaíochtaí eile dá leithéid dá láithreáin ghréasáin. Ní forbhreathnú cuimsitheach é seo ar éiceachórais agus bithóim uile an domhain ar chor ar bith, mar sin chun coibhéis ríomhchláraithe na ceimice orgánaí a sheachaint, ní roghnóimid ach na creataí is éasca cód a chlóscríobh dóibh. . nach bhfuil Java cinnte.

Mura bhfuil tú i bhfolach faoi do chóip de K&RC nó Knuth&#x27;s Ealaín na ríomhchláraithe le cúig bliana déag anuas, is dócha gur chuala tú trácht ar Node.js. Tá na daoine againn atá thart ó thús JavaScript thar a bheith scanraithe, faoi ionadh, nó an dá rud faoi staid JavaScript nua-aimseartha, ach níl aon séanadh go bhfuil JavaScript éirithe mar fhórsa le bheith san áireamh ar fhreastalaithe freisin. mar bhrabhsálaithe. Tar éis an tsaoil, tá fiú slánuimhreacha 64 giotán dúchasacha againn anois sa teanga! Tá sé sin i bhfad níos fearr ná gach rud a stóráiltear i snámháin 64 giotán i bhfad!

Is dócha gurb é ExpressJS an freastalaí Node.js is fusa le húsáid, mar sin déanfaimid aip Node.js/ExpressJS sciobtha salach chun freastal ar ár gcuntar.

/**********************************************************************
 * 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}`));

Bhí an cód seo níos fusa i ndáiríre a scríobh ná na leaganacha Python, cé go n-éiríonn JavaScript dúchais sách dochloíte nuair a éiríonn feidhmchláir níos mó, agus go tapa éiríonn gach iarracht é seo a cheartú mar TypeScript níos briathartha ná Python.

Feicfimid conas a fheidhmíonn sé seo!

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

Seans gur chuala tú seanscéalta (ársa de réir caighdeáin Idirlín ar aon nós...) faoi Node.js&#x27; luas, agus tá na scéalta sin fíor den chuid is mó a bhuíochas leis an obair iontach atá déanta ag Google leis an inneall V8 JavaScript. Sa chás seo, áfach, cé go n-éiríonn lenár n-aip sciobtha níos fearr ná an script Flask, tá a nádúr snáithithe aonair sáraithe ag na ceithre phróiseas async atá á bhfeidhmiú ag an Starletette Knight a deir "Ni!&quot;.

Faighimid tuilleadh cabhrach!

╰─➤  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 │
└────┴──────────────┴─────────────┴─────────┴─────────┴──────────┴────────┴──────┴───────────┴──────────┴──────────┴──────────┴──────────┘

Ceart go leor! Anois is cath cothrom ceithre ar cheithre é! Déanaimis tagarmharcáil!

╰─➤  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

Fós ní ag leibhéal Starlette, ach níl sé go dona le haghaidh hack JavaScript tapa cúig nóiméad. Ó mo thástáil féin, tá an script seo á choinneáil siar beagán ag leibhéal comhéadan an bhunachair shonraí toisc nach bhfuil nód-postgres chomh héifeachtach agus atá psychcopg do Python. Nuair a aistrítear go sqlite mar thiománaí an bhunachair sonraí, tagann níos mó ná 3000 iarratas in aghaidh an tsoicind ar an gcód ExpressJS céanna.

Is é an rud is mó le tabhairt faoi deara, in ainneoin luas mall forghníomhaithe Python, is féidir le creataí ASGI a bheith iomaíoch i ndáiríre le réitigh Node.js le haghaidh ualaí oibre áirithe.

Meirge/Actix

Mar sin anois, táimid ag druidim níos gaire do bharr an tsléibhe, agus de réir sléibhe, is é atá i gceist agam ná na scóir tagarmharcála is airde a thaifead lucha agus fir araon.

Má fhéachann tú ar fhormhór na dtagarmharcanna creatlaí atá ar fáil ar an ngréasán, tabharfaidh tú faoi deara go bhfuil dhá theanga ann a mbíonn ceannas ag an mbarr: C++ agus Rust. D’oibrigh mé le C++ ó na 90idí, agus bhí mo chreat Win32 C++ féin agam ar ais sula raibh MFC/ATL ina rud, mar sin tá go leor taithí agam ar an teanga. Níl sé an-spraoi a bheith ag obair le rud éigin nuair atá sé ar eolas agat cheana féin, mar sin táimid chun leagan Rust a dhéanamh ina ionad sin. ;)

Tá Rust sách nua ó thaobh teangacha ríomhchlárúcháin de, ach tháinig sé ina ábhar fiosrachta dom nuair a d’fhógair Linus Torvalds go nglacfadh sé le Rust mar theanga ríomhchláraithe eithne Linux. Maidir le ríomhchláraitheoirí níos sine, tá sé sin thart ar an gcéanna le rá gur leasú nua ar Bhunreacht na SA a bheidh sa hippie thingie nua d’aois nua seo.

Anois, nuair is ríomhchláraitheoir le taithí tú, de ghnáth ní léimeann tú ar an mbanna ceoil chomh tapa agus a dhéanann daoine óga, nó d’fhéadfadh sé go mbeadh tú dóite ag athruithe tapa ar an teanga nó ar na leabharlanna. (Beidh a fhios ag duine ar bith a d’úsáid an chéad leagan de AngularJS cad faoi atáim ag caint.) Tá meirge fós ag céim na forbartha turgnamhaí sin, agus is greannmhar liom nach fiú an iliomad samplaí cód ar an ngréasán. tiomsaigh níos mó leis na leaganacha reatha de phacáistí.

Ní féidir an fheidhmíocht a léirigh feidhmchláir Rust a dhiúltú, áfach. Mura ndearna tú iarracht riamh rigrep fd-aimsigh amach ar chrainn cód foinse mór, ba chóir duit a thabhairt cinnte casadh dóibh. Tá siad ar fáil fiú don chuid is mó de dháileacháin Linux go simplí ón mbainisteoir pacáiste. Tá tú ag malartú briathrachais le haghaidh feidhmíochta le Rust... a lán of briathrachas le haghaidh a lán of feidhmíochta.

Tá an cód iomlán le haghaidh Rust beagán mór, mar sin ní dhéanfaimid ach breathnú ar na láimhseálaithe ábhartha anseo:

// =====================================================================
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
  )))
}

Tá sé seo i bhfad níos casta ná na leaganacha 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

Agus i bhfad níos mó taibheoir!

Buaileann ár bhfreastalaí meirge ag baint úsáide as Actix/deadpool_postgres ár laoch Starlette roimhe seo le +125%, ExpressJS le +362%, agus PHP íon ag +1366%. (Fágfaidh mé an deilt léirithe leis an leagan Laravel mar chleachtadh don léitheoir.)

Fuair ​​​​mé amach go raibh sé níos deacra an teanga Rust féin a fhoghlaim ná teangacha eile toisc go bhfuil i bhfad níos mó seans ann ná rud ar bith a chonaic mé lasmuigh de Thionól 6502, ach más féidir le do fhreastalaí Rust glacadh le 14x líon na úsáideoirí mar do fhreastalaí PHP, ansin b’fhéidir go bhfuil rud éigin le baint as teicneolaíochtaí a athrú tar éis an tsaoil. Sin an fáth a mbeidh an chéad leagan eile de Chreat Pafera bunaithe ar Rust. Tá an cuar foghlama i bhfad níos airde ná teangacha scriptithe, ach is fiú an fheidhmíocht. Murar féidir leat an t-am a chur isteach chun Rust a fhoghlaim, ní droch-chinneadh é do chruach teicneolaíochta a bhunú ar Starlette nó Node.js ach an oiread.

Fiachas Teicniúil

Le fiche bliain anuas, táimid imithe ó shuíomhanna óstála statacha saor go hóstáil roinnte le stoic LAMP go VPSanna a ligean ar cíos chuig AWS, Azure, agus seirbhísí scamall eile. Sa lá atá inniu ann, tá go leor cuideachtaí sásta le cinntí dearaidh a dhéanamh bunaithe ar cibé acu atá ar fáil nó is saoire ó tháinig seirbhísí áisiúla néal a d’fhág go raibh sé éasca níos mó crua-earraí a chaitheamh ar fhreastalaithe agus feidhmchláir mhall. Thug sé seo gnóthachain iontacha gearrthéarmacha dóibh ar chostas fiacha teicniúil fadtéarmach.

Rabhadh Máinlia Ginearálta California: Ní madra spáis fíor é seo.

70 bliain ó shin, bhí rás spás mór idir an tAontas Sóivéadach agus na Stáit Aontaithe. Bhuaigh na Sóivéadaigh an chuid is mó de na garspriocanna tosaigh. Bhí an chéad satailít acu i Sputnik, an chéad mhadra sa spás i Laika, an chéad spásárthach gealaí i Luna 2, an chéad fhear agus bean sa spás i Yuri Gagarin agus Valentina Tereshkova, agus mar sin de...

Ach bhí siad go mall carnadh fiach teicniúil.

Cé gurbh iad na Sóivéadaigh ba thúisce a bhain gach ceann de na héachtaí seo amach, bhí a bpróisis agus a spriocanna innealtóireachta ag cur as dóibh díriú ar dhúshláin ghearrthéarmacha seachas ar indéantacht fhadtéarmach. Bhuaigh siad gach uair a léim siad, ach bhí siad ag éirí níos tuirseach agus níos moille fad is a lean a gcéilí comhraic ag déanamh dul chun cinn comhsheasmhach i dtreo na líne deiridh.

Nuair a ghlac Neil Armstrong a chéimeanna stairiúla ar an ngealach ar theilifís bheo, ghlac na Meiriceánaigh an lámh in uachtar, agus ansin d’fhan siad ann agus clár na Sóivéide imithe i léig. Ní hionann é sin agus cuideachtaí sa lá atá inniu ann a dhírigh ar an gcéad rud mór eile, ar an gcéad íocaíocht mhór eile, nó ar an gcéad theicneolaíocht mhór eile agus iad ag teip ar nósanna agus straitéisí cearta a fhorbairt don turas fada.

Ní hionann sin is a rá go mbeidh tú i do cheannasaí sa mhargadh sin. Mar mhalairt air sin, ní ráthaítear go n-éireoidh leis an am a ghlacadh chun rudaí a dhéanamh ina gceart, ach is cinnte go méadaíonn sé do sheans go mbainfidh tú éachtaí fadtéarmacha amach. Más tusa an ceannaire teicneolaíochta do do chuideachta, roghnaigh an treo agus na huirlisí ceart do d’ualach oibre. Ná lig don tóir a bheith in ionad feidhmíochta agus éifeachtúlachta.

Acmhainní

Ar mhaith leat comhad 7z a íoslódáil ina bhfuil na scripteanna Rust, ExpressJS, Flask, Starlette, agus Pure PHP?

Maidir leis an Údar

Tá Jim ag ríomhchlárú ó fuair sé IBM PS/2 ar ais i rith na 90idí. Go dtí an lá atá inniu ann, is fearr leis fós HTML agus SQL a scríobh de láimh, agus díríonn sé ar éifeachtúlacht agus cruinneas ina chuid oibre.