806 lines
25 KiB
Python
806 lines
25 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Создаёт/обновляет 6 benchmark-функций с ~10KB кода и тяжёлой вычислительной нагрузкой.
|
||
Случайные задержки, матрицы, сортировки, хэши — настоящая нагрузка.
|
||
"""
|
||
import json, subprocess, sys
|
||
|
||
BASE = "https://fission.kube5s.ru/console/api"
|
||
SUB = "livetest@test.local"
|
||
|
||
# ── Node.js ──────────────────────────────────────────────────────────────────
|
||
NODE_CODE = r"""module.exports = async (ctx) => {
|
||
// ~10KB of real CPU work + async delays with random timing
|
||
|
||
function sleep(ms) { return new Promise(r => setTimeout(r, ms)); }
|
||
|
||
function millerRabin(n) {
|
||
if (n < 2) return false; if (n===2||n===3||n===5||n===7) return true;
|
||
if (n%2===0) return false;
|
||
let d=n-1, r=0; while(d%2===0){d/=2;r++;}
|
||
const witnesses=[2,3,5,7,11,13,17,19,23,29,31,37];
|
||
for(const a of witnesses){
|
||
if(a>=n)continue; let x=modPow(a,d,n);
|
||
if(x===1||x===n-1)continue; let cont=false;
|
||
for(let i=0;i<r-1;i++){x=modPow(x,2,n);if(x===n-1){cont=true;break;}}
|
||
if(!cont)return false;
|
||
}
|
||
return true;
|
||
}
|
||
function modPow(base,exp,mod){
|
||
let result=1n,b=BigInt(base),e=BigInt(exp),m=BigInt(mod);
|
||
b%=m; while(e>0n){if(e%2n===1n)result=result*b%m;e>>=1n;b=b*b%m;}
|
||
return Number(result);
|
||
}
|
||
|
||
function gcd(a,b){while(b){[a,b]=[b,a%b];}return a;}
|
||
function lcm(a,b){return a/gcd(a,b)*b;}
|
||
|
||
function lucas(n){
|
||
if(n===0)return 2; if(n===1)return 1;
|
||
let a=2,b=1; for(let i=2;i<=n;i++){let t=a+b;a=b;b=t;} return b;
|
||
}
|
||
|
||
function fnv1a(str){
|
||
let h=2166136261>>>0;
|
||
for(let i=0;i<str.length;i++){h^=str.charCodeAt(i);h=Math.imul(h,16777619)>>>0;}
|
||
return h;
|
||
}
|
||
|
||
function collatz(n){let s=0;while(n!==1){n=n%2===0?n/2:3*n+1;s++;}return s;}
|
||
|
||
function hornerEval(coeffs,x){
|
||
let r=0; for(let i=coeffs.length-1;i>=0;i--)r=r*x+coeffs[i]; return r;
|
||
}
|
||
|
||
function digitSum(n){let s=0;while(n>0){s+=n%10;n=Math.floor(n/10);}return s;}
|
||
|
||
function sundaramSieve(n){
|
||
const lim=Math.floor((n-2)/2);
|
||
const s=new Array(lim+1).fill(false);
|
||
for(let i=1;i<=lim;i++) for(let j=i;i+j+2*i*j<=lim;j++) s[i+j+2*i*j]=true;
|
||
const primes=[2];
|
||
for(let i=1;i<=lim;i++) if(!s[i]) primes.push(2*i+1);
|
||
return primes;
|
||
}
|
||
|
||
function rleEncode(arr){
|
||
if(!arr.length)return[];
|
||
const out=[];let cur=arr[0],cnt=1;
|
||
for(let i=1;i<arr.length;i++){if(arr[i]===cur)cnt++;else{out.push([cur,cnt]);cur=arr[i];cnt=1;}}
|
||
out.push([cur,cnt]);return out;
|
||
}
|
||
|
||
function heapSort(arr){
|
||
const a=[...arr],n=a.length;
|
||
function heapify(i,size){let l=2*i+1,r=2*i+2,m=i;if(l<size&&a[l]>a[m])m=l;if(r<size&&a[r]>a[m])m=r;if(m!==i){[a[i],a[m]]=[a[m],a[i]];heapify(m,size);}}
|
||
for(let i=Math.floor(n/2)-1;i>=0;i--)heapify(i,n);
|
||
for(let i=n-1;i>0;i--){[a[0],a[i]]=[a[i],a[0]];heapify(0,i);}
|
||
return a;
|
||
}
|
||
|
||
function fib(n) {
|
||
if (n <= 1) return n;
|
||
let a = 0, b = 1;
|
||
for (let i = 2; i <= n; i++) { let t = a + b; a = b; b = t; }
|
||
return b;
|
||
}
|
||
|
||
function isPrime(n) {
|
||
if (n < 2) return false;
|
||
if (n === 2) return true;
|
||
if (n % 2 === 0) return false;
|
||
for (let i = 3; i * i <= n; i += 2) if (n % i === 0) return false;
|
||
return true;
|
||
}
|
||
|
||
function sieveOfEratosthenes(limit) {
|
||
const sieve = new Array(limit + 1).fill(true);
|
||
sieve[0] = sieve[1] = false;
|
||
for (let i = 2; i * i <= limit; i++) {
|
||
if (sieve[i]) for (let j = i * i; j <= limit; j += i) sieve[j] = false;
|
||
}
|
||
return sieve.map((v, i) => v ? i : -1).filter(v => v > 0);
|
||
}
|
||
|
||
function matMul(A, B, n) {
|
||
const C = Array.from({length: n}, () => new Array(n).fill(0));
|
||
for (let i = 0; i < n; i++)
|
||
for (let k = 0; k < n; k++)
|
||
for (let j = 0; j < n; j++)
|
||
C[i][j] += A[i][k] * B[k][j];
|
||
return C;
|
||
}
|
||
|
||
function makeMatrix(n, seed) {
|
||
const M = [];
|
||
for (let i = 0; i < n; i++) {
|
||
const row = [];
|
||
for (let j = 0; j < n; j++) row.push(((i * n + j + seed) % 17) * 0.1 + 1);
|
||
M.push(row);
|
||
}
|
||
return M;
|
||
}
|
||
|
||
function bubbleSort(arr) {
|
||
const a = [...arr];
|
||
for (let i = 0; i < a.length; i++)
|
||
for (let j = 0; j < a.length - i - 1; j++)
|
||
if (a[j] > a[j+1]) { let t = a[j]; a[j] = a[j+1]; a[j+1] = t; }
|
||
return a;
|
||
}
|
||
|
||
function mergeSort(arr) {
|
||
if (arr.length <= 1) return arr;
|
||
const mid = Math.floor(arr.length / 2);
|
||
const L = mergeSort(arr.slice(0, mid));
|
||
const R = mergeSort(arr.slice(mid));
|
||
const res = [];
|
||
let i = 0, j = 0;
|
||
while (i < L.length && j < R.length)
|
||
res.push(L[i] <= R[j] ? L[i++] : R[j++]);
|
||
return res.concat(L.slice(i)).concat(R.slice(j));
|
||
}
|
||
|
||
function lcg(seed) {
|
||
// Linear Congruential Generator for pseudo-random
|
||
return ((seed * 1664525 + 1013904223) & 0xffffffff) >>> 0;
|
||
}
|
||
|
||
function generateArray(size, seed) {
|
||
const arr = [];
|
||
let s = seed;
|
||
for (let i = 0; i < size; i++) { s = lcg(s); arr.push(s % 10000); }
|
||
return arr;
|
||
}
|
||
|
||
function polyEval(coeffs, x) {
|
||
let result = 0, power = 1;
|
||
for (const c of coeffs) { result += c * power; power *= x; }
|
||
return result;
|
||
}
|
||
|
||
function computeHash(str) {
|
||
let hash = 5381;
|
||
for (let i = 0; i < str.length; i++) hash = ((hash << 5) + hash + str.charCodeAt(i)) & 0xffffffff;
|
||
return hash >>> 0;
|
||
}
|
||
|
||
function runRLE(data) {
|
||
// Run-length encoding
|
||
if (!data.length) return [];
|
||
const out = [];
|
||
let cur = data[0], cnt = 1;
|
||
for (let i = 1; i < data.length; i++) {
|
||
if (data[i] === cur) cnt++;
|
||
else { out.push([cur, cnt]); cur = data[i]; cnt = 1; }
|
||
}
|
||
out.push([cur, cnt]);
|
||
return out;
|
||
}
|
||
|
||
// Random delay 200ms–1500ms
|
||
const delay = 200 + (lcg(Date.now() & 0xffff) % 1300);
|
||
await sleep(delay);
|
||
|
||
// Phase 1: Sieve primes up to 2000
|
||
const primes = sieveOfEratosthenes(2000);
|
||
await sleep(50 + (lcg(primes.length) % 200));
|
||
|
||
// Phase 2: Fibonacci batch
|
||
const fibs = [];
|
||
for (let i = 20; i <= 50; i += 5) fibs.push({ n: i, val: fib(i) });
|
||
await sleep(30 + (lcg(fibs.length * 7) % 150));
|
||
|
||
// Phase 3: Matrix multiply 20×20
|
||
const A = makeMatrix(20, 3);
|
||
const B = makeMatrix(20, 7);
|
||
const C = matMul(A, B, 20);
|
||
const matSum = C.reduce((s, row) => s + row.reduce((a, b) => a + b, 0), 0);
|
||
await sleep(20 + (lcg(Math.floor(matSum) & 0xffff) % 100));
|
||
|
||
// Phase 4: Sort 800 elements two ways
|
||
const arr800 = generateArray(800, 42);
|
||
const bSorted = bubbleSort(arr800.slice(0, 200));
|
||
const mSorted = mergeSort(arr800);
|
||
await sleep(10 + (lcg(bSorted[0]) % 80));
|
||
|
||
// Phase 5: Polynomial evaluation
|
||
const coeffs = [1, -3, 2, 5, -1, 4, -2, 1, 3, -1, 2, 1, -3, 2, 5, -1];
|
||
const polyResults = [];
|
||
for (let x = -5; x <= 5; x += 0.5) polyResults.push(polyEval(coeffs, x));
|
||
await sleep(10 + (lcg(polyResults.length * 3) % 60));
|
||
|
||
// Phase 6: Hash chain
|
||
let h = computeHash("bench-node-start");
|
||
const hashChain = [h];
|
||
for (let i = 0; i < 500; i++) { h = computeHash(String(h)); hashChain.push(h); }
|
||
|
||
// Phase 7: RLE on prime indicators
|
||
const indicators = Array.from({length: 500}, (_, i) => isPrime(i) ? 1 : 0);
|
||
const rle = runRLE(indicators);
|
||
|
||
await sleep(10 + (lcg(hashChain[hashChain.length - 1] & 0xffff) % 50));
|
||
|
||
return {
|
||
body: JSON.stringify({
|
||
language: "nodejs",
|
||
delay_ms: delay,
|
||
prime_count: primes.length,
|
||
prime_sum: primes.reduce((a, b) => a + b, 0),
|
||
fibs: fibs,
|
||
mat_sum: matSum.toFixed(4),
|
||
sort_check: mSorted[0] <= mSorted[mSorted.length - 1],
|
||
poly_max: Math.max(...polyResults).toFixed(4),
|
||
hash_final: hashChain[hashChain.length - 1],
|
||
rle_segments: rle.length,
|
||
})
|
||
};
|
||
};
|
||
"""
|
||
|
||
# ── PHP ───────────────────────────────────────────────────────────────────────
|
||
PHP_CODE = r"""<?php
|
||
function handler($context) {
|
||
// ~10KB CPU work + random delays
|
||
|
||
$startTime = microtime(true);
|
||
|
||
// LCG pseudo-random
|
||
function lcg_rand($seed) {
|
||
return (($seed * 1664525 + 1013904223) & 0x7fffffff);
|
||
}
|
||
|
||
function is_prime($n) {
|
||
if ($n < 2) return false;
|
||
if ($n === 2) return true;
|
||
if ($n % 2 === 0) return false;
|
||
for ($i = 3; $i * $i <= $n; $i += 2) if ($n % $i === 0) return false;
|
||
return true;
|
||
}
|
||
|
||
function sieve($limit) {
|
||
$s = array_fill(0, $limit + 1, true);
|
||
$s[0] = $s[1] = false;
|
||
for ($i = 2; $i * $i <= $limit; $i++)
|
||
if ($s[$i]) for ($j = $i * $i; $j <= $limit; $j += $i) $s[$j] = false;
|
||
$primes = [];
|
||
for ($i = 2; $i <= $limit; $i++) if ($s[$i]) $primes[] = $i;
|
||
return $primes;
|
||
}
|
||
|
||
function mat_mul($A, $B, $n) {
|
||
$C = array_fill(0, $n, array_fill(0, $n, 0.0));
|
||
for ($i = 0; $i < $n; $i++)
|
||
for ($k = 0; $k < $n; $k++)
|
||
for ($j = 0; $j < $n; $j++)
|
||
$C[$i][$j] += $A[$i][$k] * $B[$k][$j];
|
||
return $C;
|
||
}
|
||
|
||
function make_matrix($n, $seed) {
|
||
$M = [];
|
||
for ($i = 0; $i < $n; $i++) {
|
||
$row = [];
|
||
for ($j = 0; $j < $n; $j++) $row[] = (($i * $n + $j + $seed) % 17) * 0.1 + 1.0;
|
||
$M[] = $row;
|
||
}
|
||
return $M;
|
||
}
|
||
|
||
function fib($n) {
|
||
if ($n <= 1) return $n;
|
||
$a = 0; $b = 1;
|
||
for ($i = 2; $i <= $n; $i++) { $t = $a + $b; $a = $b; $b = $t; }
|
||
return $b;
|
||
}
|
||
|
||
function insertion_sort($arr) {
|
||
$n = count($arr);
|
||
for ($i = 1; $i < $n; $i++) {
|
||
$key = $arr[$i]; $j = $i - 1;
|
||
while ($j >= 0 && $arr[$j] > $key) { $arr[$j + 1] = $arr[$j]; $j--; }
|
||
$arr[$j + 1] = $key;
|
||
}
|
||
return $arr;
|
||
}
|
||
|
||
function poly_eval($coeffs, $x) {
|
||
$result = 0.0; $power = 1.0;
|
||
foreach ($coeffs as $c) { $result += $c * $power; $power *= $x; }
|
||
return $result;
|
||
}
|
||
|
||
function djb2($str) {
|
||
$hash = 5381;
|
||
for ($i = 0; $i < strlen($str); $i++) $hash = (($hash << 5) + $hash + ord($str[$i])) & 0x7fffffff;
|
||
return $hash;
|
||
}
|
||
|
||
// Random delay 300ms-1200ms via usleep
|
||
$seed = (int)(microtime(true) * 1000) & 0xffff;
|
||
$delay_us = (300 + lcg_rand($seed) % 900) * 1000;
|
||
usleep($delay_us);
|
||
|
||
// Phase 1: Sieve primes up to 2000
|
||
$primes = sieve(2000);
|
||
$prime_sum = array_sum($primes);
|
||
|
||
// Phase 2: Fibonacci batch
|
||
$fibs = [];
|
||
for ($i = 20; $i <= 50; $i += 5) $fibs[$i] = fib($i);
|
||
usleep(30000 + lcg_rand(count($fibs)*7) % 100000);
|
||
|
||
// Phase 3: Matrix 20x20
|
||
$A = make_matrix(20, 5);
|
||
$B = make_matrix(20, 9);
|
||
$C = mat_mul($A, $B, 20);
|
||
$mat_sum = 0.0;
|
||
foreach ($C as $row) foreach ($row as $v) $mat_sum += $v;
|
||
usleep(20000 + lcg_rand((int)$mat_sum & 0xffff) % 80000);
|
||
|
||
// Phase 4: Insertion sort 300 elements
|
||
$arr = [];
|
||
$s2 = 99;
|
||
for ($i = 0; $i < 300; $i++) { $s2 = lcg_rand($s2); $arr[] = $s2 % 10000; }
|
||
$sorted = insertion_sort($arr);
|
||
usleep(10000 + lcg_rand($sorted[0]) % 60000);
|
||
|
||
// Phase 5: Polynomial evaluation
|
||
$coeffs = [1, -3, 2, 5, -1, 4, -2, 1, 3, -1, 2, 1, -3, 2, 5, -1];
|
||
$poly_max = -1e18;
|
||
for ($x = -5.0; $x <= 5.0; $x += 0.5) {
|
||
$v = poly_eval($coeffs, $x);
|
||
if ($v > $poly_max) $poly_max = $v;
|
||
}
|
||
usleep(10000 + lcg_rand(count($primes)) % 50000);
|
||
|
||
// Phase 6: Hash chain 500 iterations
|
||
$h = djb2("bench-php-start");
|
||
$chain = [$h];
|
||
for ($i = 0; $i < 500; $i++) { $h = djb2((string)$h); $chain[] = $h; }
|
||
|
||
// Phase 7: Count twin primes
|
||
$twins = 0;
|
||
for ($i = 0; $i < count($primes) - 1; $i++)
|
||
if ($primes[$i + 1] - $primes[$i] === 2) $twins++;
|
||
|
||
usleep(10000 + lcg_rand(end($chain)) % 40000);
|
||
|
||
$elapsed = round((microtime(true) - $startTime) * 1000);
|
||
|
||
$context["response"]->getBody()->write(json_encode([
|
||
"language" => "php",
|
||
"delay_ms" => (int)($delay_us / 1000),
|
||
"elapsed_ms" => $elapsed,
|
||
"prime_count" => count($primes),
|
||
"prime_sum" => $prime_sum,
|
||
"fib45" => $fibs[45],
|
||
"mat_sum" => round($mat_sum, 4),
|
||
"sort_ok" => $sorted[0] <= $sorted[count($sorted)-1],
|
||
"poly_max" => round($poly_max, 4),
|
||
"hash_final" => end($chain),
|
||
"twin_primes" => $twins,
|
||
]));
|
||
}
|
||
"""
|
||
|
||
# ── Ruby ──────────────────────────────────────────────────────────────────────
|
||
RUBY_CODE = r"""def handler
|
||
require 'json'
|
||
|
||
start_time = Time.now
|
||
|
||
# LCG pseudo-random
|
||
lcg = ->(s) { ((s * 1664525 + 1013904223) & 0x7fffffff) }
|
||
|
||
is_prime = ->(n) {
|
||
return false if n < 2
|
||
return true if n == 2
|
||
return false if n.even?
|
||
d = 3; while d * d <= n; return false if n % d == 0; d += 2; end
|
||
true
|
||
}
|
||
|
||
sieve = ->(limit) {
|
||
s = Array.new(limit + 1, true); s[0] = s[1] = false
|
||
i = 2; while i * i <= limit
|
||
if s[i]; j = i * i; while j <= limit; s[j] = false; j += i; end; end
|
||
i += 1
|
||
end
|
||
(2..limit).select { |k| s[k] }
|
||
}
|
||
|
||
mat_mul = ->(a, b, n) {
|
||
c = Array.new(n) { Array.new(n, 0.0) }
|
||
n.times { |i| n.times { |k| n.times { |j| c[i][j] += a[i][k] * b[k][j] } } }
|
||
c
|
||
}
|
||
|
||
make_matrix = ->(n, seed) {
|
||
Array.new(n) { |i| Array.new(n) { |j| ((i * n + j + seed) % 17) * 0.1 + 1.0 } }
|
||
}
|
||
|
||
fib = ->(n) {
|
||
return n if n <= 1
|
||
a, b = 0, 1; (n - 1).times { a, b = b, a + b }; b
|
||
}
|
||
|
||
shell_sort = ->(arr) {
|
||
a = arr.dup; gap = a.length / 2
|
||
while gap > 0
|
||
(gap...a.length).each { |i| tmp = a[i]; j = i; while j >= gap && a[j-gap] > tmp; a[j] = a[j-gap]; j -= gap; end; a[j] = tmp }
|
||
gap /= 2
|
||
end
|
||
a
|
||
}
|
||
|
||
poly_eval = ->(coeffs, x) {
|
||
result = 0.0; power = 1.0
|
||
coeffs.each { |c| result += c * power; power *= x }
|
||
result
|
||
}
|
||
|
||
djb2 = ->(str) {
|
||
h = 5381; str.each_byte { |b| h = ((h << 5) + h + b) & 0x7fffffff }; h
|
||
}
|
||
|
||
collatz = ->(n) { steps = 0; while n != 1; n = n.even? ? n / 2 : 3 * n + 1; steps += 1; end; steps }
|
||
|
||
# Random delay 250ms-1600ms
|
||
seed = (Time.now.to_f * 1000).to_i & 0xffff
|
||
delay_ms = 250 + lcg.(seed) % 1350
|
||
sleep(delay_ms / 1000.0)
|
||
|
||
# Phase 1: Sieve
|
||
primes = sieve.(2000)
|
||
prime_sum = primes.sum
|
||
sleep(0.05 + (lcg.(primes.length) % 200) / 1000.0)
|
||
|
||
# Phase 2: Fibonacci batch
|
||
fibs = (20..50).step(5).map { |n| [n, fib.(n)] }.to_h
|
||
sleep(0.03 + (lcg.(fibs.length * 7) % 150) / 1000.0)
|
||
|
||
# Phase 3: Matrix 20x20
|
||
a_mat = make_matrix.(20, 4)
|
||
b_mat = make_matrix.(20, 8)
|
||
c_mat = mat_mul.(a_mat, b_mat, 20)
|
||
mat_sum = c_mat.flatten.sum
|
||
sleep(0.02 + (lcg.(mat_sum.to_i & 0xffff) % 100) / 1000.0)
|
||
|
||
# Phase 4: Shell sort 500 elements
|
||
s2 = 77
|
||
arr = Array.new(500) { s2 = lcg.(s2); s2 % 10000 }
|
||
sorted = shell_sort.(arr)
|
||
sleep(0.01 + (lcg.(sorted.first) % 80) / 1000.0)
|
||
|
||
# Phase 5: Polynomial
|
||
coeffs = [1, -3, 2, 5, -1, 4, -2, 1, 3, -1, 2, 1, -3, 2, 5, -1]
|
||
poly_max = (-5.0..5.0).step(0.5).map { |x| poly_eval.(coeffs, x) }.max
|
||
sleep(0.01 + (lcg.(primes.length) % 60) / 1000.0)
|
||
|
||
# Phase 6: Hash chain
|
||
h = djb2.("bench-ruby-start")
|
||
chain = [h]
|
||
500.times { h = djb2.(h.to_s); chain << h }
|
||
|
||
# Phase 7: Collatz max steps for 1..200
|
||
collatz_max = (1..200).map { |n| collatz.(n) }.max
|
||
sleep(0.01 + (lcg.(chain.last & 0xffff) % 50) / 1000.0)
|
||
|
||
elapsed_ms = ((Time.now - start_time) * 1000).round
|
||
|
||
{
|
||
language: "ruby",
|
||
delay_ms: delay_ms,
|
||
elapsed_ms: elapsed_ms,
|
||
prime_count: primes.size,
|
||
prime_sum: prime_sum,
|
||
fib45: fibs[45],
|
||
mat_sum: mat_sum.round(4),
|
||
sort_ok: sorted.first <= sorted.last,
|
||
poly_max: poly_max.round(4),
|
||
hash_final: chain.last,
|
||
collatz_max: collatz_max,
|
||
}.to_json
|
||
end
|
||
"""
|
||
|
||
# ── Perl ──────────────────────────────────────────────────────────────────────
|
||
PERL_CODE = r"""sub {
|
||
use Time::HiRes qw(time usleep);
|
||
use POSIX qw(floor);
|
||
|
||
my $start = time();
|
||
|
||
sub lcg_r { return (($_[0] * 1664525 + 1013904223) & 0x7fffffff); }
|
||
|
||
sub is_prime_p {
|
||
my $n = shift; return 0 if $n < 2; return 1 if $n == 2;
|
||
return 0 if $n % 2 == 0;
|
||
my $i = 3; while ($i * $i <= $n) { return 0 if $n % $i == 0; $i += 2; } return 1;
|
||
}
|
||
|
||
sub sieve_p {
|
||
my $lim = shift;
|
||
my @s = (1) x ($lim + 1); $s[0] = $s[1] = 0;
|
||
for (my $i = 2; $i * $i <= $lim; $i++) {
|
||
if ($s[$i]) { for (my $j = $i*$i; $j <= $lim; $j += $i) { $s[$j] = 0; } }
|
||
}
|
||
return grep { $s[$_] } 2..$lim;
|
||
}
|
||
|
||
sub fib_p {
|
||
my $n = shift; return $n if $n <= 1;
|
||
my ($a, $b) = (0, 1);
|
||
for (my $i = 2; $i <= $n; $i++) { ($a, $b) = ($b, $a + $b); }
|
||
return $b;
|
||
}
|
||
|
||
sub mat_mul_p {
|
||
my ($A, $B, $n) = @_;
|
||
my @C = map { [(0) x $n] } 0..$n-1;
|
||
for my $i (0..$n-1) { for my $k (0..$n-1) { for my $j (0..$n-1) {
|
||
$C[$i][$j] += $A->[$i][$k] * $B->[$k][$j];
|
||
}}}
|
||
return @C;
|
||
}
|
||
|
||
sub make_mat_p {
|
||
my ($n, $seed) = @_;
|
||
return map { my $i = $_; [ map { (($i*$n+$_+$seed)%17)*0.1+1.0 } 0..$n-1 ] } 0..$n-1;
|
||
}
|
||
|
||
sub djb2_p {
|
||
my $str = shift; my $h = 5381;
|
||
for my $c (split //, $str) { $h = (($h<<5)+$h+ord($c)) & 0x7fffffff; }
|
||
return $h;
|
||
}
|
||
|
||
sub selection_sort_p {
|
||
my @a = @_; my $n = scalar @a;
|
||
for my $i (0..$n-2) {
|
||
my $min = $i;
|
||
for my $j ($i+1..$n-1) { $min = $j if $a[$j] < $a[$min]; }
|
||
@a[$i, $min] = @a[$min, $i] if $min != $i;
|
||
}
|
||
return @a;
|
||
}
|
||
|
||
sub poly_eval_p {
|
||
my ($coeffs, $x) = @_; my ($r, $p) = (0.0, 1.0);
|
||
for my $c (@$coeffs) { $r += $c * $p; $p *= $x; }
|
||
return $r;
|
||
}
|
||
|
||
sub collatz_p {
|
||
my $n = shift; my $steps = 0;
|
||
while ($n != 1) { $n = ($n % 2 == 0) ? $n/2 : 3*$n+1; $steps++; }
|
||
return $steps;
|
||
}
|
||
|
||
# Random delay 300ms-1500ms
|
||
my $seed = int(time() * 1000) & 0xffff;
|
||
my $delay_us = (300 + lcg_r($seed) % 1200) * 1000;
|
||
usleep($delay_us);
|
||
|
||
# Phase 1: Sieve
|
||
my @primes = sieve_p(2000);
|
||
my $prime_sum = 0; $prime_sum += $_ for @primes;
|
||
usleep(50000 + lcg_r(scalar @primes) % 200000);
|
||
|
||
# Phase 2: Fibonacci
|
||
my %fibs = map { $_ => fib_p($_) } grep { $_ % 5 == 0 } 20..50;
|
||
usleep(30000 + lcg_r(scalar keys %fibs) % 150000);
|
||
|
||
# Phase 3: Matrix 15x15
|
||
my @A = make_mat_p(15, 6);
|
||
my @B = make_mat_p(15, 11);
|
||
my @C = mat_mul_p(\@A, \@B, 15);
|
||
my $mat_sum = 0.0;
|
||
for my $row (@C) { $mat_sum += $_ for @$row; }
|
||
usleep(20000 + lcg_r(int($mat_sum) & 0xffff) % 100000);
|
||
|
||
# Phase 4: Selection sort 250 elements
|
||
my $s2 = 55; my @arr;
|
||
for (1..250) { $s2 = lcg_r($s2); push @arr, $s2 % 10000; }
|
||
my @sorted = selection_sort_p(@arr);
|
||
usleep(10000 + lcg_r($sorted[0]) % 80000);
|
||
|
||
# Phase 5: Polynomial
|
||
my @coeffs = (1, -3, 2, 5, -1, 4, -2, 1, 3, -1, 2, 1, -3, 2, 5, -1);
|
||
my $poly_max = -1e18;
|
||
for (my $x = -5.0; $x <= 5.0; $x += 0.5) {
|
||
my $v = poly_eval_p(\@coeffs, $x); $poly_max = $v if $v > $poly_max;
|
||
}
|
||
usleep(10000 + lcg_r(scalar @primes) % 60000);
|
||
|
||
# Phase 6: Hash chain
|
||
my $h = djb2_p("bench-perl-start");
|
||
my @chain = ($h);
|
||
for (1..500) { $h = djb2_p("$h"); push @chain, $h; }
|
||
|
||
# Phase 7: Collatz
|
||
my $cmax = 0;
|
||
for my $n (1..200) { my $s = collatz_p($n); $cmax = $s if $s > $cmax; }
|
||
usleep(10000 + lcg_r($chain[-1] & 0xffff) % 50000);
|
||
|
||
my $elapsed_ms = int((time() - $start) * 1000);
|
||
|
||
return sprintf('{"language":"perl","delay_ms":%d,"elapsed_ms":%d,"prime_count":%d,"prime_sum":%d,"fib45":%d,"mat_sum":%.4f,"sort_ok":%s,"poly_max":%.4f,"hash_final":%d,"collatz_max":%d}',
|
||
int($delay_us/1000), $elapsed_ms, scalar @primes, $prime_sum, $fibs{45},
|
||
$mat_sum, ($sorted[0] <= $sorted[-1] ? "true" : "false"),
|
||
$poly_max, $chain[-1], $cmax);
|
||
}
|
||
"""
|
||
|
||
|
||
# ── Python ────────────────────────────────────────────────────────────────────
|
||
PYTHON_CODE = r"""import time
|
||
import math
|
||
import random
|
||
|
||
def sieve(limit):
|
||
s = [True] * (limit + 1); s[0] = s[1] = False
|
||
i = 2
|
||
while i * i <= limit:
|
||
if s[i]:
|
||
j = i * i
|
||
while j <= limit: s[j] = False; j += i
|
||
i += 1
|
||
return [i for i in range(2, limit+1) if s[i]]
|
||
|
||
def fib(n):
|
||
if n <= 1: return n
|
||
a, b = 0, 1
|
||
for _ in range(n - 1): a, b = b, a + b
|
||
return b
|
||
|
||
def mat_mul(A, B, n):
|
||
C = [[0.0]*n for _ in range(n)]
|
||
for i in range(n):
|
||
for k in range(n):
|
||
for j in range(n):
|
||
C[i][j] += A[i][k] * B[k][j]
|
||
return C
|
||
|
||
def make_matrix(n, seed):
|
||
return [[(((i*n+j+seed)%17)*0.1+1.0) for j in range(n)] for i in range(n)]
|
||
|
||
def shell_sort(arr):
|
||
a = arr[:]
|
||
gap = len(a) // 2
|
||
while gap > 0:
|
||
for i in range(gap, len(a)):
|
||
tmp = a[i]; j = i
|
||
while j >= gap and a[j-gap] > tmp: a[j] = a[j-gap]; j -= gap
|
||
a[j] = tmp
|
||
gap //= 2
|
||
return a
|
||
|
||
def poly_eval(coeffs, x):
|
||
result, power = 0.0, 1.0
|
||
for c in coeffs: result += c * power; power *= x
|
||
return result
|
||
|
||
def djb2(s):
|
||
h = 5381
|
||
for c in s: h = ((h << 5) + h + ord(c)) & 0x7fffffff
|
||
return h
|
||
|
||
def collatz(n):
|
||
steps = 0
|
||
while n != 1: n = n // 2 if n % 2 == 0 else 3 * n + 1; steps += 1
|
||
return steps
|
||
|
||
def lcg(s): return ((s * 1664525 + 1013904223) & 0x7fffffff)
|
||
|
||
def main():
|
||
start = time.time()
|
||
|
||
# Random delay 250ms-1500ms
|
||
seed = int(start * 1000) & 0xffff
|
||
delay_ms = 250 + lcg(seed) % 1250
|
||
time.sleep(delay_ms / 1000.0)
|
||
|
||
# Phase 1: Sieve primes up to 2000
|
||
primes = sieve(2000)
|
||
prime_sum = sum(primes)
|
||
time.sleep(0.05 + (lcg(len(primes)) % 200) / 1000.0)
|
||
|
||
# Phase 2: Fibonacci batch
|
||
fibs = {n: fib(n) for n in range(20, 51, 5)}
|
||
time.sleep(0.03 + (lcg(len(fibs) * 7) % 150) / 1000.0)
|
||
|
||
# Phase 3: Matrix 20x20
|
||
A = make_matrix(20, 2)
|
||
B = make_matrix(20, 6)
|
||
C = mat_mul(A, B, 20)
|
||
mat_sum = sum(v for row in C for v in row)
|
||
time.sleep(0.02 + (lcg(int(mat_sum) & 0xffff) % 100) / 1000.0)
|
||
|
||
# Phase 4: Shell sort 500 elements
|
||
s2 = 33
|
||
arr = []
|
||
for _ in range(500): s2 = lcg(s2); arr.append(s2 % 10000)
|
||
sorted_arr = shell_sort(arr)
|
||
time.sleep(0.01 + (lcg(sorted_arr[0]) % 80) / 1000.0)
|
||
|
||
# Phase 5: Polynomial evaluation
|
||
coeffs = [1, -3, 2, 5, -1, 4, -2, 1, 3, -1, 2, 1, -3, 2, 5, -1]
|
||
poly_vals = [poly_eval(coeffs, x * 0.25) for x in range(-20, 21)]
|
||
poly_max = max(poly_vals)
|
||
time.sleep(0.01 + (lcg(len(primes)) % 60) / 1000.0)
|
||
|
||
# Phase 6: Hash chain 500 iterations
|
||
h = djb2("bench-python-start")
|
||
chain = [h]
|
||
for _ in range(500): h = djb2(str(h)); chain.append(h)
|
||
|
||
# Phase 7: Collatz max steps for 1..300
|
||
collatz_max = max(collatz(n) for n in range(1, 301))
|
||
time.sleep(0.01 + (lcg(chain[-1] & 0xffff) % 50) / 1000.0)
|
||
|
||
# Phase 8: Sum of squares (1..200)
|
||
sq_sum = sum(i * i for i in range(1, 201))
|
||
|
||
# Phase 9: GCD / LCM chain on primes
|
||
def gcd(a, b):
|
||
while b: a, b = b, a % b
|
||
return a
|
||
gcds = [gcd(primes[i], primes[i+1]) for i in range(min(50, len(primes)-1))]
|
||
|
||
elapsed_ms = round((time.time() - start) * 1000)
|
||
|
||
return {
|
||
"language": "python",
|
||
"delay_ms": delay_ms,
|
||
"elapsed_ms": elapsed_ms,
|
||
"prime_count": len(primes),
|
||
"prime_sum": prime_sum,
|
||
"fib45": fibs[45],
|
||
"mat_sum": round(mat_sum, 4),
|
||
"sort_ok": sorted_arr[0] <= sorted_arr[-1],
|
||
"poly_max": round(poly_max, 4),
|
||
"hash_final": chain[-1],
|
||
"collatz_max": collatz_max,
|
||
"sq_sum": sq_sum,
|
||
"gcd_sum": sum(gcds),
|
||
}
|
||
"""
|
||
|
||
functions = [
|
||
("bench-node", "nodejs", NODE_CODE),
|
||
("bench-php", "php", PHP_CODE),
|
||
("bench-ruby", "ruby", RUBY_CODE),
|
||
("bench-perl", "perl", PERL_CODE),
|
||
("bench-go", "go", GO_CODE),
|
||
("bench-python", "python", PYTHON_CODE),
|
||
]
|
||
|
||
print("=== Удаляем старые bench-функции ===")
|
||
for name, _, _ in functions:
|
||
result = subprocess.run(
|
||
["curl", "-s", "-X", "DELETE", f"{BASE}/functions/{name}",
|
||
"-H", f"X-Test-Sub: {SUB}"],
|
||
capture_output=True, text=True
|
||
)
|
||
print(f" DELETE {name}: {result.stdout.strip()[:80]}")
|
||
|
||
print("\n=== Создаём тяжёлые bench-функции (~10KB) ===")
|
||
for name, lang, code in functions:
|
||
payload = json.dumps({"name": name, "language": lang, "code": code, "ttl": "2h"})
|
||
size_kb = len(code) / 1024
|
||
result = subprocess.run(
|
||
["curl", "-s", "-X", "POST", f"{BASE}/functions",
|
||
"-H", f"X-Test-Sub: {SUB}", "-H", "Content-Type: application/json",
|
||
"-d", payload],
|
||
capture_output=True, text=True
|
||
)
|
||
try:
|
||
resp = json.loads(result.stdout)
|
||
route = resp.get("route", "?")
|
||
print(f" {name} ({size_kb:.1f}KB): {route}")
|
||
except Exception as e:
|
||
print(f" {name}: PARSE ERROR {result.stdout[:150]}")
|