Skip to content

Commit

Permalink
perf: 优化 customTree 包含大量 values 生成结构时性能 (#2469)
Browse files Browse the repository at this point in the history
  • Loading branch information
wjgogogo authored Dec 12, 2023
1 parent 6e3683b commit 56677c5
Show file tree
Hide file tree
Showing 6 changed files with 84 additions and 51 deletions.
3 changes: 3 additions & 0 deletions packages/s2-core/__tests__/unit/facet/pivot-facet-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,9 @@ jest.mock('@/data-set/pivot-data-set', () => {
indexesData,
sortedDimensionValues,
moreThanOneValue: jest.fn(),
transformIndexesData: actualPivotDataSet.prototype.transformIndexesData,
getExistValuesByDataItem:
actualPivotDataSet.prototype.getExistValuesByDataItem,
getFieldFormatter: actualDataSet.prototype.getFieldFormatter,
getFieldMeta: (field: string, meta: ViewMeta) => find(meta, { field }),
getFieldName: actualPivotDataSet.prototype.getFieldName,
Expand Down
6 changes: 5 additions & 1 deletion packages/s2-core/__tests__/unit/facet/util.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { assembleDataCfg } from 'tests/util';
import { transformIndexesData } from '@/utils/dataset/pivot-data-set';
import {
getExistValues,
transformIndexesData,
} from '@/utils/dataset/pivot-data-set';

/**
* 获取 Mock 数据
Expand All @@ -20,5 +23,6 @@ export function getMockPivotMeta() {
rowPivotMeta: rawRowPivotMeta,
colPivotMeta: rawColPivotMeta,
valueInCols: true,
getExistValuesByDataItem: getExistValues,
});
}
57 changes: 30 additions & 27 deletions packages/s2-core/src/data-set/pivot-data-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,11 +44,13 @@ import {
flattenIndexesData,
getDataPath,
getDataPathPrefix,
getExistValues,
getFlattenDimensionValues,
getSatisfiedPivotMetaValues,
isMultiValue,
transformDimensionsValues,
transformIndexesData,
type TransformResult,
} from '../utils/dataset/pivot-data-set';
import { DataHandler } from '../utils/dataset/proxy-handler';
import { calcActionByType } from '../utils/number-calculate';
Expand All @@ -75,6 +77,10 @@ export class PivotDataSet extends BaseDataSet {
// sorted dimension values
public sortedDimensionValues: SortedDimensionValues;

getExistValuesByDataItem(data: DataType, values: string[]) {
return getExistValues(data, values);
}

/**
* When data related config changed, we need
* 1、re-process config
Expand All @@ -84,26 +90,41 @@ export class PivotDataSet extends BaseDataSet {
*/
public setDataCfg(dataCfg: S2DataConfig) {
super.setDataCfg(dataCfg);
const { rows } = this.fields;
this.sortedDimensionValues = {};
this.rowPivotMeta = new Map();
this.colPivotMeta = new Map();
this.transformIndexesData(this.originData.concat(this.totalData), rows);
this.handleDimensionValuesSort();
}

public transformIndexesData(
data: DataType[],
rows: string[],
): TransformResult {
const { columns, values, valueInCols } = this.fields;

let result: TransformResult;
DebuggerUtil.getInstance().debugCallback(DEBUG_TRANSFORM_DATA, () => {
const { rows, columns, values, valueInCols } = this.fields;
const { indexesData } = transformIndexesData({
result = transformIndexesData({
rows,
columns: columns as string[],
values,
valueInCols,
data: this.originData.concat(this.totalData),
data,
indexesData: this.indexesData,
sortedDimensionValues: this.sortedDimensionValues,
rowPivotMeta: this.rowPivotMeta,
colPivotMeta: this.colPivotMeta,
getExistValuesByDataItem: this.getExistValuesByDataItem,
});
this.indexesData = indexesData;
this.indexesData = result.indexesData;
this.rowPivotMeta = result.rowPivotMeta;
this.colPivotMeta = result.colPivotMeta;
this.sortedDimensionValues = result.sortedDimensionValues;
});

this.handleDimensionValuesSort();
return result;
}

/**
Expand All @@ -117,7 +138,6 @@ export class PivotDataSet extends BaseDataSet {
drillDownData: DataType[],
rowNode: Node,
) {
const { columns, values, valueInCols } = this.fields;
const currentRowFields = Node.getFieldPath(rowNode, true);
const nextRowFields = [...currentRowFields, extraRowField];
const store = this.spreadsheet.store;
Expand All @@ -134,27 +154,10 @@ export class PivotDataSet extends BaseDataSet {
}

// 3、转换数据
const {
paths: drillDownDataPaths,
indexesData,
rowPivotMeta,
colPivotMeta,
sortedDimensionValues,
} = transformIndexesData({
rows: nextRowFields,
columns: columns as string[],
values,
valueInCols,
data: drillDownData,
indexesData: this.indexesData,
sortedDimensionValues: this.sortedDimensionValues,
rowPivotMeta: this.rowPivotMeta,
colPivotMeta: this.colPivotMeta,
});
this.indexesData = indexesData;
this.rowPivotMeta = rowPivotMeta;
this.colPivotMeta = colPivotMeta;
this.sortedDimensionValues = sortedDimensionValues;
const { paths: drillDownDataPaths } = this.transformIndexesData(
drillDownData,
nextRowFields,
);

// 4、record data paths by nodeId
// set new drill-down data path
Expand Down
1 change: 0 additions & 1 deletion packages/s2-core/src/utils/data-set-operate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ export const filterOutDetail = (values: string[] = []) => {
(v) => v !== TOTAL_VALUE && v !== EMPTY_EXTRA_FIELD_PLACEHOLDER,
);
};

export const customFlattenDeep = (
data: Record<any, any>[] | Record<any, any>,
) => {
Expand Down
55 changes: 33 additions & 22 deletions packages/s2-core/src/utils/dataset/pivot-data-set.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function isMultiValue(pathValue: string | number) {
export function transformDimensionsValues(
record: DataType = {},
dimensions: string[] = [],
placeholder: string = TOTAL_VALUE,
placeholder = TOTAL_VALUE,
): string[] {
return dimensions.reduce((res: string[], dimension: string) => {
const value = record[dimension];
Expand All @@ -70,10 +70,19 @@ export function transformDimensionsValues(
}, []);
}

export function getExistValues(data: DataType, values: string[]) {
const result = values.filter((v) => v in data);
if (isEmpty(result)) {
result.push(EMPTY_EXTRA_FIELD_PLACEHOLDER);
}

return result;
}

export function transformDimensionsValuesWithExtraFields(
record: DataType = {},
dimensions: string[] = [],
values: string[] = [],
values?: string[],
) {
const result = [];

Expand All @@ -93,25 +102,13 @@ export function transformDimensionsValuesWithExtraFields(
}, []);
}

if (isEmpty(values)) {
result.push(transform(record, dimensions));
} else {
if (values) {
values.forEach((value) => {
if (value in record) {
result.push(transform(record, dimensions, value));
}
result.push(transform(record, dimensions, value));
});
} else {
result.push(transform(record, dimensions));
}

/**
* result 为空时,就是命中了数组置于当前维度,但是当前的数据中并没有包含任何 values 配置,给一个默认维度用于占位
* 主要用于处理趋势分析表中只存在日期列头,不存在任何值的情况:
* ref: @see packages/s2-react/__tests__/unit/components/sheets/strategy-sheet/index-spec.tsx
*/
if (isEmpty(result)) {
result.push(transform(record, dimensions, EMPTY_EXTRA_FIELD_PLACEHOLDER));
}

return result;
}

Expand Down Expand Up @@ -277,12 +274,21 @@ interface Param {
sortedDimensionValues: SortedDimensionValues;
rowPivotMeta?: PivotMeta;
colPivotMeta?: PivotMeta;
getExistValuesByDataItem?: (data: DataType, values: string[]) => string[];
}

export interface TransformResult {
paths: (string | number)[];
indexesData: Record<string, DataType[][] | DataType[]>;
rowPivotMeta: PivotMeta;
colPivotMeta: PivotMeta;
sortedDimensionValues: SortedDimensionValues;
}

/**
* 转换原始数据为二维数组数据
*/
export function transformIndexesData(params: Param) {
export function transformIndexesData(params: Param): TransformResult {
const {
rows,
columns,
Expand All @@ -293,6 +299,7 @@ export function transformIndexesData(params: Param) {
sortedDimensionValues,
rowPivotMeta,
colPivotMeta,
getExistValuesByDataItem,
} = params;
const paths = [];

Expand All @@ -319,21 +326,25 @@ export function transformIndexesData(params: Param) {

const prefix = getDataPathPrefix(rows, columns as string[]);

data.forEach((item) => {
data.forEach((item: DataType) => {
// 空数据没有意义,直接跳过
if (!item || isEmpty(item)) {
return;
}

const existValues = getExistValuesByDataItem
? getExistValuesByDataItem(item, values)
: getExistValues(item, values);

const multiRowDimensionValues = transformDimensionsValuesWithExtraFields(
item,
rows,
valueInCols ? undefined : values,
valueInCols ? null : existValues,
);
const multiColDimensionValues = transformDimensionsValuesWithExtraFields(
item,
columns,
valueInCols ? values : undefined,
valueInCols ? existValues : null,
);

for (const rowDimensionValues of multiRowDimensionValues) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,24 @@
import {
CustomTreePivotDataSet,
EMPTY_EXTRA_FIELD_PLACEHOLDER,
i18n,
type DataType,
type Meta,
type S2DataConfig,
} from '@antv/s2';
import { isEmpty, isObject, keys } from 'lodash';

export class StrategyDataSet extends CustomTreePivotDataSet {
getExistValuesByDataItem(data: DataType, values: string[]) {
const result = keys(data).filter((key) => isObject(data[key]));

if (isEmpty(result)) {
result.push(EMPTY_EXTRA_FIELD_PLACEHOLDER);
}

return result;
}

processDataCfg(dataCfg: S2DataConfig): S2DataConfig {
const { meta } = dataCfg;
const updatedDataCfg = super.processDataCfg(dataCfg);
Expand Down

0 comments on commit 56677c5

Please sign in to comment.