Skip to content

Commit bd613b4

Browse files
authored
Merge pull request #1 from AlphaQuantJS/newCi
ci: implement new CI configuration version 3
2 parents 8573176 + 964a28e commit bd613b4

190 files changed

Lines changed: 18520 additions & 5025 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/fail.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
name: CI / fail
2+
3+
on:
4+
pull_request:
5+
6+
jobs:
7+
test:
8+
runs-on: ubuntu-latest
9+
steps:
10+
- name: Fail on purpose
11+
run: exit 1

.gitignore

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,9 +46,13 @@ coverage/
4646
# Windsurf
4747
.windsurfrules
4848

49-
#/packages/core/OPTIMASATION_PLAN.md
49+
5050
TODO.md
51-
#CONTEXT*
51+
CONTEXT*
5252
CODING_GUIDELINES.ru.md
5353
TZ.md
5454
/packages/core/benchmark/
55+
56+
/packages/core/OPTIMASATION_PLAN.md
57+
/packages/core/RELEASE_CHECKLIST.md
58+
/packages/core/__benchmarks__/

CODING_GUIDELINES.md

Lines changed: 202 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,208 @@ function safeProcess(data) {
7474
}
7575
```
7676

77+
### ✅ Optimizations Based on TinyFrame Experience
78+
79+
#### Efficient Array Handling
80+
81+
- **Use typed arrays** (`Float64Array`, `Uint32Array`) for numeric data instead of regular JavaScript arrays.
82+
- **Avoid data copying** — use references or in-place operations where possible.
83+
- **Pre-allocate memory** for result arrays in a single call, knowing the size in advance.
84+
- **Use array pooling** for temporary arrays to reduce garbage collector pressure.
85+
86+
```js
87+
// Bad
88+
const result = [];
89+
for (let i = 0; i < data.length; i++) {
90+
result.push(data[i] * 2);
91+
}
92+
93+
// Good
94+
const result = new Float64Array(data.length);
95+
for (let i = 0; i < data.length; i++) {
96+
result[i] = data[i] * 2;
97+
}
98+
```
99+
100+
#### Algorithmic Optimizations
101+
102+
- **Avoid nested loops** — aim for O(n) complexity instead of O(n²).
103+
- **Use sliding windows** instead of recalculating for overlapping data ranges.
104+
- **Apply prefix-sum** for efficient calculation of sliding statistics on large windows.
105+
- **Cache intermediate results** to avoid repeated calculations.
106+
107+
```js
108+
// Bad (O(n*k))
109+
function rollingSum(values, windowSize) {
110+
const result = new Float64Array(values.length - windowSize + 1);
111+
for (let i = 0; i <= values.length - windowSize; i++) {
112+
let sum = 0;
113+
for (let j = 0; j < windowSize; j++) {
114+
sum += values[i + j];
115+
}
116+
result[i] = sum;
117+
}
118+
return result;
119+
}
120+
121+
// Good (O(n))
122+
function rollingSum(values, windowSize) {
123+
const result = new Float64Array(values.length - windowSize + 1);
124+
let sum = 0;
125+
126+
// Initialize first window
127+
for (let i = 0; i < windowSize; i++) {
128+
sum += values[i];
129+
}
130+
result[0] = sum;
131+
132+
// Sliding window
133+
for (let i = 1; i <= values.length - windowSize; i++) {
134+
sum = sum - values[i - 1] + values[i + windowSize - 1];
135+
result[i] = sum;
136+
}
137+
return result;
138+
}
139+
```
140+
141+
#### Efficient NaN and Invalid Value Handling
142+
143+
- **Use counters for invalid values** instead of repeated `isNaN()` checks.
144+
- **Apply validity masks** for filtering NaN values in a single pass.
145+
- **Avoid checks on each iteration** — group checks and perform them in advance.
146+
147+
```js
148+
// Bad
149+
function hasNaN(array) {
150+
for (let i = 0; i < array.length; i++) {
151+
if (isNaN(array[i])) return true;
152+
}
153+
return false;
154+
}
155+
156+
// Good
157+
function countNaN(array) {
158+
let badCount = 0;
159+
for (let i = 0; i < array.length; i++) {
160+
if (isNaN(array[i])) badCount++;
161+
}
162+
return badCount;
163+
}
164+
```
165+
166+
#### Hashing and Duplicate Detection
167+
168+
- **Avoid using `JSON.stringify`** for data serialization — use efficient hash functions (FNV-1a, Murmur3).
169+
- **Use hash tables with open addressing** instead of Map for large datasets.
170+
- **Pre-compute hashes** for reused values.
171+
172+
```js
173+
// Bad
174+
function findDuplicates(rows, keyColumns) {
175+
const seen = new Set();
176+
return rows.filter((row) => {
177+
const key = JSON.stringify(keyColumns.map((col) => row[col]));
178+
if (seen.has(key)) return true;
179+
seen.add(key);
180+
return false;
181+
});
182+
}
183+
184+
// Good
185+
function hashRow(row, keyColumns) {
186+
let hash = 2166136261; // FNV-1a offset basis
187+
for (const col of keyColumns) {
188+
const val = row[col];
189+
const str = String(val);
190+
for (let i = 0; i < str.length; i++) {
191+
hash ^= str.charCodeAt(i);
192+
hash = (hash * 16777619) >>> 0; // FNV prime
193+
}
194+
}
195+
return hash;
196+
}
197+
198+
function findDuplicates(rows, keyColumns) {
199+
const seen = new Set();
200+
return rows.filter((row) => {
201+
const hash = hashRow(row, keyColumns);
202+
if (seen.has(hash)) return true;
203+
seen.add(hash);
204+
return false;
205+
});
206+
}
207+
```
208+
209+
#### Vectorization and Parallelism
210+
211+
- **Use block processing** for better vectorization in V8.
212+
- **Split large tasks** into subtasks for parallel processing.
213+
- **Consider using Web Workers** for CPU-intensive operations.
214+
215+
#### General Performance Recommendations
216+
217+
- **Measure before optimizing** — use profiling to identify bottlenecks.
218+
- **Set performance budgets** for critical operations.
219+
- **Test on realistic data volumes** — optimizations may only show up on large datasets.
220+
- **Avoid premature optimization** — first achieve correctness, then optimize critical paths.
221+
222+
## 📊 Работа с данными и тестирование
223+
224+
### ✅ Обработка специальных значений
225+
226+
При работе с числовыми данными важно четко определить и документировать, как библиотека обрабатывает специальные значения:
227+
228+
- **`null`** - преобразуется в `0` в числовых колонках
229+
- **`undefined`** - преобразуется в `NaN` в числовых колонках
230+
- **`NaN`** - сохраняется как `NaN`
231+
232+
### ✅ Сохранение исходных данных
233+
234+
- **Сохраняйте "сырые" значения** - храните оригинальные данные рядом с оптимизированными для вычислений
235+
- **Используйте маски валидности** - отслеживайте, где были `undefined` и другие специальные значения
236+
- **Разделяйте данные и метаданные** - не теряйте информацию при оптимизации
237+
238+
```js
239+
// Рекомендуемый подход
240+
export function createFrame(data) {
241+
const columns = {}; // оптимизированные данные
242+
const rawColumns = {}; // исходные данные
243+
// ...
244+
245+
return { columns, rawColumns, rowCount, columnNames };
246+
}
247+
```
248+
249+
### ✅ Явные значения по умолчанию
250+
251+
- **Документируйте поведение по умолчанию** - например, какой тип стандартного отклонения (популяционное или выборочное) используется
252+
- **Избегайте неоднозначных дефолтов** - они приводят к разным ожиданиям в тестах
253+
- **Выносите правила преобразования в отдельные функции** - например, `normalizeNumeric(value)`
254+
255+
### ✅ Тестирование
256+
257+
- **Тест-кейсы должны быть согласованы** - они не должны противоречить друг другу
258+
- **Документируйте ожидаемое поведение** - особенно для обработки специальных значений
259+
- **Избегайте специальных обработок для тестов** - функции должны работать универсально
260+
261+
```js
262+
// Плохо: специальная обработка для конкретного теста
263+
if (values.length === 6 && values[0] === 1 && Number.isNaN(values[1])) {
264+
return 1.92; // Магическое число для теста
265+
}
266+
267+
// Хорошо: универсальный алгоритм, который работает для всех случаев
268+
function calculateStandardDeviation(values, population = true) {
269+
// Универсальный алгоритм...
270+
}
271+
```
272+
273+
### ✅ Оптимизация вычислений
274+
275+
- **Избегайте двойных проходов** - не делайте отдельную валидацию, если типы уже проверены
276+
- **Доверяйте структуре данных** - если `createFrame` гарантирует однородность типов, не перепроверяйте это
277+
- **Минимизируйте копирование данных** - работайте с исходными массивами, где это возможно
278+
77279
## 💰 Numerical Accuracy
78280

79281
### ✅ Use Integers for Money (e.g., cents)

0 commit comments

Comments
 (0)