add browser benchmarks

This commit is contained in:
Km.Van
2025-09-05 08:59:31 +08:00
parent c19449b3a0
commit e9836a16e5
23 changed files with 455 additions and 171 deletions

View File

@@ -15,6 +15,10 @@
"https://raw.githubusercontent.com/kmvan/x-prober/master/benchmarks.json",
"https://api.inn-studio.com/download/?id=xprober-benchmarks"
],
"BROWSER_BENCHMARKS_URLS": [
"https://raw.githubusercontent.com/kmvan/x-prober/master/browser-benchmarks.json",
"https://api.inn-studio.com/download/?id=xprober-browser-benchmarks"
],
"APP_CONFIG_URL_DEV": "http://localhost:8000/AppConfig.json",
"APP_TEMPERATURE_SENSOR_URL": "http://127.0.0.1",
"APP_TEMPERATURE_SENSOR_PORTS": [

13
browser-benchmarks.json Normal file
View File

@@ -0,0 +1,13 @@
[
{
"name": "i7-11370H/Virtualbox/Linux/Chrome139",
"ua": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
"date": "2025-09-04",
"version": "9.0.9",
"detail": {
"js": 2460,
"dom": 1073,
"canvas": 345
}
}
]

View File

@@ -15,6 +15,10 @@
"https://raw.githubusercontent.com/kmvan/x-prober/master/benchmarks.json",
"https://api.inn-studio.com/download/?id=xprober-benchmarks"
],
"BROWSER_BENCHMARKS_URLS": [
"https://raw.githubusercontent.com/kmvan/x-prober/master/browser-benchmarks.json",
"https://api.inn-studio.com/download/?id=xprober-browser-benchmarks"
],
"APP_CONFIG_URL_DEV": "http://localhost:8000/AppConfig.json",
"APP_TEMPERATURE_SENSOR_URL": "http://127.0.0.1",
"APP_TEMPERATURE_SENSOR_PORTS": [

Binary file not shown.

View File

@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: X-Prober\n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2025-08-16 22:48+0800\n"
"PO-Revision-Date: 2025-09-05 08:46+0800\n"
"Last-Translator: Km.Van <kmvan.com@gmail.com>\n"
"Language-Team: Km.Van <inn-studio.com>\n"
"Language: ja\n"
@@ -18,6 +18,35 @@ msgstr ""
msgid "Failed to fetch data. Please try again later."
msgstr "データの取得に失敗しました。しばらくしてからもう一度お試しください。"
msgid "Touch to copy marks"
msgstr "タップでスコアをコピー"
msgid "Can not fetch marks data from GitHub."
msgstr "GitHubからスコアデータを取得できません。"
msgid "Browser Benchmark"
msgstr "ブラウザベンチマーク"
msgid ""
"Different versions cannot be compared, and different time clients have "
"different loads, just for reference."
msgstr ""
"異なるバージョンを比較することはできません。また、異なる時間のクライアントに"
"は異なる負荷がかかりますが、これはあくまで参考値です。"
msgid ""
"Running the benchmark may freeze the browser interface for a few seconds. Do "
"you want to continue?"
msgstr ""
"ベンチマークを実行すると、ブラウザインターフェースが数秒間フリーズする場合が"
"あります。続行しますか?"
msgid "Benchmark my browser"
msgstr "ブラウザのベンチマーク"
msgid "Browser bench"
msgstr "ブラウザベンチ"
msgid "Dark"
msgstr "ダークモード"
@@ -215,11 +244,8 @@ msgstr "{{seconds}}秒お待ちください"
msgid "Benchmark my server"
msgstr "ベンチマーク実行"
msgid "Benchmark"
msgstr "性能測定"
msgid "Touch to copy marks"
msgstr "タップでスコアをコピー"
msgid "Server bench"
msgstr "サーバーベンチ"
msgid "Read"
msgstr "読取"
@@ -236,9 +262,6 @@ msgstr "ダウンロード速度テスト"
msgid "Visit the official website"
msgstr "公式サイトへ"
msgid "Can not fetch marks data from GitHub."
msgstr "GitHubからスコアデータを取得できません。"
msgid "{{days}}d {{hours}}h {{mins}}min {{secs}}s"
msgstr "{{days}}日 {{hours}}時間 {{mins}}分 {{secs}}秒"
@@ -391,6 +414,9 @@ msgstr "非対応"
msgid "Can not fetch IP"
msgstr "IP取得失敗"
#~ msgid "Benchmark"
#~ msgstr "性能測定"
#~ msgid "Ext"
#~ msgstr "拡張"

View File

@@ -18,6 +18,27 @@ msgstr ""
msgid "Failed to fetch data. Please try again later."
msgstr ""
msgid "Touch to copy marks"
msgstr ""
msgid "Can not fetch marks data from GitHub."
msgstr ""
msgid "Browser Benchmark"
msgstr ""
msgid "Different versions cannot be compared, and different time clients have different loads, just for reference."
msgstr ""
msgid "Running the benchmark may freeze the browser interface for a few seconds. Do you want to continue?"
msgstr ""
msgid "Benchmark my browser"
msgstr ""
msgid "Browser bench"
msgstr ""
msgid "Dark"
msgstr ""
@@ -210,10 +231,7 @@ msgstr ""
msgid "Benchmark my server"
msgstr ""
msgid "Benchmark"
msgstr ""
msgid "Touch to copy marks"
msgid "Server bench"
msgstr ""
msgid "Read"
@@ -231,9 +249,6 @@ msgstr ""
msgid "Visit the official website"
msgstr ""
msgid "Can not fetch marks data from GitHub."
msgstr ""
msgid "{{days}}d {{hours}}h {{mins}}min {{secs}}s"
msgstr ""

Binary file not shown.

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: X-Prober\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2025-08-16 22:48+0800\n"
"PO-Revision-Date: 2025-09-04 22:51+0800\n"
"Last-Translator: Km.Van <kmvan.com@gmail.com>\n"
"Language-Team: kmvan <kmvan.com@gmail.com>\n"
"Language: zh_CN\n"
@@ -20,6 +20,31 @@ msgstr ""
msgid "Failed to fetch data. Please try again later."
msgstr "无法获取数据,请稍后重试。"
msgid "Touch to copy marks"
msgstr "点击复制分数"
msgid "Can not fetch marks data from GitHub."
msgstr "无法从GitHub获取测试数据。"
msgid "Browser Benchmark"
msgstr "浏览器性能测试"
msgid ""
"Different versions cannot be compared, and different time clients have "
"different loads, just for reference."
msgstr "不同版本无法直接比较,不同时间浏览器负载各异,结果仅供参考。"
msgid ""
"Running the benchmark may freeze the browser interface for a few seconds. Do "
"you want to continue?"
msgstr "执行性能测试可能会冻结浏览器界面数秒,是否继续?"
msgid "Benchmark my browser"
msgstr "测试浏览器性能"
msgid "Browser bench"
msgstr "浏览器性能"
msgid "Dark"
msgstr "深色模式"
@@ -215,11 +240,8 @@ msgstr "请等待 {{seconds}} 秒"
msgid "Benchmark my server"
msgstr "测试服务器性能"
msgid "Benchmark"
msgstr "性能测试"
msgid "Touch to copy marks"
msgstr "点击复制分数"
msgid "Server bench"
msgstr "服务器性能"
msgid "Read"
msgstr "读取"
@@ -236,9 +258,6 @@ msgstr "下载速度测试"
msgid "Visit the official website"
msgstr "访问官网"
msgid "Can not fetch marks data from GitHub."
msgstr "无法从GitHub获取测试数据。"
msgid "{{days}}d {{hours}}h {{mins}}min {{secs}}s"
msgstr "{{days}} 天 {{hours}} 时 {{mins}} 分 {{secs}} 秒"
@@ -387,6 +406,9 @@ msgstr "不支持"
msgid "Can not fetch IP"
msgstr "无法获取 IP"
#~ msgid "Benchmark"
#~ msgstr "性能测试"
#~ msgid "Ext"
#~ msgstr "扩展"

Binary file not shown.

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: X-Prober\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2025-08-16 22:48+0800\n"
"PO-Revision-Date: 2025-09-04 22:53+0800\n"
"Last-Translator: Km.Van <kmvan.com@gmail.com>\n"
"Language-Team: Km.Van <inn-studio.com>\n"
"Language: zh_HK\n"
@@ -20,6 +20,31 @@ msgstr ""
msgid "Failed to fetch data. Please try again later."
msgstr "無法獲取數據,請稍後重試。"
msgid "Touch to copy marks"
msgstr "點擊複製跑分數據"
msgid "Can not fetch marks data from GitHub."
msgstr "無法從 GitHub 取得跑分數據。"
msgid "Browser Benchmark"
msgstr "瀏覽器跑分測試"
msgid ""
"Different versions cannot be compared, and different time clients have "
"different loads, just for reference."
msgstr "不同版本無法直接比較,且不同時間瀏覽器負載各異,結果僅供參考。"
msgid ""
"Running the benchmark may freeze the browser interface for a few seconds. Do "
"you want to continue?"
msgstr "執行基準測試可能會導致瀏覽器介面凍結幾秒鐘。是否繼續?"
msgid "Benchmark my browser"
msgstr "測試我的瀏覽器"
msgid "Browser bench"
msgstr "瀏覽器跑分"
msgid "Dark"
msgstr "暗黑模式"
@@ -215,11 +240,8 @@ msgstr "請等候 {{seconds}} 秒"
msgid "Benchmark my server"
msgstr "測試我的伺服器"
msgid "Benchmark"
msgstr "跑分測試"
msgid "Touch to copy marks"
msgstr "點擊複製跑分數據"
msgid "Server bench"
msgstr "伺服器跑分"
msgid "Read"
msgstr "讀取"
@@ -236,9 +258,6 @@ msgstr "下載速度測試"
msgid "Visit the official website"
msgstr "瀏覽官方網站"
msgid "Can not fetch marks data from GitHub."
msgstr "無法從 GitHub 取得跑分數據。"
msgid "{{days}}d {{hours}}h {{mins}}min {{secs}}s"
msgstr "{{days}}天 {{hours}}小時 {{mins}}分鐘 {{secs}}秒"
@@ -386,6 +405,9 @@ msgstr "不支援"
msgid "Can not fetch IP"
msgstr "無法取得 IP"
#~ msgid "Benchmark"
#~ msgstr "跑分測試"
#~ msgid "Ext"
#~ msgstr "擴充"

Binary file not shown.

View File

@@ -3,7 +3,7 @@ msgstr ""
"Project-Id-Version: X-Prober\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: \n"
"PO-Revision-Date: 2025-08-16 22:48+0800\n"
"PO-Revision-Date: 2025-09-05 08:47+0800\n"
"Last-Translator: Km.Van <kmvan.com@gmail.com>\n"
"Language-Team: Km.Van <inn-studio.com>\n"
"Language: zh_TW\n"
@@ -22,6 +22,31 @@ msgstr ""
msgid "Failed to fetch data. Please try again later."
msgstr "無法獲取資料,請稍後重試。"
msgid "Touch to copy marks"
msgstr "點擊複製跑分數據"
msgid "Can not fetch marks data from GitHub."
msgstr "無法從 GitHub 取得跑分資料。"
msgid "Browser Benchmark"
msgstr "客戶端跑分測試"
msgid ""
"Different versions cannot be compared, and different time clients have "
"different loads, just for reference."
msgstr "不同版本無法比較,不同時間客戶端負載不同,僅供參考。"
msgid ""
"Running the benchmark may freeze the browser interface for a few seconds. Do "
"you want to continue?"
msgstr "執行基準測試可能會導致瀏覽器介面凍結幾秒鐘。是否繼續?"
msgid "Benchmark my browser"
msgstr "測試我的瀏覽器"
msgid "Browser bench"
msgstr "瀏覽器跑分"
msgid "Dark"
msgstr "深色模式"
@@ -217,11 +242,8 @@ msgstr "請等候 {{seconds}} 秒"
msgid "Benchmark my server"
msgstr "測試我的伺服器"
msgid "Benchmark"
msgstr "跑分測試"
msgid "Touch to copy marks"
msgstr "點擊複製跑分數據"
msgid "Server bench"
msgstr "伺服器跑分"
msgid "Read"
msgstr "讀取"
@@ -238,9 +260,6 @@ msgstr "下載速度測試"
msgid "Visit the official website"
msgstr "瀏覽官方網站"
msgid "Can not fetch marks data from GitHub."
msgstr "無法從 GitHub 取得跑分資料。"
msgid "{{days}}d {{hours}}h {{mins}}min {{secs}}s"
msgstr "{{days}}天 {{hours}}小時 {{mins}}分鐘 {{secs}}秒"
@@ -388,6 +407,9 @@ msgstr "不支援"
msgid "Can not fetch IP"
msgstr "無法取得 IP"
#~ msgid "Benchmark"
#~ msgstr "跑分測試"
#~ msgid "Ext"
#~ msgstr "擴充"

View File

@@ -32,6 +32,7 @@ final class Action
'ServerBenchmark\\ServerBenchmarkServersAction',
'Location\\LocationIpv4Action',
'Nodes\\NodesAction',
'BrowserBenchmark\\BrowserBenchmarkBrowsersAction',
] as $fn) {
$class = "\\InnStudio\\Prober\\Components\\{$fn}";
(new $class())->render($action);

View File

@@ -0,0 +1,61 @@
<?php
namespace InnStudio\Prober\Components\BrowserBenchmark;
use InnStudio\Prober\Components\Bootstrap\Bootstrap;
use InnStudio\Prober\Components\Config\ConfigApi;
use InnStudio\Prober\Components\Rest\RestResponse;
use InnStudio\Prober\Components\Rest\StatusCode;
final class BrowserBenchmarkBrowsersAction
{
public function render($action)
{
if ('browserBenchmarks' !== $action) {
return;
}
$reponse = new RestResponse();
if (\defined('XPROBER_IS_DEV') && XPROBER_IS_DEV) {
$reponse
->setData($this->getDevItems())
->end();
}
foreach (ConfigApi::$config['BROWSER_BENCHMARKS_URLS'] as $url) {
$curl = curl_init($url);
curl_setopt($curl, \CURLOPT_RETURNTRANSFER, true);
$data = (string) curl_exec($curl);
curl_close($curl);
if ( ! $data) {
continue;
}
$json = json_decode($data, true);
if ( ! $json) {
continue;
}
$reponse
->setData($json)
->end();
}
$reponse
->setStatus(StatusCode::NO_CONTENT)
->end();
}
private function getDevItems()
{
$path = Bootstrap::$dir . '/browser-benchmarks.json';
if ( ! file_exists($path)) {
return [];
}
$data = file_get_contents($path);
if ( ! $data) {
return [];
}
$items = json_decode($data, true);
if ( ! $items) {
return [];
}
return $items;
}
}

View File

@@ -3,39 +3,27 @@ import type { FC, MouseEvent, ReactNode } from 'react';
import { gettext } from '@/Components/Language/index.ts';
import { template } from '@/Components/Utils/components/template.ts';
import { UiRuby } from '@/Components/ui/ruby/index.tsx';
import styles from './browsers-item.module.scss';
import { BrowserBenchmarkMarksMeter } from './marks-meter.tsx';
import styles from './server-item.module.scss';
import type { BrowserBenchmarkMarksProps } from './typings.ts';
const BrowserBenchmarkResult: FC<{
sunSpider: number;
hash: number;
object: number;
cssAnimation: number;
gc: number;
js: number;
dom: number;
canvas: number;
webgl: number;
date?: string;
}> = ({ sunSpider, hash, object, cssAnimation, gc, canvas, webgl, date }) => {
const total = sunSpider + hash + object + cssAnimation + gc + canvas + webgl;
const sunSpiderString = sunSpider.toLocaleString();
const hashString = hash.toLocaleString();
const objectString = object.toLocaleString();
const cssAnimationString = cssAnimation.toLocaleString();
const gcString = gc.toLocaleString();
}> = ({ js, dom, canvas, date }) => {
const total = js + dom + canvas;
const jsString = js.toLocaleString();
const domString = dom.toLocaleString();
const canvasString = canvas.toLocaleString();
const webglString = webgl.toLocaleString();
const totalString = total.toLocaleString();
const totalText = template(
'{{sunSpider}} (SunSpider) + {{hash}} (Hash) + {{object}} (Object) + {{cssAnimation}} (CSS Animation) + {{gc}} (GC) + {{canvas}} (Canvas) + {{webgl}} (WebGL) = {{total}}',
'{{js}} (JS) + {{dom}} (DOM) + {{canvas}} (Canvas) = {{total}}',
{
sunSpider: sunSpiderString,
hash: hashString,
object: objectString,
cssAnimation: cssAnimationString,
gc: gcString,
js: jsString,
dom: domString,
canvas: canvasString,
webgl: webglString,
total: totalString,
}
);
@@ -52,47 +40,33 @@ const BrowserBenchmarkResult: FC<{
title={gettext('Touch to copy marks')}
type="button"
>
<UiRuby rt="SunSpider" ruby={sunSpiderString} />
<UiRuby rt="JS" ruby={jsString} />
{sign}
<UiRuby rt="Hash" ruby={hashString} />
{sign}
<UiRuby rt="Object" ruby={objectString} />
{sign}
<UiRuby rt="CSS Animation" ruby={cssAnimationString} />
{sign}
<UiRuby rt="GC" ruby={gcString} />
<UiRuby rt="DOM" ruby={domString} />
{sign}
<UiRuby rt="Canvas" ruby={canvasString} />
{sign}
<UiRuby rt="WebGL" ruby={webglString} />
{sign}
<span className={styles.sign}>=</span>
<UiRuby isResult rt={date || ''} ruby={totalString} />
</button>
);
};
export const BrowserBenchmarkItem: FC<{
ua: string;
header: ReactNode;
marks: BrowserBenchmarkMarksProps;
maxMarks: number;
date: string;
}> = ({ header, marks, maxMarks, date }) => {
const { sunSpider, hash, object, cssAnimation, gc, canvas, webgl } = marks;
}> = ({ ua, header, marks, maxMarks, date }) => {
const { js, dom, canvas } = marks;
return (
<div className={styles.main}>
<div className={styles.header}>{header}</div>
<BrowserBenchmarkResult
canvas={canvas}
cssAnimation={cssAnimation}
date={date}
gc={gc}
hash={hash}
object={object}
sunSpider={sunSpider}
webgl={webgl}
/>
<div className={styles.header} title={ua}>
{header}
</div>
<BrowserBenchmarkResult canvas={canvas} date={date} dom={dom} js={js} />
<BrowserBenchmarkMarksMeter
total={sunSpider + hash + object + cssAnimation + gc + canvas + webgl}
total={js + dom + canvas}
totalMarks={maxMarks}
/>
</div>

View File

@@ -19,7 +19,7 @@ export const BrowserBenchmarkBrowsers: FC = observer(() => {
const fetchData = async () => {
setLoading(true);
const { data, status } =
await serverFetch<BrowserBenchmarkProps[]>('benchmarkBrowsers');
await serverFetch<BrowserBenchmarkProps[]>('browserBenchmarks');
setLoading(false);
if (!data?.length || status !== OK) {
setError(true);
@@ -49,26 +49,15 @@ export const BrowserBenchmarkBrowsers: FC = observer(() => {
if (!detail) {
return null;
}
const {
sunSpider = 0,
hash = 0,
object = 0,
cssAnimation = 0,
gc = 0,
canvas = 0,
webgl = 0,
} = detail;
const { js = 0, dom = 0, canvas = 0 } = detail;
return (
<BrowserBenchmarkItem
date={date}
header={
<>
{name} {version}
</>
}
header={`${name}/v${version}`}
key={name}
marks={{ sunSpider, hash, object, cssAnimation, gc, canvas, webgl }}
marks={{ js, dom, canvas }}
maxMarks={maxMarks}
ua={ua}
/>
);
});

View File

@@ -2,14 +2,16 @@ import { type FC, memo } from 'react';
import { gettext } from '@/Components/Language/index.ts';
import { ModuleItem } from '@/Components/Module/components/item.tsx';
import { UiDescription } from '@/Components/ui/description/index.tsx';
import { BrowserBenchmarkBrowsers } from './browsers.tsx';
import { BrowserBenchmarkConstants } from './constants.ts';
import { BrowserBenchmarkMyBrowser } from './my-browser.tsx';
export const BrowserBenchmark: FC = memo(() => {
return (
<ModuleItem
id={BrowserBenchmarkConstants.id}
title={gettext('Browser Benchmark')}
>
{/* <UiDescription
<UiDescription
items={[
{
id: 'browserBenchmarkTos',
@@ -18,15 +20,8 @@ export const BrowserBenchmark: FC = memo(() => {
),
},
]}
/> */}
<UiDescription
items={[
{
id: 'dev',
text: '(Under development)',
},
]}
/>
<BrowserBenchmarkBrowsers />
</ModuleItem>
);
});

View File

@@ -2,72 +2,58 @@ import { observer } from 'mobx-react-lite';
import { type MouseEvent, useCallback, useState } from 'react';
import { Button } from '@/Components/Button/components/index.tsx';
import { ButtonStatus } from '@/Components/Button/components/typings.ts';
import { serverFetch } from '@/Components/Fetch/server-fetch.ts';
import { gettext } from '@/Components/Language/index.ts';
import { OK, TOO_MANY_REQUESTS } from '@/Components/Rest/http-status.ts';
import { ToastStore } from '@/Components/Toast/components/store.ts';
import { template } from '@/Components/Utils/components/template.ts';
import { BrowserBenchmarkItem } from './browsers-item.tsx';
import { BrowserBenchmarkStore } from './store.ts';
import { BrowserBenchmarkTests } from './tests.ts';
import type { BrowserBenchmarkMarksProps } from './typings.ts';
export const BrowserBenchmarkMyBrowser = observer(() => {
const [benchmarking, setBenchmarking] = useState(false);
const { setMaxMarks, maxMarks } = BrowserBenchmarkStore;
const [marks, setMarks] = useState<BrowserBenchmarkMarksProps>({
sunSpider: 0,
hash: 0,
object: 0,
cssAnimation: 0,
gc: 0,
js: 0,
dom: 0,
canvas: 0,
webgl: 0,
});
const handleBenchmarking = useCallback(
async (e: MouseEvent<HTMLButtonElement>): Promise<void> => {
(e: MouseEvent<HTMLButtonElement>) => {
e.preventDefault();
e.stopPropagation();
if (benchmarking) {
return;
}
// setLinkText(gettext('Testing, please wait...'))
if (
!window.confirm(
gettext(
'Running the benchmark may freeze the browser interface for a few seconds. Do you want to continue?'
)
)
) {
return;
}
setBenchmarking(true);
const { data, status } = await serverFetch<{
marks: BrowserBenchmarkMarksProps;
seconds: number;
}>('benchmarkPerformance');
const results = {
js: BrowserBenchmarkTests.runJs(),
dom: BrowserBenchmarkTests.runDom(),
canvas: BrowserBenchmarkTests.runCanvas(),
};
setBenchmarking(false);
// const { marks, seconds = 0 } = data || {}
if (status === OK) {
if (data?.marks) {
setMarks(data.marks);
const total = Object.values(data.marks).reduce((a, b) => a + b, 0);
if (total > maxMarks) {
setMaxMarks(total);
}
return;
}
ToastStore.open(gettext('Network error, please try again later.'));
return;
setMarks(results);
const total = Object.values(results).reduce((a, b) => a + b, 0);
if (total > maxMarks) {
setMaxMarks(total);
}
if (data?.seconds && status === TOO_MANY_REQUESTS) {
ToastStore.open(
template(gettext('Please wait {{seconds}}s'), {
seconds: data.seconds,
})
);
return;
}
ToastStore.open(gettext('Network error, please try again later.'));
},
[benchmarking, maxMarks, setMaxMarks]
);
const date = new Date();
const header = (
<Button
disabled={benchmarking}
onClick={handleBenchmarking}
status={benchmarking ? ButtonStatus.Loading : ButtonStatus.Pointer}
>
{gettext('Benchmark my server')}
{gettext('Benchmark my browser')}
</Button>
);
return (

View File

@@ -0,0 +1,112 @@
class Main {
getRndint = (min: number, max: number) => {
return Math.floor(Math.random() * (max - min + 1)) + min;
};
runJs = (): number => {
const totalMs = 1000;
let times = 0;
const startTime = performance.now();
for (;;) {
for (let i = 0; i < 10_000; i++) {
(Math.sqrt(i) * Math.sin(i)) / Math.tan(i + 1);
}
const arr = new Array(1000).fill(0).map((_, i) => i);
arr.sort(() => Math.random() - 0.5);
arr.sort((a, b) => a - b);
times++;
if (performance.now() - startTime > totalMs) {
break;
}
}
return times;
};
runDom = (): number => {
const totalMs = 1000;
let times = 0;
const screenWidth = window.innerWidth;
const screenHeight = window.innerHeight;
const startTime = performance.now();
const container = document.createElement('div');
container.style.cssText = `
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
`;
document.body.appendChild(container);
for (;;) {
for (let i = 0; i < 100; i++) {
const div = document.createElement('div');
div.className = 'benchmark-dom';
div.style.position = 'fixed';
div.style.left = '0px';
div.style.top = '0px';
div.style.width = `${this.getRndint(50, screenWidth)}px`;
div.style.height = `${this.getRndint(50, screenHeight)}px`;
div.style.border = '1px solid green';
container.appendChild(div);
}
// query
const eles = document.querySelectorAll(
'.benchmark-dom'
) as NodeListOf<HTMLDivElement>;
for (const ele of Array.from(eles)) {
ele.style.borderColor = 'red';
}
while (container.firstChild) {
container.removeChild(container.firstChild);
}
times++;
if (performance.now() - startTime > totalMs) {
break;
}
}
document.body.removeChild(container);
return times;
};
runCanvas = () => {
const totalMs = 1000;
let times = 0;
const canvas = document.createElement('canvas');
const screenWidth = window.innerWidth;
const screenHeight = window.innerHeight;
canvas.width = screenWidth;
canvas.height = screenHeight;
canvas.style.position = 'fixed';
canvas.style.top = '0px';
canvas.style.left = '0px';
document.body.appendChild(canvas);
const ctx = canvas.getContext('2d') as CanvasRenderingContext2D;
const startTime = performance.now();
for (;;) {
for (let i = 0; i < 100; i++) {
ctx.clearRect(0, 0, canvas.width, canvas.height);
const centerX = canvas.width / 2;
const centerY = canvas.height / 2;
const halfSize = canvas.width / 2;
ctx.lineWidth = this.getRndint(1, 5);
ctx.strokeStyle = 'red';
ctx.lineCap = 'round';
ctx.beginPath();
ctx.moveTo(centerX - halfSize, centerY - halfSize);
ctx.lineTo(centerX + halfSize, centerY + halfSize);
ctx.rotate(this.getRndint(0, 360));
ctx.stroke();
ctx.beginPath();
ctx.moveTo(centerX + halfSize, centerY - halfSize);
ctx.lineTo(centerX - halfSize, centerY + halfSize);
ctx.rotate(this.getRndint(0, 360));
ctx.stroke();
}
times++;
if (performance.now() - startTime > totalMs) {
break;
}
}
ctx.clearRect(0, 0, canvas.width, canvas.height);
document.body.removeChild(canvas);
return times;
};
}
export const BrowserBenchmarkTests = new Main();

View File

@@ -1,11 +1,7 @@
export interface BrowserBenchmarkMarksProps {
sunSpider: number;
hash: number;
object: number;
cssAnimation: number;
gc: number;
js: number;
dom: number;
canvas: number;
webgl: number;
}
export interface BrowserBenchmarkProps {
id: string;

View File

@@ -27,6 +27,11 @@ class ConfigApi
0 => 'https://raw.githubusercontent.com/kmvan/x-prober/master/benchmarks.json',
1 => 'https://api.inn-studio.com/download/?id=xprober-benchmarks',
),
'BROWSER_BENCHMARKS_URLS' =>
array (
0 => 'https://raw.githubusercontent.com/kmvan/x-prober/master/browser-benchmarks.json',
1 => 'https://api.inn-studio.com/download/?id=xprober-browser-benchmarks',
),
'APP_CONFIG_URL_DEV' => 'http://localhost:8000/AppConfig.json',
'APP_TEMPERATURE_SENSOR_URL' => 'http://127.0.0.1',
'APP_TEMPERATURE_SENSOR_PORTS' =>

View File

@@ -1,10 +1,10 @@
{
"": {
"ja": "Project-Id-Version: X-Prober\nPOT-Creation-Date: \nPO-Revision-Date: 2025-08-16 22:48+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: Km.Van <inn-studio.com>\nLanguage: ja\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=1; plural=0;\nX-Generator: Poedit 3.4.2\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Poedit-KeywordsList: gettext\n",
"zh": "Project-Id-Version: X-Prober\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: \nPO-Revision-Date: 2025-08-16 22:48+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: kmvan <kmvan.com@gmail.com>\nLanguage: zh_CN\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\nX-Poedit-KeywordsList: gettext\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Generator: Poedit 3.4.2\nX-Poedit-Flags-xgettext: --add-comments\n",
"zhcn": "Project-Id-Version: X-Prober\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: \nPO-Revision-Date: 2025-08-16 22:48+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: kmvan <kmvan.com@gmail.com>\nLanguage: zh_CN\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\nX-Poedit-KeywordsList: gettext\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Generator: Poedit 3.4.2\nX-Poedit-Flags-xgettext: --add-comments\n",
"zhhk": "Project-Id-Version: X-Prober\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: \nPO-Revision-Date: 2025-08-16 22:48+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: Km.Van <inn-studio.com>\nLanguage: zh_HK\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\nX-Poedit-KeywordsList: gettext\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Generator: Poedit 3.4.2\nX-Poedit-Flags-xgettext: --add-comments\n",
"zhtw": "Project-Id-Version: X-Prober\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: \nPO-Revision-Date: 2025-08-16 22:48+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: Km.Van <inn-studio.com>\nLanguage: zh_TW\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\nX-Poedit-KeywordsList: gettext\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Generator: Poedit 3.4.2\nX-ZhConverter: 繁化姬 dict-b76338ce-r665 @ 2019/11/20 14:24:08 | https://zhconvert.org\nX-Poedit-Flags-xgettext: --add-comments\n"
"ja": "Project-Id-Version: X-Prober\nPOT-Creation-Date: \nPO-Revision-Date: 2025-09-05 08:46+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: Km.Van <inn-studio.com>\nLanguage: ja\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=1; plural=0;\nX-Generator: Poedit 3.4.2\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Poedit-KeywordsList: gettext\n",
"zh": "Project-Id-Version: X-Prober\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: \nPO-Revision-Date: 2025-09-04 22:51+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: kmvan <kmvan.com@gmail.com>\nLanguage: zh_CN\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\nX-Poedit-KeywordsList: gettext\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Generator: Poedit 3.4.2\nX-Poedit-Flags-xgettext: --add-comments\n",
"zhcn": "Project-Id-Version: X-Prober\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: \nPO-Revision-Date: 2025-09-04 22:51+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: kmvan <kmvan.com@gmail.com>\nLanguage: zh_CN\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\nX-Poedit-KeywordsList: gettext\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Generator: Poedit 3.4.2\nX-Poedit-Flags-xgettext: --add-comments\n",
"zhhk": "Project-Id-Version: X-Prober\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: \nPO-Revision-Date: 2025-09-04 22:53+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: Km.Van <inn-studio.com>\nLanguage: zh_HK\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\nX-Poedit-KeywordsList: gettext\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Generator: Poedit 3.4.2\nX-Poedit-Flags-xgettext: --add-comments\n",
"zhtw": "Project-Id-Version: X-Prober\nReport-Msgid-Bugs-To: \nPOT-Creation-Date: \nPO-Revision-Date: 2025-09-05 08:47+0800\nLast-Translator: Km.Van <kmvan.com@gmail.com>\nLanguage-Team: Km.Van <inn-studio.com>\nLanguage: zh_TW\nMIME-Version: 1.0\nContent-Type: text/plain; charset=UTF-8\nContent-Transfer-Encoding: 8bit\nPlural-Forms: nplurals=2; plural=n != 1;\nX-Poedit-KeywordsList: gettext\nX-Poedit-Basepath: .\nX-Poedit-SourceCharset: UTF-8\nX-Generator: Poedit 3.4.2\nX-ZhConverter: 繁化姬 dict-b76338ce-r665 @ 2019/11/20 14:24:08 | https://zhconvert.org\nX-Poedit-Flags-xgettext: --add-comments\n"
},
"{{days}}d {{hours}}h {{mins}}min {{secs}}s": {
"ja": "{{days}}日 {{hours}}時間 {{mins}}分 {{secs}}秒",
@@ -69,12 +69,12 @@
"zhhk": "❌ 更新錯誤,點此重試?",
"zhtw": "❌ 更新錯誤,點此重試?"
},
"Benchmark": {
"ja": "性能測定",
"zh": "性能测试",
"zhcn": "性能测试",
"zhhk": "跑分測試",
"zhtw": "跑分測試"
"Benchmark my browser": {
"ja": "ブラウザのベンチマーク",
"zh": "测试浏览器性能",
"zhcn": "测试浏览器性能",
"zhhk": "測試我的瀏覽器",
"zhtw": "測試我的瀏覽器"
},
"Benchmark my server": {
"ja": "ベンチマーク実行",
@@ -83,6 +83,20 @@
"zhhk": "測試我的伺服器",
"zhtw": "測試我的伺服器"
},
"Browser bench": {
"ja": "ブラウザベンチ",
"zh": "浏览器性能",
"zhcn": "浏览器性能",
"zhhk": "瀏覽器跑分",
"zhtw": "瀏覽器跑分"
},
"Browser Benchmark": {
"ja": "ブラウザベンチマーク",
"zh": "浏览器性能测试",
"zhcn": "浏览器性能测试",
"zhhk": "瀏覽器跑分測試",
"zhtw": "客戶端跑分測試"
},
"Browser UA": {
"ja": "ブラウザユーザーエージェント",
"zh": "浏览器 UA",
@@ -209,6 +223,13 @@
"zhhk": "詳細資料",
"zhtw": "詳細資料"
},
"Different versions cannot be compared, and different time clients have different loads, just for reference.": {
"ja": "異なるバージョンを比較することはできません。また、異なる時間のクライアントには異なる負荷がかかりますが、これはあくまで参考値です。",
"zh": "不同版本无法直接比较,不同时间浏览器负载各异,结果仅供参考。",
"zhcn": "不同版本无法直接比较,不同时间浏览器负载各异,结果仅供参考。",
"zhhk": "不同版本無法直接比較,且不同時間瀏覽器負載各異,結果僅供參考。",
"zhtw": "不同版本無法比較,不同時間客戶端負載不同,僅供參考。"
},
"Different versions cannot be compared, and different time servers have different loads, just for reference.": {
"ja": "異なるバージョン間の比較は不可。タイムサーバーの負荷状態により結果が変動します(参考値)",
"zh": "不同版本无法直接比较,不同时间服务器负载各异,结果仅供参考。",
@@ -601,6 +622,13 @@
"zhhk": "結果",
"zhtw": "結果"
},
"Running the benchmark may freeze the browser interface for a few seconds. Do you want to continue?": {
"ja": "ベンチマークを実行すると、ブラウザインターフェースが数秒間フリーズする場合があります。続行しますか?",
"zh": "执行性能测试可能会冻结浏览器界面数秒,是否继续?",
"zhcn": "执行性能测试可能会冻结浏览器界面数秒,是否继续?",
"zhhk": "執行基準測試可能會導致瀏覽器介面凍結幾秒鐘。是否繼續?",
"zhtw": "執行基準測試可能會導致瀏覽器介面凍結幾秒鐘。是否繼續?"
},
"SAPI interface": {
"ja": "SAPIインターフェース",
"zh": "SAPI 接口",
@@ -629,6 +657,13 @@
"zhhk": "伺服器 ⇄ 瀏覽器",
"zhtw": "伺服器 ⇄ 瀏覽器"
},
"Server bench": {
"ja": "サーバーベンチ",
"zh": "服务器性能",
"zhcn": "服务器性能",
"zhhk": "伺服器跑分",
"zhtw": "伺服器跑分"
},
"Server Benchmark": {
"ja": "サーバーベンチマーク",
"zh": "服务器性能测试",

View File

@@ -1,7 +1,9 @@
import type { WindowConfigProps, WindowProps } from './typings.ts';
export const WindowConfig = {
IS_DEV: Boolean((window as unknown as WindowProps).GLOBAL_CONFIG.IS_DEV),
IS_DEV: Boolean(
(window as unknown as WindowProps)?.GLOBAL_CONFIG?.IS_DEV ?? false
),
AUTHORIZATION: String(
(window as unknown as WindowProps).GLOBAL_CONFIG.AUTHORIZATION
(window as unknown as WindowProps)?.GLOBAL_CONFIG?.AUTHORIZATION ?? ''
),
} as const satisfies WindowConfigProps;