Skip to content

Commit 844d130

Browse files
committed
Add Bench to promo
1 parent 9aa311a commit 844d130

4 files changed

Lines changed: 306 additions & 5 deletions

File tree

.vitepress/theme/HomeBench.vue

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
<script setup lang="ts">
2+
import { ref } from 'vue'
3+
4+
withDefaults(defineProps<{
5+
codeTab?: string
6+
resultTab?: string
7+
}>(), {
8+
codeTab: 'Code',
9+
resultTab: 'Result',
10+
})
11+
12+
const activeTab = ref<'code' | 'result'>('code')
13+
</script>
14+
15+
<template>
16+
<div class="bench-showcase">
17+
<div class="bench-description">
18+
<slot name="description" />
19+
</div>
20+
21+
<div class="bench-tabs-wrap">
22+
<div class="bench-tabs">
23+
<button
24+
:class="{ active: activeTab === 'code' }"
25+
@click="activeTab = 'code'"
26+
>{{ codeTab }}</button>
27+
<button
28+
:class="{ active: activeTab === 'result' }"
29+
@click="activeTab = 'result'"
30+
>{{ resultTab }}</button>
31+
</div>
32+
</div>
33+
34+
<div v-show="activeTab === 'code'" class="bench-code-panel">
35+
<div class="bench-code-split">
36+
<div class="bench-code-block">
37+
<slot name="left" />
38+
</div>
39+
<div class="bench-code-block">
40+
<slot name="right" />
41+
</div>
42+
</div>
43+
</div>
44+
45+
<div v-show="activeTab === 'result'" class="bench-result-panel">
46+
<slot name="result" />
47+
</div>
48+
</div>
49+
</template>
50+
51+
<style scoped>
52+
.bench-showcase {
53+
margin: 0 auto;
54+
}
55+
56+
/* Description */
57+
.bench-description {
58+
text-align: center;
59+
max-width: 640px;
60+
margin: 0 auto 28px;
61+
}
62+
63+
.bench-description :deep(p) {
64+
font-size: 17px;
65+
line-height: 1.7;
66+
color: var(--vp-c-text-2);
67+
margin: 0;
68+
}
69+
70+
.bench-description :deep(code) {
71+
background: var(--vp-c-bg-soft);
72+
padding: 2px 6px;
73+
border-radius: 4px;
74+
font-size: 15px;
75+
color: var(--vp-c-brand-1);
76+
}
77+
78+
/* Tabs — segmented control */
79+
.bench-tabs-wrap {
80+
display: flex;
81+
justify-content: center;
82+
margin-bottom: 20px;
83+
}
84+
85+
.bench-tabs {
86+
display: inline-flex;
87+
border: 1px solid var(--vp-c-divider);
88+
border-radius: 8px;
89+
overflow: hidden;
90+
}
91+
92+
.bench-tabs button {
93+
padding: 8px 24px;
94+
border: none;
95+
background: transparent;
96+
color: var(--vp-c-text-2);
97+
font-size: 14px;
98+
font-family: var(--vp-font-family-base);
99+
cursor: pointer;
100+
transition: all 0.2s ease;
101+
}
102+
103+
.bench-tabs button + button {
104+
border-left: 1px solid var(--vp-c-divider);
105+
}
106+
107+
.bench-tabs button:hover {
108+
color: var(--vp-c-text-1);
109+
background: var(--vp-c-bg-soft);
110+
}
111+
112+
.bench-tabs button.active {
113+
background: var(--vp-c-brand-soft);
114+
color: var(--vp-c-brand-1);
115+
}
116+
117+
/* Two separate code windows */
118+
.bench-code-split {
119+
display: flex;
120+
gap: 16px;
121+
}
122+
123+
.bench-code-block {
124+
flex: 1;
125+
min-width: 0;
126+
}
127+
128+
.bench-code-block :deep(div[class*="language-"]) {
129+
margin: 0 !important;
130+
}
131+
132+
.bench-code-block :deep(span.lang),
133+
.bench-code-block :deep(button.copy) {
134+
display: none;
135+
}
136+
137+
div.bench-code-panel {
138+
min-height: 255px;
139+
}
140+
141+
/* Result — centered, minimal */
142+
143+
.bench-result-panel {
144+
min-height: 255px;
145+
padding-bottom: 20px;
146+
display: flex;
147+
justify-content: center;
148+
}
149+
150+
.bench-result-panel :deep(div[class*="language-"]) {
151+
margin: 0 !important;
152+
box-shadow: none !important;
153+
border: 1px solid var(--vp-c-divider);
154+
}
155+
156+
.bench-result-panel :deep(span.lang),
157+
.bench-result-panel :deep(button.copy) {
158+
display: none;
159+
}
160+
161+
/* Responsive */
162+
@media (max-width: 768px) {
163+
.bench-code-split {
164+
flex-direction: column;
165+
gap: 12px;
166+
}
167+
}
168+
</style>

.vitepress/theme/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import DefaultTheme from 'vitepress/theme'
55
import BlogSponsor from './BlogSponsor.vue'
66
import GitHubStars from './GitHubStars.vue'
77
import CodeTabs from './CodeTabs.vue'
8+
import HomeBench from './HomeBench.vue'
89
import JetBrainsPluginButton from './JetBrainsPluginButton.vue'
910
import JetBrainsPlugin from './JetBrainsPlugin.vue'
1011
import BlogPosts from './BlogPosts.vue'
@@ -82,6 +83,7 @@ export default {
8283
}),
8384
enhanceApp({ app, router }) {
8485
app.component('CodeTabs', CodeTabs)
86+
app.component('HomeBench', HomeBench)
8587
app.component('JetBrainsPluginButton', JetBrainsPluginButton)
8688
app.component('JetBrainsPlugin', JetBrainsPlugin)
8789
app.component('BlogPosts', BlogPosts)

index.md

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ const declareTabs = [
7373
{ name: 'Convention', slot: 'declare-convention', icon: 'testo-class' },
7474
{ name: 'Inline', slot: 'declare-inline', icon: 'class' },
7575
]
76+
7677
</script>
7778

7879
<div style="max-width: 700px; margin: 48px auto 0;">
@@ -95,8 +96,8 @@ Want to support the project? [Star the repo](https://github.com/php-testo/testo)
9596

9697
Assertion functions are split into semantic groups:
9798

98-
- `Assert::` facade — assertions, executed immediately
99-
- `Expect::` facade — expectations, deferred until test completion
99+
- <class>\Testo\Assert</class> facade — assertions, executed immediately
100+
- <class>\Testo\Expect</class> facade — expectations, deferred until test completion
100101

101102
Pipe syntax with type grouping keeps code concise and type-safe.
102103

@@ -300,6 +301,71 @@ Full-featured workflow: run and re-run from gutter icons, navigation between tes
300301
</div>
301302
</div>
302303

304+
<div class="home-feature">
305+
306+
## Benchmarks with a Single Attribute
307+
308+
<HomeBench code-tab="Bench.php" result-tab="Result">
309+
310+
<template #description>
311+
312+
Add the <attr>\Testo\Bench</attr> attribute to a method, and Testo will show which implementation is faster. With statistics, outlier filtering, and stability recommendations.
313+
314+
</template>
315+
316+
<template #left>
317+
318+
```php
319+
// Baseline method with the #[Bench] attribute
320+
#[Bench(
321+
callables: [
322+
'sumInCycle' => [self::class, 'sumInCycle'],
323+
],
324+
arguments: [1, 5_000],
325+
)]
326+
public static function sumInArray(int $a, int $b): int
327+
{
328+
return \array_sum(\range($a, $b));
329+
}
330+
```
331+
332+
</template>
333+
334+
<template #right>
335+
336+
```php
337+
// Alternative implementation
338+
public static function sumInCycle(int $a, int $b): int
339+
{
340+
$result = 0;
341+
for ($i = $a; $i <= $b; ++$i) {
342+
$result += $i;
343+
}
344+
return $result;
345+
}
346+
```
347+
348+
</template>
349+
350+
<template #result>
351+
352+
```
353+
Results for sumInArray:
354+
+--------------------------+------------------------------------------------+---------+
355+
| BENCHMARK SETUP | TIME RESULTS | SUMMARY |
356+
| Name | Iters | Calls | Mean | Median | RStDev | Place |
357+
+----------+-------+-------+-------------------+-------------------+--------+---------+
358+
| current | 10 | 1000 | 11.65µs | 11.58µs | ±1.55% | 1st |
359+
| in cycle | 10 | 1000 | 43.80µs (+275.8%) | 44.17µs (+281.5%) | ±1.67% | 2nd |
360+
+----------+-------+-------+-------------------+-------------------+--------+---------+
361+
```
362+
363+
</template>
364+
365+
</HomeBench>
366+
367+
</div>
368+
303369
<div class="sponsors-section">
304370
<h2 class="sponsors-title">Sponsored by</h2>
305371
<div class="sponsors-grid">

ru/index.md

Lines changed: 68 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ const declareTabs = [
7272
{ name: 'Конвенция', slot: 'declare-convention', icon: 'testo-class' },
7373
{ name: 'Inline', slot: 'declare-inline', icon: 'class' },
7474
]
75+
7576
</script>
7677

7778
<div style="max-width: 700px; margin: 48px auto 0;">
@@ -94,8 +95,8 @@ Testo находится в фазе активной разработки и п
9495

9596
Функции проверок разбиты на семантические группы:
9697

97-
- Фасад `Assert::` — утверждения, выполняются сразу
98-
- Фасад `Expect::` — ожидания, откладываются до завершения теста
98+
- Фасад <class>\Testo\Assert</class> — утверждения, выполняются сразу
99+
- Фасад <class>\Testo\Expect</class> — ожидания, откладываются до завершения теста
99100

100101
Пайповый синтаксис с группировкой по типу делает код лаконичным и типобезопасным.
101102

@@ -186,7 +187,7 @@ public function testInvalidInput(): void
186187
Пишите тесты так, как удобно вам.
187188

188189
- Тестами могут быть классы, функции или даже атрибуты прямо в продуктовом коде (Inline Tests).
189-
- Классам не нужно наследование от базового тестового класса. Код остаётся чистым.
190+
- Классы не нужно наследовать от базового тестового класса. Код остаётся чистым.
190191
- Обнаружение тестов по соглашениям об именовании или по явным атрибутам.
191192

192193
</div>
@@ -299,6 +300,70 @@ final class Calculator
299300
</div>
300301
</div>
301302

303+
<div class="home-feature">
304+
305+
## Бенчмарки одним атрибутом
306+
307+
<HomeBench code-tab="Bench.php" result-tab="Результат">
308+
309+
<template #description>
310+
311+
Добавьте атрибут <attr>\Testo\Bench</attr> к методу, и Testo покажет, какая из реализаций работает быстрее. Со статистикой, фильтрацией выбросов и рекомендациями по стабильности.
312+
313+
</template>
314+
315+
<template #left>
316+
317+
```php
318+
// Эталонный метод с атрибутом #[Bench]
319+
#[Bench(
320+
callables: ['sumInCycle' => [self::class, 'sumInCycle']],
321+
arguments: [1, 5_000],
322+
)]
323+
public static function sumInArray(int $a, int $b): int
324+
{
325+
return \array_sum(\range($a, $b));
326+
}
327+
```
328+
329+
</template>
330+
331+
<template #right>
332+
333+
```php
334+
// Альтернативная реализация
335+
public static function sumInCycle(int $a, int $b): int
336+
{
337+
$result = 0;
338+
for ($i = $a; $i <= $b; ++$i) {
339+
$result += $i;
340+
}
341+
return $result;
342+
}
343+
```
344+
345+
</template>
346+
347+
<template #result>
348+
349+
```
350+
Results for sumInArray:
351+
+--------------------------+------------------------------------------------+---------+
352+
| BENCHMARK SETUP | TIME RESULTS | SUMMARY |
353+
| Name | Iters | Calls | Mean | Median | RStDev | Place |
354+
+----------+-------+-------+-------------------+-------------------+--------+---------+
355+
| current | 10 | 1000 | 11.65µs | 11.58µs | ±1.55% | 1st |
356+
| in cycle | 10 | 1000 | 43.80µs (+275.8%) | 44.17µs (+281.5%) | ±1.67% | 2nd |
357+
+----------+-------+-------+-------------------+-------------------+--------+---------+
358+
359+
```
360+
361+
</template>
362+
363+
</HomeBench>
364+
365+
</div>
366+
302367
<div class="sponsors-section">
303368
<h2 class="sponsors-title">Спонсоры</h2>
304369
<div class="sponsors-grid">

0 commit comments

Comments
 (0)