@malloydata/malloy-profiler 0.0.300

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.
package/README.md ADDED
@@ -0,0 +1,8 @@
1
+ # Malloy Stable Request Profiler
2
+
3
+ This package enables profiling of the Malloy compiler. Currently it only works with stateless compilation of queries. In the future we can extend it support other kinds of compilation.
4
+
5
+ Usage:
6
+
7
+ - Write a Malloy query request to a file.
8
+ - Run `npm run profile path/to/file.json`
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,27 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ /* eslint-disable no-console */
10
+ const profiler_1 = require("./profiler");
11
+ async function main() {
12
+ const fs = require('fs');
13
+ const filePath = process.argv[2];
14
+ if (filePath === undefined) {
15
+ console.log('Missing file path');
16
+ return;
17
+ }
18
+ const fileContent = fs.readFileSync(filePath, 'utf8');
19
+ console.log(`REQUEST ${fileContent.substring(0, 100)}`);
20
+ const response = (0, profiler_1.compileQueryStable)(fileContent);
21
+ if (response.time) {
22
+ console.log(`TOOK: ${response.time}ms`);
23
+ }
24
+ console.log(`RESPONSE ${response.response.substring(0, 100)}`);
25
+ }
26
+ main();
27
+ //# sourceMappingURL=profile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAEH,+BAA+B;AAC/B,yCAA8C;AAE9C,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IACD,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,WAAW,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAExD,MAAM,QAAQ,GAAG,IAAA,6BAAkB,EAAC,WAAW,CAAC,CAAC;IAEjD,IAAI,QAAQ,CAAC,IAAI,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,SAAS,QAAQ,CAAC,IAAI,IAAI,CAAC,CAAC;IAC1C,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,YAAY,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;AACjE,CAAC;AAED,IAAI,EAAE,CAAC"}
@@ -0,0 +1,4 @@
1
+ export declare function compileQueryStable(serializedCompileQueryRequest: string): {
2
+ response: string;
3
+ time: number | undefined;
4
+ };
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.compileQueryStable = compileQueryStable;
10
+ /* eslint-disable no-console */
11
+ const malloy_1 = require("@malloydata/malloy");
12
+ const malloy_interfaces_1 = require("@malloydata/malloy-interfaces");
13
+ function compileQueryStableInternalObjRequest(parsedRequest) {
14
+ const sessionId = parsedRequest.session_id;
15
+ delete parsedRequest.session_id;
16
+ const request = (0, malloy_interfaces_1.convertFromThrift)(parsedRequest, 'CompileQueryRequest');
17
+ const now = Date.now();
18
+ const response = malloy_1.API.sessioned.compileQuery(request, {
19
+ ttl: {
20
+ seconds: 300,
21
+ },
22
+ session_id: sessionId,
23
+ });
24
+ const end = Date.now();
25
+ const took = end - now;
26
+ const { session_id, ...spreadedResponse } = response;
27
+ const withNestResponse = (0, malloy_interfaces_1.convertToThrift)(spreadedResponse, 'CompileQueryResponse');
28
+ // TODO: Remove when session id is part of the response thrift.
29
+ withNestResponse.session_id =
30
+ session_id;
31
+ return { response: withNestResponse, time: took };
32
+ }
33
+ function compileQueryStableInternal(serializedCompileQueryRequest) {
34
+ const parsedRequest = JSON.parse(serializedCompileQueryRequest);
35
+ const { response, time } = compileQueryStableInternalObjRequest(parsedRequest);
36
+ return { response: JSON.stringify(response), time };
37
+ }
38
+ // Compile Query.
39
+ function compileQueryStable(serializedCompileQueryRequest) {
40
+ var _a;
41
+ try {
42
+ return compileQueryStableInternal(serializedCompileQueryRequest);
43
+ }
44
+ catch (e) {
45
+ const response = {
46
+ logs: [
47
+ {
48
+ message: `Failed to compile Query ${e instanceof Error
49
+ ? `${e.message} ${(_a = e.stack) !== null && _a !== void 0 ? _a : ''}`
50
+ : JSON.stringify(e)}`,
51
+ severity: 'error',
52
+ // TODO: location should be optional.
53
+ url: '',
54
+ range: {
55
+ start: {
56
+ line: 0,
57
+ character: 0,
58
+ },
59
+ end: {
60
+ line: 0,
61
+ character: 0,
62
+ },
63
+ },
64
+ },
65
+ ],
66
+ };
67
+ return {
68
+ response: JSON.stringify((0, malloy_interfaces_1.convertToThrift)(response, 'CompileQueryResponse')),
69
+ time: undefined,
70
+ };
71
+ }
72
+ }
73
+ //# sourceMappingURL=profiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profiler.js","sourceRoot":"","sources":["../src/profiler.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AA8DH,gDAuCC;AAnGD,+BAA+B;AAC/B,+CAAuC;AAKvC,qEAGuC;AAUvC,SAAS,oCAAoC,CAC3C,aAA+C;IAE/C,MAAM,SAAS,GAAG,aAAa,CAAC,UAAU,CAAC;IAC3C,OAAO,aAAa,CAAC,UAAU,CAAC;IAChC,MAAM,OAAO,GAAG,IAAA,qCAAiB,EAC/B,aAAa,EACb,qBAAqB,CACC,CAAC;IAEzB,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,QAAQ,GAAG,YAAG,CAAC,SAAS,CAAC,YAAY,CAAC,OAAO,EAAE;QACnD,GAAG,EAAE;YACH,OAAO,EAAE,GAAG;SACb;QACD,UAAU,EAAE,SAAS;KACtB,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IACvB,MAAM,IAAI,GAAG,GAAG,GAAG,GAAG,CAAC;IAEvB,MAAM,EAAC,UAAU,EAAE,GAAG,gBAAgB,EAAC,GAAG,QAAQ,CAAC;IACnD,MAAM,gBAAgB,GAAG,IAAA,mCAAe,EACtC,gBAAgB,EAChB,sBAAsB,CACC,CAAC;IAC1B,+DAA+D;IAC9D,gBAAsD,CAAC,UAAU;QAChE,UAAU,CAAC;IACb,OAAO,EAAC,QAAQ,EAAE,gBAAgB,EAAE,IAAI,EAAE,IAAI,EAAC,CAAC;AAClD,CAAC;AAED,SAAS,0BAA0B,CAAC,6BAAqC;IAIvE,MAAM,aAAa,GAAG,IAAI,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAChE,MAAM,EAAC,QAAQ,EAAE,IAAI,EAAC,GAAG,oCAAoC,CAAC,aAAa,CAAC,CAAC;IAC7E,OAAO,EAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAC,CAAC;AACpD,CAAC;AAED,iBAAiB;AACjB,SAAgB,kBAAkB,CAAC,6BAAqC;;IAItE,IAAI,CAAC;QACH,OAAO,0BAA0B,CAAC,6BAA6B,CAAC,CAAC;IACnE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,MAAM,QAAQ,GAAyB;YACrC,IAAI,EAAE;gBACJ;oBACE,OAAO,EAAE,2BACP,CAAC,YAAY,KAAK;wBAChB,CAAC,CAAC,GAAG,CAAC,CAAC,OAAO,IAAI,MAAA,CAAC,CAAC,KAAK,mCAAI,EAAE,EAAE;wBACjC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CACtB,EAAE;oBACF,QAAQ,EAAE,OAAO;oBACjB,qCAAqC;oBACrC,GAAG,EAAE,EAAE;oBACP,KAAK,EAAE;wBACL,KAAK,EAAE;4BACL,IAAI,EAAE,CAAC;4BACP,SAAS,EAAE,CAAC;yBACb;wBACD,GAAG,EAAE;4BACH,IAAI,EAAE,CAAC;4BACP,SAAS,EAAE,CAAC;yBACb;qBACF;iBACF;aACF;SACF,CAAC;QAEF,OAAO;YACL,QAAQ,EAAE,IAAI,CAAC,SAAS,CACtB,IAAA,mCAAe,EAAC,QAAQ,EAAE,sBAAsB,CAAC,CAClD;YACD,IAAI,EAAE,SAAS;SAChB,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -0,0 +1 @@
1
+ export {};
package/dist/timer.js ADDED
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ /*
3
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
4
+ *
5
+ * This source code is licensed under the MIT license found in the
6
+ * LICENSE file in the root directory of this source tree.
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ /* eslint-disable no-console */
10
+ const profiler_1 = require("./profiler");
11
+ async function main() {
12
+ const fs = require('fs');
13
+ const filePath = process.argv[2];
14
+ if (filePath === undefined) {
15
+ console.log('Missing file path');
16
+ return;
17
+ }
18
+ const fileContent = fs.readFileSync(filePath, 'utf8');
19
+ console.log(`REQUEST ${fileContent.substring(0, 100)}`);
20
+ const times = [];
21
+ for (let i = 0; i < 100; i++) {
22
+ const response = (0, profiler_1.compileQueryStable)(fileContent);
23
+ if (i === 0) {
24
+ console.log(`RESPONSE ${response.response.substring(0, 100)}`);
25
+ }
26
+ if (response.time !== undefined) {
27
+ times.push(response.time);
28
+ }
29
+ else {
30
+ return;
31
+ }
32
+ }
33
+ const avg = times.reduce((a, b) => a + b) / times.length;
34
+ console.log('AVERAGE TIME = ' + avg + 'ms');
35
+ }
36
+ main();
37
+ //# sourceMappingURL=timer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"timer.js","sourceRoot":"","sources":["../src/timer.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;AAEH,+BAA+B;AAC/B,yCAA8C;AAE9C,KAAK,UAAU,IAAI;IACjB,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzB,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACjC,IAAI,QAAQ,KAAK,SAAS,EAAE,CAAC;QAC3B,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;QACjC,OAAO;IACT,CAAC;IACD,MAAM,WAAW,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACtD,OAAO,CAAC,GAAG,CAAC,WAAW,WAAW,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACxD,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,IAAA,6BAAkB,EAAC,WAAW,CAAC,CAAC;QACjD,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACZ,OAAO,CAAC,GAAG,CAAC,YAAY,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;QACjE,CAAC;QACD,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,OAAO;QACT,CAAC;IACH,CAAC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC;IACzD,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,GAAG,GAAG,IAAI,CAAC,CAAC;AAC9C,CAAC;AAED,IAAI,EAAE,CAAC"}
package/package.json ADDED
@@ -0,0 +1,30 @@
1
+ {
2
+ "name": "@malloydata/malloy-profiler",
3
+ "license": "MIT",
4
+ "engines": {
5
+ "node": ">=20"
6
+ },
7
+ "main": "dist/index.js",
8
+ "types": "dist/index.d.ts",
9
+ "homepage": "https://github.com/malloydata/malloy#readme",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/malloydata/malloy"
13
+ },
14
+ "scripts": {
15
+ "lint": "eslint '**/*.ts{,x}'",
16
+ "lint-fix": "eslint '**/*.ts{,x}' --fix",
17
+ "test": "jest --config=../jest.config.js",
18
+ "build": "tsc --build",
19
+ "clean": "tsc --build --clean",
20
+ "profile": "npx clinic flame -- node dist/profile.js",
21
+ "time": "ts-node src/timer.ts"
22
+ },
23
+ "dependencies": {
24
+ "@malloydata/malloy": "0.0.300",
25
+ "@malloydata/malloy-interfaces": "0.0.300",
26
+ "clinic": "^13.0.0"
27
+ },
28
+ "devDependencies": {},
29
+ "version": "0.0.300"
30
+ }
package/src/profile.ts ADDED
@@ -0,0 +1,30 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /* eslint-disable no-console */
9
+ import {compileQueryStable} from './profiler';
10
+
11
+ async function main() {
12
+ const fs = require('fs');
13
+ const filePath = process.argv[2];
14
+ if (filePath === undefined) {
15
+ console.log('Missing file path');
16
+ return;
17
+ }
18
+ const fileContent = fs.readFileSync(filePath, 'utf8');
19
+ console.log(`REQUEST ${fileContent.substring(0, 100)}`);
20
+
21
+ const response = compileQueryStable(fileContent);
22
+
23
+ if (response.time) {
24
+ console.log(`TOOK: ${response.time}ms`);
25
+ }
26
+
27
+ console.log(`RESPONSE ${response.response.substring(0, 100)}`);
28
+ }
29
+
30
+ main();
@@ -0,0 +1,107 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /* eslint-disable no-console */
9
+ import {API} from '@malloydata/malloy';
10
+ import type {
11
+ CompileQueryResponse,
12
+ CompileQueryRequest,
13
+ } from '@malloydata/malloy-interfaces';
14
+ import {
15
+ convertFromThrift,
16
+ convertToThrift,
17
+ } from '@malloydata/malloy-interfaces';
18
+
19
+ type CompileQueryRequestWithSessionId = CompileQueryRequest & {
20
+ session_id?: string;
21
+ };
22
+
23
+ type CompileQueryResponseWithSessionId = CompileQueryResponse & {
24
+ session_id?: string;
25
+ };
26
+
27
+ function compileQueryStableInternalObjRequest(
28
+ parsedRequest: CompileQueryRequestWithSessionId
29
+ ): {response: CompileQueryResponse; time: number} {
30
+ const sessionId = parsedRequest.session_id;
31
+ delete parsedRequest.session_id;
32
+ const request = convertFromThrift(
33
+ parsedRequest,
34
+ 'CompileQueryRequest'
35
+ ) as CompileQueryRequest;
36
+
37
+ const now = Date.now();
38
+ const response = API.sessioned.compileQuery(request, {
39
+ ttl: {
40
+ seconds: 300,
41
+ },
42
+ session_id: sessionId,
43
+ });
44
+ const end = Date.now();
45
+ const took = end - now;
46
+
47
+ const {session_id, ...spreadedResponse} = response;
48
+ const withNestResponse = convertToThrift(
49
+ spreadedResponse,
50
+ 'CompileQueryResponse'
51
+ ) as CompileQueryResponse;
52
+ // TODO: Remove when session id is part of the response thrift.
53
+ (withNestResponse as CompileQueryResponseWithSessionId).session_id =
54
+ session_id;
55
+ return {response: withNestResponse, time: took};
56
+ }
57
+
58
+ function compileQueryStableInternal(serializedCompileQueryRequest: string): {
59
+ response: string;
60
+ time: number;
61
+ } {
62
+ const parsedRequest = JSON.parse(serializedCompileQueryRequest);
63
+ const {response, time} = compileQueryStableInternalObjRequest(parsedRequest);
64
+ return {response: JSON.stringify(response), time};
65
+ }
66
+
67
+ // Compile Query.
68
+ export function compileQueryStable(serializedCompileQueryRequest: string): {
69
+ response: string;
70
+ time: number | undefined;
71
+ } {
72
+ try {
73
+ return compileQueryStableInternal(serializedCompileQueryRequest);
74
+ } catch (e) {
75
+ const response: CompileQueryResponse = {
76
+ logs: [
77
+ {
78
+ message: `Failed to compile Query ${
79
+ e instanceof Error
80
+ ? `${e.message} ${e.stack ?? ''}`
81
+ : JSON.stringify(e)
82
+ }`,
83
+ severity: 'error',
84
+ // TODO: location should be optional.
85
+ url: '',
86
+ range: {
87
+ start: {
88
+ line: 0,
89
+ character: 0,
90
+ },
91
+ end: {
92
+ line: 0,
93
+ character: 0,
94
+ },
95
+ },
96
+ },
97
+ ],
98
+ };
99
+
100
+ return {
101
+ response: JSON.stringify(
102
+ convertToThrift(response, 'CompileQueryResponse')
103
+ ),
104
+ time: undefined,
105
+ };
106
+ }
107
+ }
package/src/timer.ts ADDED
@@ -0,0 +1,36 @@
1
+ /*
2
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
3
+ *
4
+ * This source code is licensed under the MIT license found in the
5
+ * LICENSE file in the root directory of this source tree.
6
+ */
7
+
8
+ /* eslint-disable no-console */
9
+ import {compileQueryStable} from './profiler';
10
+
11
+ async function main() {
12
+ const fs = require('fs');
13
+ const filePath = process.argv[2];
14
+ if (filePath === undefined) {
15
+ console.log('Missing file path');
16
+ return;
17
+ }
18
+ const fileContent = fs.readFileSync(filePath, 'utf8');
19
+ console.log(`REQUEST ${fileContent.substring(0, 100)}`);
20
+ const times: number[] = [];
21
+ for (let i = 0; i < 100; i++) {
22
+ const response = compileQueryStable(fileContent);
23
+ if (i === 0) {
24
+ console.log(`RESPONSE ${response.response.substring(0, 100)}`);
25
+ }
26
+ if (response.time !== undefined) {
27
+ times.push(response.time);
28
+ } else {
29
+ return;
30
+ }
31
+ }
32
+ const avg = times.reduce((a, b) => a + b) / times.length;
33
+ console.log('AVERAGE TIME = ' + avg + 'ms');
34
+ }
35
+
36
+ main();
package/tsconfig.json ADDED
@@ -0,0 +1,19 @@
1
+ {
2
+ "extends": "../tsconfig.packages.json",
3
+ "compilerOptions": {
4
+ "rootDir": "src",
5
+ "outDir": "dist",
6
+ "composite": true,
7
+ "jsx": "react-jsx",
8
+ "jsxImportSource": "solid-js"
9
+ },
10
+ "include": ["src"],
11
+ "references": [
12
+ {
13
+ "path": "../packages/malloy-interfaces"
14
+ },
15
+ {
16
+ "path": "../packages/malloy"
17
+ },
18
+ ]
19
+ }