@fluidframework/matrix 2.0.0-internal.3.0.2 → 2.0.0-internal.3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. package/.eslintrc.js +20 -21
  2. package/.mocharc.js +2 -2
  3. package/README.md +21 -21
  4. package/api-extractor.json +2 -2
  5. package/bench/bsp-set-optimizations.md +5 -5
  6. package/bench/src/index.ts +38 -20
  7. package/bench/src/read/map.ts +16 -10
  8. package/bench/src/read/nativearray.ts +16 -10
  9. package/bench/src/read/test.ts +17 -19
  10. package/bench/src/read/tiled.ts +240 -181
  11. package/bench/src/util.ts +19 -18
  12. package/bench/tsconfig.json +8 -13
  13. package/dist/bspSet.d.ts.map +1 -1
  14. package/dist/bspSet.js.map +1 -1
  15. package/dist/handlecache.d.ts.map +1 -1
  16. package/dist/handlecache.js +1 -3
  17. package/dist/handlecache.js.map +1 -1
  18. package/dist/handletable.d.ts.map +1 -1
  19. package/dist/handletable.js +7 -3
  20. package/dist/handletable.js.map +1 -1
  21. package/dist/matrix.d.ts +1 -1
  22. package/dist/matrix.d.ts.map +1 -1
  23. package/dist/matrix.js +28 -19
  24. package/dist/matrix.js.map +1 -1
  25. package/dist/ops.d.ts.map +1 -1
  26. package/dist/ops.js.map +1 -1
  27. package/dist/packageVersion.d.ts +1 -1
  28. package/dist/packageVersion.js +1 -1
  29. package/dist/packageVersion.js.map +1 -1
  30. package/dist/permutationvector.d.ts.map +1 -1
  31. package/dist/permutationvector.js +15 -8
  32. package/dist/permutationvector.js.map +1 -1
  33. package/dist/productSet.d.ts.map +1 -1
  34. package/dist/productSet.js +6 -3
  35. package/dist/productSet.js.map +1 -1
  36. package/dist/range.d.ts.map +1 -1
  37. package/dist/range.js.map +1 -1
  38. package/dist/runtime.d.ts.map +1 -1
  39. package/dist/runtime.js.map +1 -1
  40. package/dist/serialization.d.ts.map +1 -1
  41. package/dist/serialization.js.map +1 -1
  42. package/dist/sparsearray2d.d.ts.map +1 -1
  43. package/dist/sparsearray2d.js +12 -12
  44. package/dist/sparsearray2d.js.map +1 -1
  45. package/dist/split.d.ts.map +1 -1
  46. package/dist/split.js +5 -3
  47. package/dist/split.js.map +1 -1
  48. package/dist/types.d.ts.map +1 -1
  49. package/dist/types.js.map +1 -1
  50. package/dist/undoprovider.d.ts.map +1 -1
  51. package/dist/undoprovider.js.map +1 -1
  52. package/lib/bspSet.d.ts.map +1 -1
  53. package/lib/bspSet.js.map +1 -1
  54. package/lib/handlecache.d.ts.map +1 -1
  55. package/lib/handlecache.js +1 -3
  56. package/lib/handlecache.js.map +1 -1
  57. package/lib/handletable.d.ts.map +1 -1
  58. package/lib/handletable.js +7 -3
  59. package/lib/handletable.js.map +1 -1
  60. package/lib/matrix.d.ts +1 -1
  61. package/lib/matrix.d.ts.map +1 -1
  62. package/lib/matrix.js +29 -20
  63. package/lib/matrix.js.map +1 -1
  64. package/lib/ops.d.ts.map +1 -1
  65. package/lib/ops.js.map +1 -1
  66. package/lib/packageVersion.d.ts +1 -1
  67. package/lib/packageVersion.js +1 -1
  68. package/lib/packageVersion.js.map +1 -1
  69. package/lib/permutationvector.d.ts.map +1 -1
  70. package/lib/permutationvector.js +15 -8
  71. package/lib/permutationvector.js.map +1 -1
  72. package/lib/productSet.d.ts.map +1 -1
  73. package/lib/productSet.js +6 -3
  74. package/lib/productSet.js.map +1 -1
  75. package/lib/range.d.ts.map +1 -1
  76. package/lib/range.js.map +1 -1
  77. package/lib/runtime.d.ts.map +1 -1
  78. package/lib/runtime.js.map +1 -1
  79. package/lib/serialization.d.ts.map +1 -1
  80. package/lib/serialization.js.map +1 -1
  81. package/lib/sparsearray2d.d.ts.map +1 -1
  82. package/lib/sparsearray2d.js +12 -12
  83. package/lib/sparsearray2d.js.map +1 -1
  84. package/lib/split.d.ts.map +1 -1
  85. package/lib/split.js +5 -3
  86. package/lib/split.js.map +1 -1
  87. package/lib/types.d.ts.map +1 -1
  88. package/lib/types.js.map +1 -1
  89. package/lib/undoprovider.d.ts.map +1 -1
  90. package/lib/undoprovider.js +1 -1
  91. package/lib/undoprovider.js.map +1 -1
  92. package/package.json +52 -52
  93. package/prettier.config.cjs +1 -1
  94. package/src/bspSet.ts +507 -434
  95. package/src/handlecache.ts +114 -112
  96. package/src/handletable.ts +66 -62
  97. package/src/matrix.ts +781 -710
  98. package/src/ops.ts +11 -11
  99. package/src/packageVersion.ts +1 -1
  100. package/src/permutationvector.ts +425 -368
  101. package/src/productSet.ts +852 -788
  102. package/src/range.ts +8 -8
  103. package/src/runtime.ts +35 -35
  104. package/src/serialization.ts +13 -9
  105. package/src/sparsearray2d.ts +196 -192
  106. package/src/split.ts +111 -90
  107. package/src/types.ts +3 -3
  108. package/src/undoprovider.ts +161 -144
  109. package/tsconfig.esnext.json +6 -6
  110. package/tsconfig.json +8 -12
package/.eslintrc.js CHANGED
@@ -4,27 +4,26 @@
4
4
  */
5
5
 
6
6
  module.exports = {
7
- extends: [require.resolve("@fluidframework/eslint-config-fluid/minimal"), "prettier"],
7
+ extends: [require.resolve("@fluidframework/eslint-config-fluid/minimal"), "prettier"],
8
8
 
9
- parserOptions: {
10
- project: ["./tsconfig.json", "./src/test/tsconfig.json"],
11
- },
12
- rules: {
13
- "@typescript-eslint/no-shadow": "off",
14
- "space-before-function-paren": "off", // Off because it conflicts with typescript-formatter
9
+ parserOptions: {
10
+ project: ["./tsconfig.json", "./src/test/tsconfig.json"],
11
+ },
12
+ rules: {
13
+ "@typescript-eslint/no-shadow": "off",
14
+ "space-before-function-paren": "off", // Off because it conflicts with typescript-formatter
15
15
 
16
- // This library is used in the browser, so we don't want dependencies on most node libraries.
17
- "import/no-nodejs-modules": ["error", { allow: ["events"] }],
18
- },
19
- overrides: [
20
- {
21
- // Rules only for test files
22
- files: ["*.spec.ts", "src/test/**"],
23
- rules: {
24
- // Test files are run in node only so additional node libraries can be used.
25
- "import/no-nodejs-modules": ["error", { allow: ["assert", "events"] }],
26
-
27
- },
28
- },
29
- ],
16
+ // This library is used in the browser, so we don't want dependencies on most node libraries.
17
+ "import/no-nodejs-modules": ["error", { allow: ["events"] }],
18
+ },
19
+ overrides: [
20
+ {
21
+ // Rules only for test files
22
+ files: ["*.spec.ts", "src/test/**"],
23
+ rules: {
24
+ // Test files are run in node only so additional node libraries can be used.
25
+ "import/no-nodejs-modules": ["error", { allow: ["assert", "events"] }],
26
+ },
27
+ },
28
+ ],
30
29
  };
package/.mocharc.js CHANGED
@@ -3,9 +3,9 @@
3
3
  * Licensed under the MIT License.
4
4
  */
5
5
 
6
- 'use strict';
6
+ "use strict";
7
7
 
8
- const getFluidTestMochaConfig = require('@fluidframework/mocha-test-setup/mocharc-common');
8
+ const getFluidTestMochaConfig = require("@fluidframework/mocha-test-setup/mocharc-common");
9
9
 
10
10
  const packageDir = __dirname;
11
11
  const config = getFluidTestMochaConfig(packageDir);
package/README.md CHANGED
@@ -1,14 +1,14 @@
1
1
  # @fluidframework/matrix
2
2
 
3
- SharedMatrix is a rectangular 2D array of values. Matrix values are a superset of JSON serializable types that includes embedded IFluidHandle references to Fluid object.
3
+ SharedMatrix is a rectangular 2D array of values. Matrix values are a superset of JSON serializable types that includes embedded IFluidHandle references to Fluid object.
4
4
 
5
5
  ## Operations
6
6
 
7
7
  The SharedMatrix currently supports the following operations:
8
8
 
9
- * `insertCols(col, numCols)` / `removeCols(col, numCols)`
10
- * `insertRows(row, numRows)` / `removeRows(row, numRows)`
11
- * `setCells(row, col, numCols, values)` (values is a 1D array in row-major order)
9
+ - `insertCols(col, numCols)` / `removeCols(col, numCols)`
10
+ - `insertRows(row, numRows)` / `removeRows(row, numRows)`
11
+ - `setCells(row, col, numCols, values)` (values is a 1D array in row-major order)
12
12
 
13
13
  Insertion / removal operations are reconciled using Fluid sequence semantics, while setCells() uses Fluid map semantics.
14
14
 
@@ -16,8 +16,8 @@ Insertion / removal operations are reconciled using Fluid sequence semantics, wh
16
16
 
17
17
  The SharedMatrix data structure is comprised of:
18
18
 
19
- * Two 'PermutationVectors', which are used to process row/col insertion and removal ops
20
- * A sparse quadtree-like "physical store" for holding the cell values
19
+ - Two 'PermutationVectors', which are used to process row/col insertion and removal ops
20
+ - A sparse quadtree-like "physical store" for holding the cell values
21
21
 
22
22
  ### Permutation Vectors
23
23
 
@@ -57,7 +57,7 @@ physical row -> 1 | 8 .
57
57
  ```
58
58
 
59
59
  The next row/column to be inserted is assigned the next available physical address, regardless of
60
- where the row/col was logically inserted. Deleted rows/cols are recycled after clearing the physical store.
60
+ where the row/col was logically inserted. Deleted rows/cols are recycled after clearing the physical store.
61
61
 
62
62
  This indirection between logical row/col and storage row/col provides three functions:
63
63
 
@@ -66,12 +66,12 @@ This indirection between logical row/col and storage row/col provides three func
66
66
  updated).
67
67
  3. It enables us to "time-travel" to previous matrix versions when reconciling ops from remote clients.
68
68
 
69
- To support reconciliation, we use a MergeTree for each PermutationVector. MergeTree is a B-Tree of order 7 that
69
+ To support reconciliation, we use a MergeTree for each PermutationVector. MergeTree is a B-Tree of order 7 that
70
70
  temporarily maintains some extra metadata to reconcile ops while they are within the current collab window.
71
71
 
72
72
  ### Physical Storage
73
73
 
74
- Cell data is stored in a quadtree-like data structure that is a recursive subdivision of 16x16 tiles. The
74
+ Cell data is stored in a quadtree-like data structure that is a recursive subdivision of 16x16 tiles. The
75
75
  implementation leverages [Morton coding](https://en.wikipedia.org/wiki/Z-order_curve) to implement this as a cascade of
76
76
  fast 1D array accesses.
77
77
 
@@ -81,20 +81,20 @@ const keyLo = r0c0ToMorton2x16((row << 16) >>> 16, (col << 16) >>> 16);
81
81
 
82
82
  const level0 = this.root[keyHi];
83
83
  if (level0 !== undefined) {
84
- const level1 = level0[byte0(keyLo)];
85
- if (level1 !== undefined) {
86
- const level2 = level1[byte1(keyLo)];
87
- if (level2 !== undefined) {
88
- const level3 = level2[byte2(keyLo)];
89
- if (level3 !== undefined) {
90
- return level3[byte3(keyLo)];
91
- }
92
- }
93
- }
84
+ const level1 = level0[byte0(keyLo)];
85
+ if (level1 !== undefined) {
86
+ const level2 = level1[byte1(keyLo)];
87
+ if (level2 !== undefined) {
88
+ const level3 = level2[byte2(keyLo)];
89
+ if (level3 !== undefined) {
90
+ return level3[byte3(keyLo)];
91
+ }
92
+ }
93
+ }
94
94
  }
95
- return undefined; // Empty region
95
+ return undefined; // Empty region
96
96
  ```
97
97
 
98
98
  A benefit of storing the cell data in [Z-order](https://en.wikipedia.org/wiki/Z-order_curve) is that both row-major and
99
- col-major traversal benefit from prefetching and cache coherence. Reading/writing to the physical storage along either
99
+ col-major traversal benefit from prefetching and cache coherence. Reading/writing to the physical storage along either
100
100
  axis is typically within an order of magnitude compared to sequentially accessing a cache hot native JavaScript array.
@@ -1,4 +1,4 @@
1
1
  {
2
- "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3
- "extends": "@fluidframework/build-common/api-extractor-common-report.json"
2
+ "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json",
3
+ "extends": "@fluidframework/build-common/api-extractor-common-report.json"
4
4
  }
@@ -69,10 +69,10 @@ the BSP sets in general to be fairly simple.
69
69
 
70
70
  Now the memory footprint of the BSP set is thus:
71
71
 
72
- - Some general overhead for the whole BSP set, i.e. object cost
73
- - Linear in the number of keys used for the exact representation.
74
- Usually tiny, because they replace whole subtrees and occur infrequently.
75
- - About 2.5 bits per node. I.e. **tiny**.
72
+ - Some general overhead for the whole BSP set, i.e. object cost
73
+ - Linear in the number of keys used for the exact representation.
74
+ Usually tiny, because they replace whole subtrees and occur infrequently.
75
+ - About 2.5 bits per node. I.e. **tiny**.
76
76
 
77
77
  All the algorithms recurse over the structure of the tree, so they should be able to run over this
78
78
  bit encoding as well. Chances are it would be a lot faster, but definitely consuming a lot less
@@ -81,4 +81,4 @@ memory than before.
81
81
  ## Application
82
82
 
83
83
  If we did this change, we might be able to use raw product sets as messages inside say a shared dictionary
84
- because the payload of the messages might be small enough for that.
84
+ because the payload of the messages might be small enough for that.
@@ -6,25 +6,43 @@
6
6
  import { run } from "hotloop";
7
7
 
8
8
  (async () => {
9
- console.group("Populated");
10
- await run([
11
- // { path: "./src/read/nativearray", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true } },
12
- // { path: "./src/read/map", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true } },
13
- { path: "./src/read/sparsearray2d", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true } },
14
- { path: "./src/read/matrix/contiguous", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true } },
15
- { path: "./src/read/matrix/fragmented", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true } },
16
- // { path: "./src/read/tiled", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true } }
17
- ]);
18
- console.groupEnd();
9
+ console.group("Populated");
10
+ await run([
11
+ // { path: "./src/read/nativearray", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true } },
12
+ // { path: "./src/read/map", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true } },
13
+ {
14
+ path: "./src/read/sparsearray2d",
15
+ args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true },
16
+ },
17
+ {
18
+ path: "./src/read/matrix/contiguous",
19
+ args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true },
20
+ },
21
+ {
22
+ path: "./src/read/matrix/fragmented",
23
+ args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true },
24
+ },
25
+ // { path: "./src/read/tiled", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: true } }
26
+ ]);
27
+ console.groupEnd();
19
28
 
20
- console.group("Empty");
21
- await run([
22
- // { path: "./src/read/nativearray", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false } },
23
- // { path: "./src/read/map", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false } },
24
- { path: "./src/read/sparsearray2d", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false } },
25
- { path: "./src/read/matrix/contiguous", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false } },
26
- { path: "./src/read/matrix/fragmented", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false } },
27
- // { path: "./src/read/tiled", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false } }
28
- ]);
29
- console.groupEnd();
29
+ console.group("Empty");
30
+ await run([
31
+ // { path: "./src/read/nativearray", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false } },
32
+ // { path: "./src/read/map", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false } },
33
+ {
34
+ path: "./src/read/sparsearray2d",
35
+ args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false },
36
+ },
37
+ {
38
+ path: "./src/read/matrix/contiguous",
39
+ args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false },
40
+ },
41
+ {
42
+ path: "./src/read/matrix/fragmented",
43
+ args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false },
44
+ },
45
+ // { path: "./src/read/tiled", args: { row: 0, col: 0, rowCount: 256, colCount: 256, fill: false } }
46
+ ]);
47
+ console.groupEnd();
30
48
  })();
@@ -6,20 +6,26 @@
6
6
  import { pointwise } from "./test";
7
7
 
8
8
  export class Map256x256<T> {
9
- private readonly cells = new Map<number, T>();
9
+ private readonly cells = new Map<number, T>();
10
10
 
11
- public get rowCount() { return 256; }
12
- public get colCount() { return 256; }
11
+ public get rowCount() {
12
+ return 256;
13
+ }
14
+ public get colCount() {
15
+ return 256;
16
+ }
13
17
 
14
- public getCell(row: number, col: number) {
15
- return this.cells.get((row << 8) + col);
16
- }
18
+ public getCell(row: number, col: number) {
19
+ return this.cells.get((row << 8) + col);
20
+ }
17
21
 
18
- public setCell(row: number, col: number, value: T) {
19
- this.cells.set((row << 8) + col, value);
20
- }
22
+ public setCell(row: number, col: number, value: T) {
23
+ this.cells.set((row << 8) + col, value);
24
+ }
21
25
 
22
- public get matrixProducer() { return undefined as any; }
26
+ public get matrixProducer() {
27
+ return undefined as any;
28
+ }
23
29
  }
24
30
 
25
31
  pointwise(undefined, new Map256x256<number>());
@@ -6,20 +6,26 @@
6
6
  import { pointwise } from "./test";
7
7
 
8
8
  export class Array256x256<T> {
9
- private readonly cells: T[] = new Array(256 * 256).fill(0);
9
+ private readonly cells: T[] = new Array(256 * 256).fill(0);
10
10
 
11
- public get rowCount() { return 256; }
12
- public get colCount() { return 256; }
11
+ public get rowCount() {
12
+ return 256;
13
+ }
14
+ public get colCount() {
15
+ return 256;
16
+ }
13
17
 
14
- public getCell(row: number, col: number) {
15
- return this.cells[(row << 8) + col];
16
- }
18
+ public getCell(row: number, col: number) {
19
+ return this.cells[(row << 8) + col];
20
+ }
17
21
 
18
- public setCell(row: number, col: number, value: T) {
19
- this.cells[(row << 8) + col] = value;
20
- }
22
+ public setCell(row: number, col: number, value: T) {
23
+ this.cells[(row << 8) + col] = value;
24
+ }
21
25
 
22
- public get matrixProducer() { return undefined as any; }
26
+ public get matrixProducer() {
27
+ return undefined as any;
28
+ }
23
29
  }
24
30
 
25
31
  pointwise(undefined, new Array256x256<number>());
@@ -9,24 +9,22 @@ import { fill, IMatrix } from "../imports";
9
9
  const { row, col, rowCount, colCount, fill: shouldFill } = getTestArgs();
10
10
 
11
11
  export function pointwise<T>(name: string | undefined, matrix: IMatrix<T>) {
12
- if (shouldFill) {
13
- fill(matrix, row, col, rowCount, colCount);
14
- }
12
+ if (shouldFill) {
13
+ fill(matrix, row, col, rowCount, colCount);
14
+ }
15
15
 
16
- benchmark(
17
- `SUM ${name !== undefined ? name : matrix.constructor.name} (${
18
- shouldFill
19
- ? "full"
20
- : "empty"
21
- }) Pointwise Read ${rowCount}x${colCount} @${row},${col}`,
22
- () => {
23
- let sum = 0;
24
- for (let r = row; r < rowCount; r++) {
25
- for (let c = col; c < colCount; c++) {
26
- sum += (matrix.getCell(r, c) as any | 0);
27
- }
28
- }
29
- return sum;
30
- }
31
- );
16
+ benchmark(
17
+ `SUM ${name !== undefined ? name : matrix.constructor.name} (${
18
+ shouldFill ? "full" : "empty"
19
+ }) Pointwise Read ${rowCount}x${colCount} @${row},${col}`,
20
+ () => {
21
+ let sum = 0;
22
+ for (let r = row; r < rowCount; r++) {
23
+ for (let c = col; c < colCount; c++) {
24
+ sum += matrix.getCell(r, c) as any | 0;
25
+ }
26
+ }
27
+ return sum;
28
+ },
29
+ );
32
30
  }