socket-function 0.9.0 → 0.9.2
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/.eslintrc.js +50 -50
- package/SocketFunction.ts +280 -280
- package/SocketFunctionTypes.ts +90 -90
- package/hot/HotReloadController.ts +105 -105
- package/mobx/UrlParam.ts +39 -39
- package/mobx/observer.tsx +49 -49
- package/mobx/promiseToObservable.tsx +41 -41
- package/package.json +30 -28
- package/require/CSSShim.ts +19 -19
- package/require/RequireController.ts +252 -252
- package/require/buffer.js +2368 -2368
- package/require/compileFlags.ts +44 -44
- package/require/require.html +13 -13
- package/require/require.js +462 -456
- package/spec.txt +115 -115
- package/src/CallFactory.ts +389 -389
- package/src/JSONLACKS/JSONLACKS.generated.js +17 -17
- package/src/JSONLACKS/JSONLACKS.pegjs +247 -247
- package/src/JSONLACKS/JSONLACKS.ts +429 -375
- package/src/args.ts +21 -21
- package/src/batching.ts +170 -129
- package/src/caching.ts +318 -314
- package/src/callHTTPHandler.ts +203 -203
- package/src/callManager.ts +134 -134
- package/src/certStore.ts +29 -29
- package/src/fixLargeNetworkCalls.ts +8 -8
- package/src/formatting/colors.ts +78 -78
- package/src/formatting/format.ts +160 -156
- package/src/formatting/logColors.ts +17 -17
- package/src/misc.ts +302 -171
- package/src/nodeCache.ts +92 -92
- package/src/nodeProxy.ts +54 -54
- package/src/profiling/getOwnTime.ts +142 -142
- package/src/profiling/measure.ts +273 -244
- package/src/profiling/stats.ts +212 -212
- package/src/profiling/tcpLagProxy.ts +63 -63
- package/src/storagePath.ts +10 -10
- package/src/tlsParsing.ts +96 -96
- package/src/types.ts +8 -8
- package/src/webSocketServer.ts +250 -250
- package/test/client.css +2 -2
- package/test/client.ts +46 -46
- package/test/server.ts +43 -43
- package/test/shared.ts +52 -52
- package/tsconfig.json +26 -26
package/src/nodeProxy.ts
CHANGED
|
@@ -1,55 +1,55 @@
|
|
|
1
|
-
import { lazy } from "./caching";
|
|
2
|
-
import { FullCallType, SocketExposedInterface, SocketInternalInterface } from "../SocketFunctionTypes";
|
|
3
|
-
|
|
4
|
-
type CallProxyType = {
|
|
5
|
-
[nodeId: string]: SocketInternalInterface;
|
|
6
|
-
};
|
|
7
|
-
|
|
8
|
-
export const getCallObj = Symbol.for("getCallObj");
|
|
9
|
-
|
|
10
|
-
let proxyCache = new Map<string, CallProxyType>();
|
|
11
|
-
export function getCallProxy(id: string, callback: (callType: FullCallType) => Promise<unknown>): CallProxyType {
|
|
12
|
-
let value = proxyCache.get(id);
|
|
13
|
-
if (!value) {
|
|
14
|
-
let nodeCache = new Map<string, CallProxyType[""]>();
|
|
15
|
-
value = new Proxy(Object.create(null), {
|
|
16
|
-
get(target, nodeId) {
|
|
17
|
-
if (typeof nodeId !== "string") return undefined;
|
|
18
|
-
let nodeProxy = nodeCache.get(nodeId);
|
|
19
|
-
if (!nodeProxy) {
|
|
20
|
-
nodeProxy = new Proxy(Object.create(null), {
|
|
21
|
-
get(target, functionName) {
|
|
22
|
-
if (typeof functionName !== "string") return undefined;
|
|
23
|
-
return Object.assign(
|
|
24
|
-
(...args: unknown[]) => {
|
|
25
|
-
let call: FullCallType = {
|
|
26
|
-
classGuid: id,
|
|
27
|
-
nodeId,
|
|
28
|
-
functionName,
|
|
29
|
-
args,
|
|
30
|
-
};
|
|
31
|
-
return callback(call);
|
|
32
|
-
},
|
|
33
|
-
{
|
|
34
|
-
[getCallObj]: (...args: unknown[]) => {
|
|
35
|
-
let call: FullCallType = {
|
|
36
|
-
classGuid: id,
|
|
37
|
-
nodeId,
|
|
38
|
-
functionName,
|
|
39
|
-
args,
|
|
40
|
-
};
|
|
41
|
-
return call;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
}) as CallProxyType[""];
|
|
47
|
-
nodeCache.set(nodeId, nodeProxy);
|
|
48
|
-
}
|
|
49
|
-
return nodeProxy;
|
|
50
|
-
},
|
|
51
|
-
}) as CallProxyType;
|
|
52
|
-
proxyCache.set(id, value);
|
|
53
|
-
}
|
|
54
|
-
return value;
|
|
1
|
+
import { lazy } from "./caching";
|
|
2
|
+
import { FullCallType, SocketExposedInterface, SocketInternalInterface } from "../SocketFunctionTypes";
|
|
3
|
+
|
|
4
|
+
type CallProxyType = {
|
|
5
|
+
[nodeId: string]: SocketInternalInterface;
|
|
6
|
+
};
|
|
7
|
+
|
|
8
|
+
export const getCallObj = Symbol.for("getCallObj");
|
|
9
|
+
|
|
10
|
+
let proxyCache = new Map<string, CallProxyType>();
|
|
11
|
+
export function getCallProxy(id: string, callback: (callType: FullCallType) => Promise<unknown>): CallProxyType {
|
|
12
|
+
let value = proxyCache.get(id);
|
|
13
|
+
if (!value) {
|
|
14
|
+
let nodeCache = new Map<string, CallProxyType[""]>();
|
|
15
|
+
value = new Proxy(Object.create(null), {
|
|
16
|
+
get(target, nodeId) {
|
|
17
|
+
if (typeof nodeId !== "string") return undefined;
|
|
18
|
+
let nodeProxy = nodeCache.get(nodeId);
|
|
19
|
+
if (!nodeProxy) {
|
|
20
|
+
nodeProxy = new Proxy(Object.create(null), {
|
|
21
|
+
get(target, functionName) {
|
|
22
|
+
if (typeof functionName !== "string") return undefined;
|
|
23
|
+
return Object.assign(
|
|
24
|
+
(...args: unknown[]) => {
|
|
25
|
+
let call: FullCallType = {
|
|
26
|
+
classGuid: id,
|
|
27
|
+
nodeId,
|
|
28
|
+
functionName,
|
|
29
|
+
args,
|
|
30
|
+
};
|
|
31
|
+
return callback(call);
|
|
32
|
+
},
|
|
33
|
+
{
|
|
34
|
+
[getCallObj]: (...args: unknown[]) => {
|
|
35
|
+
let call: FullCallType = {
|
|
36
|
+
classGuid: id,
|
|
37
|
+
nodeId,
|
|
38
|
+
functionName,
|
|
39
|
+
args,
|
|
40
|
+
};
|
|
41
|
+
return call;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
}) as CallProxyType[""];
|
|
47
|
+
nodeCache.set(nodeId, nodeProxy);
|
|
48
|
+
}
|
|
49
|
+
return nodeProxy;
|
|
50
|
+
},
|
|
51
|
+
}) as CallProxyType;
|
|
52
|
+
proxyCache.set(id, value);
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
55
|
}
|
|
@@ -1,143 +1,143 @@
|
|
|
1
|
-
import debugbreak from "debugbreak";
|
|
2
|
-
// TODO: We could probably make this an optional / dev dependency, to allow
|
|
3
|
-
// for use on machines without the ability to compile?
|
|
4
|
-
import { now } from "rdtsc-now";
|
|
5
|
-
|
|
6
|
-
export type OwnTimeObj = {
|
|
7
|
-
name: string;
|
|
8
|
-
time: number;
|
|
9
|
-
ownTime: number;
|
|
10
|
-
};
|
|
11
|
-
type OwnTimeObjInternal = OwnTimeObj & {
|
|
12
|
-
lastStartTime: number;
|
|
13
|
-
firstStartTime: number;
|
|
14
|
-
parent: OwnTimeObjInternal | undefined;
|
|
15
|
-
child: OwnTimeObjInternal | undefined;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
let pendingCallTime: OwnTimeObjInternal | undefined;
|
|
19
|
-
export function getPendingOwnTimeObjs(): (OwnTimeObj & { source: OwnTimeObjInternal })[] | undefined {
|
|
20
|
-
let time = now();
|
|
21
|
-
let instances = getPendingOwnTimeInstances();
|
|
22
|
-
if (!instances) return undefined;
|
|
23
|
-
if (!pendingCallTime) return undefined;
|
|
24
|
-
let results = instances.map((instance) => ({
|
|
25
|
-
name: instance.name,
|
|
26
|
-
ownTime: instance.ownTime,
|
|
27
|
-
time: time - instance.firstStartTime,
|
|
28
|
-
source: instance
|
|
29
|
-
}));
|
|
30
|
-
results[0].ownTime += time - pendingCallTime.lastStartTime;
|
|
31
|
-
return results;
|
|
32
|
-
}
|
|
33
|
-
export function getPendingOwnTimeInstances(): OwnTimeObjInternal[] | undefined {
|
|
34
|
-
if (!pendingCallTime) return undefined;
|
|
35
|
-
let results: OwnTimeObjInternal[] = [];
|
|
36
|
-
let current: OwnTimeObjInternal | undefined = pendingCallTime;
|
|
37
|
-
while (current) {
|
|
38
|
-
results.push(current);
|
|
39
|
-
current = current.parent;
|
|
40
|
-
}
|
|
41
|
-
return results;
|
|
42
|
-
}
|
|
43
|
-
(global as any).pendingOwnCallTime = pendingCallTime;
|
|
44
|
-
|
|
45
|
-
// NOTE: This overhead time is actually mostly for aggregate time, but it is needed,
|
|
46
|
-
// otherwise we consistently underestimate the time spent.
|
|
47
|
-
// ALSO! This forces high count lines to be at the top of the aggregate time list, which is really important!
|
|
48
|
-
// NOTE: The overhead time greatly varies, but even if it only takes 100ns, if 10X of that
|
|
49
|
-
// is significant, you are probably spending too much timing profiling anyway!
|
|
50
|
-
export const measureOverheadTime = 500 / 1000 / 1000;
|
|
51
|
-
// We internally add, because of where we measure time, there is time spent before we grab the
|
|
52
|
-
// current time, and after we record the last time, that is lost, but should be added.
|
|
53
|
-
let addMeasureOverheadTime = 0;
|
|
54
|
-
{
|
|
55
|
-
// NOTE: This is going to vary considerably. I assume because sometimes we are on a core
|
|
56
|
-
// that is free, and other times we are on a core that is hyperthreading with another hardware
|
|
57
|
-
// thread. This really hurts us because our timing uses rdtsc, which really hates hyper threading,
|
|
58
|
-
// and can easily get 50% slower because of it.
|
|
59
|
-
let results: number[] = [];
|
|
60
|
-
for (let j = 0; j < 10; j++) {
|
|
61
|
-
const measureCount = 1000 * 10;
|
|
62
|
-
let time = now();
|
|
63
|
-
for (let i = 0; i < measureCount; i++) {
|
|
64
|
-
getOwnTime("test", () => { }, () => { });
|
|
65
|
-
}
|
|
66
|
-
time = now() - time;
|
|
67
|
-
let overhead = time / measureCount;
|
|
68
|
-
results.push(overhead);
|
|
69
|
-
}
|
|
70
|
-
results.sort((a, b) => a - b);
|
|
71
|
-
addMeasureOverheadTime = results[results.length / 2];
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// TIMING: About 60ns, of which 40ns is just now() calls.
|
|
75
|
-
// If async is closer to 300ns.
|
|
76
|
-
export function getOwnTime<T>(
|
|
77
|
-
name: string,
|
|
78
|
-
code: () => T,
|
|
79
|
-
onTime: (obj: OwnTimeObj) => void
|
|
80
|
-
): T {
|
|
81
|
-
let time = now();
|
|
82
|
-
let obj: OwnTimeObjInternal = {
|
|
83
|
-
name,
|
|
84
|
-
time: 0,
|
|
85
|
-
ownTime: 0,
|
|
86
|
-
firstStartTime: time,
|
|
87
|
-
lastStartTime: time,
|
|
88
|
-
parent: pendingCallTime,
|
|
89
|
-
child: undefined,
|
|
90
|
-
};
|
|
91
|
-
if (pendingCallTime) {
|
|
92
|
-
pendingCallTime.child = obj;
|
|
93
|
-
}
|
|
94
|
-
pendingCallTime = obj;
|
|
95
|
-
if (obj.parent) {
|
|
96
|
-
obj.parent.ownTime += obj.lastStartTime - obj.parent.lastStartTime;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
function finish() {
|
|
100
|
-
let time = now();
|
|
101
|
-
obj.time = time - obj.firstStartTime;
|
|
102
|
-
if (pendingCallTime === obj) {
|
|
103
|
-
// Good case, all of our children call ended before us.
|
|
104
|
-
|
|
105
|
-
// End our own time calculation
|
|
106
|
-
obj.ownTime += time - obj.lastStartTime;
|
|
107
|
-
|
|
108
|
-
// Our parent is now the last open call
|
|
109
|
-
pendingCallTime = obj.parent;
|
|
110
|
-
if (pendingCallTime) {
|
|
111
|
-
// Resume our parent ownTime counting
|
|
112
|
-
pendingCallTime.lastStartTime = time;
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
if (obj.child && obj.parent) {
|
|
116
|
-
obj.child.parent = obj.parent;
|
|
117
|
-
obj.parent.child = obj.child;
|
|
118
|
-
}
|
|
119
|
-
obj.parent = undefined;
|
|
120
|
-
obj.child = undefined;
|
|
121
|
-
|
|
122
|
-
obj.time += addMeasureOverheadTime;
|
|
123
|
-
obj.ownTime += addMeasureOverheadTime;
|
|
124
|
-
|
|
125
|
-
onTime(obj);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
let isAsync = false;
|
|
129
|
-
try {
|
|
130
|
-
let result = code();
|
|
131
|
-
if (result && typeof result === "object" && result instanceof Promise) {
|
|
132
|
-
isAsync = true;
|
|
133
|
-
return result.finally(() => {
|
|
134
|
-
finish();
|
|
135
|
-
}) as any;
|
|
136
|
-
}
|
|
137
|
-
return result;
|
|
138
|
-
} finally {
|
|
139
|
-
if (!isAsync) {
|
|
140
|
-
finish();
|
|
141
|
-
}
|
|
142
|
-
}
|
|
1
|
+
import debugbreak from "debugbreak";
|
|
2
|
+
// TODO: We could probably make this an optional / dev dependency, to allow
|
|
3
|
+
// for use on machines without the ability to compile?
|
|
4
|
+
import { now } from "rdtsc-now";
|
|
5
|
+
|
|
6
|
+
export type OwnTimeObj = {
|
|
7
|
+
name: string;
|
|
8
|
+
time: number;
|
|
9
|
+
ownTime: number;
|
|
10
|
+
};
|
|
11
|
+
type OwnTimeObjInternal = OwnTimeObj & {
|
|
12
|
+
lastStartTime: number;
|
|
13
|
+
firstStartTime: number;
|
|
14
|
+
parent: OwnTimeObjInternal | undefined;
|
|
15
|
+
child: OwnTimeObjInternal | undefined;
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
let pendingCallTime: OwnTimeObjInternal | undefined;
|
|
19
|
+
export function getPendingOwnTimeObjs(): (OwnTimeObj & { source: OwnTimeObjInternal })[] | undefined {
|
|
20
|
+
let time = now();
|
|
21
|
+
let instances = getPendingOwnTimeInstances();
|
|
22
|
+
if (!instances) return undefined;
|
|
23
|
+
if (!pendingCallTime) return undefined;
|
|
24
|
+
let results = instances.map((instance) => ({
|
|
25
|
+
name: instance.name,
|
|
26
|
+
ownTime: instance.ownTime,
|
|
27
|
+
time: time - instance.firstStartTime,
|
|
28
|
+
source: instance
|
|
29
|
+
}));
|
|
30
|
+
results[0].ownTime += time - pendingCallTime.lastStartTime;
|
|
31
|
+
return results;
|
|
32
|
+
}
|
|
33
|
+
export function getPendingOwnTimeInstances(): OwnTimeObjInternal[] | undefined {
|
|
34
|
+
if (!pendingCallTime) return undefined;
|
|
35
|
+
let results: OwnTimeObjInternal[] = [];
|
|
36
|
+
let current: OwnTimeObjInternal | undefined = pendingCallTime;
|
|
37
|
+
while (current) {
|
|
38
|
+
results.push(current);
|
|
39
|
+
current = current.parent;
|
|
40
|
+
}
|
|
41
|
+
return results;
|
|
42
|
+
}
|
|
43
|
+
(global as any).pendingOwnCallTime = pendingCallTime;
|
|
44
|
+
|
|
45
|
+
// NOTE: This overhead time is actually mostly for aggregate time, but it is needed,
|
|
46
|
+
// otherwise we consistently underestimate the time spent.
|
|
47
|
+
// ALSO! This forces high count lines to be at the top of the aggregate time list, which is really important!
|
|
48
|
+
// NOTE: The overhead time greatly varies, but even if it only takes 100ns, if 10X of that
|
|
49
|
+
// is significant, you are probably spending too much timing profiling anyway!
|
|
50
|
+
export const measureOverheadTime = 500 / 1000 / 1000;
|
|
51
|
+
// We internally add, because of where we measure time, there is time spent before we grab the
|
|
52
|
+
// current time, and after we record the last time, that is lost, but should be added.
|
|
53
|
+
let addMeasureOverheadTime = 0;
|
|
54
|
+
{
|
|
55
|
+
// NOTE: This is going to vary considerably. I assume because sometimes we are on a core
|
|
56
|
+
// that is free, and other times we are on a core that is hyperthreading with another hardware
|
|
57
|
+
// thread. This really hurts us because our timing uses rdtsc, which really hates hyper threading,
|
|
58
|
+
// and can easily get 50% slower because of it.
|
|
59
|
+
let results: number[] = [];
|
|
60
|
+
for (let j = 0; j < 10; j++) {
|
|
61
|
+
const measureCount = 1000 * 10;
|
|
62
|
+
let time = now();
|
|
63
|
+
for (let i = 0; i < measureCount; i++) {
|
|
64
|
+
getOwnTime("test", () => { }, () => { });
|
|
65
|
+
}
|
|
66
|
+
time = now() - time;
|
|
67
|
+
let overhead = time / measureCount;
|
|
68
|
+
results.push(overhead);
|
|
69
|
+
}
|
|
70
|
+
results.sort((a, b) => a - b);
|
|
71
|
+
addMeasureOverheadTime = results[results.length / 2];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// TIMING: About 60ns, of which 40ns is just now() calls.
|
|
75
|
+
// If async is closer to 300ns.
|
|
76
|
+
export function getOwnTime<T>(
|
|
77
|
+
name: string,
|
|
78
|
+
code: () => T,
|
|
79
|
+
onTime: (obj: OwnTimeObj) => void
|
|
80
|
+
): T {
|
|
81
|
+
let time = now();
|
|
82
|
+
let obj: OwnTimeObjInternal = {
|
|
83
|
+
name,
|
|
84
|
+
time: 0,
|
|
85
|
+
ownTime: 0,
|
|
86
|
+
firstStartTime: time,
|
|
87
|
+
lastStartTime: time,
|
|
88
|
+
parent: pendingCallTime,
|
|
89
|
+
child: undefined,
|
|
90
|
+
};
|
|
91
|
+
if (pendingCallTime) {
|
|
92
|
+
pendingCallTime.child = obj;
|
|
93
|
+
}
|
|
94
|
+
pendingCallTime = obj;
|
|
95
|
+
if (obj.parent) {
|
|
96
|
+
obj.parent.ownTime += obj.lastStartTime - obj.parent.lastStartTime;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function finish() {
|
|
100
|
+
let time = now();
|
|
101
|
+
obj.time = time - obj.firstStartTime;
|
|
102
|
+
if (pendingCallTime === obj) {
|
|
103
|
+
// Good case, all of our children call ended before us.
|
|
104
|
+
|
|
105
|
+
// End our own time calculation
|
|
106
|
+
obj.ownTime += time - obj.lastStartTime;
|
|
107
|
+
|
|
108
|
+
// Our parent is now the last open call
|
|
109
|
+
pendingCallTime = obj.parent;
|
|
110
|
+
if (pendingCallTime) {
|
|
111
|
+
// Resume our parent ownTime counting
|
|
112
|
+
pendingCallTime.lastStartTime = time;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (obj.child && obj.parent) {
|
|
116
|
+
obj.child.parent = obj.parent;
|
|
117
|
+
obj.parent.child = obj.child;
|
|
118
|
+
}
|
|
119
|
+
obj.parent = undefined;
|
|
120
|
+
obj.child = undefined;
|
|
121
|
+
|
|
122
|
+
obj.time += addMeasureOverheadTime;
|
|
123
|
+
obj.ownTime += addMeasureOverheadTime;
|
|
124
|
+
|
|
125
|
+
onTime(obj);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
let isAsync = false;
|
|
129
|
+
try {
|
|
130
|
+
let result = code();
|
|
131
|
+
if (result && typeof result === "object" && result instanceof Promise) {
|
|
132
|
+
isAsync = true;
|
|
133
|
+
return result.finally(() => {
|
|
134
|
+
finish();
|
|
135
|
+
}) as any;
|
|
136
|
+
}
|
|
137
|
+
return result;
|
|
138
|
+
} finally {
|
|
139
|
+
if (!isAsync) {
|
|
140
|
+
finish();
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
143
|
}
|