ic-mops 0.28.0 → 0.28.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.
Files changed (48) hide show
  1. package/.gitignore +2 -1
  2. package/LICENSE +21 -0
  3. package/commands/init.ts +16 -9
  4. package/declarations/main/main.did +36 -0
  5. package/declarations/main/main.did.d.ts +28 -0
  6. package/declarations/main/main.did.js +32 -0
  7. package/dist/bench/$USER_BENCH_FILE.mo +45 -0
  8. package/dist/bench/bench-canister.mo +57 -0
  9. package/dist/commands/bench/$USER_BENCH_FILE.mo +45 -0
  10. package/dist/commands/bench/bench/$USER_BENCH_FILE.mo +45 -0
  11. package/dist/commands/bench/bench/bench-canister.mo +57 -0
  12. package/dist/commands/bench/bench-canister.mo +85 -0
  13. package/dist/commands/bench/declarations/bench/bench.did.d.ts +6 -0
  14. package/dist/commands/bench/declarations/bench/bench.did.js +22 -0
  15. package/dist/commands/bench/declarations/bench/index.d.ts +2 -0
  16. package/dist/commands/bench/declarations/bench/index.js +30 -0
  17. package/dist/commands/bench/declarations/main/index.d.ts +2 -0
  18. package/dist/commands/bench/declarations/main/index.js +30 -0
  19. package/dist/commands/bench/declarations/main/main.did.d.ts +6 -0
  20. package/dist/commands/bench/declarations/main/main.did.js +242 -0
  21. package/dist/commands/bench/declarations/storage/index.d.ts +4 -0
  22. package/dist/commands/bench/declarations/storage/index.js +26 -0
  23. package/dist/commands/bench/declarations/storage/storage.did.d.ts +6 -0
  24. package/dist/commands/bench/declarations/storage/storage.did.js +34 -0
  25. package/dist/commands/bench/user-bench.mo +14 -0
  26. package/dist/commands/bench.d.ts +10 -0
  27. package/dist/commands/bench.js +214 -0
  28. package/dist/commands/init.js +16 -9
  29. package/dist/declarations/bench/bench.did +24 -0
  30. package/dist/declarations/bench/bench.did.d.ts +24 -0
  31. package/dist/declarations/bench/bench.did.js +24 -0
  32. package/dist/declarations/bench/index.d.ts +50 -0
  33. package/dist/declarations/bench/index.js +41 -0
  34. package/dist/declarations/main/main.did +36 -0
  35. package/dist/declarations/main/main.did.d.ts +28 -0
  36. package/dist/declarations/main/main.did.js +32 -0
  37. package/dist/helpers/get-dfx-version.d.ts +1 -0
  38. package/dist/helpers/get-dfx-version.js +9 -0
  39. package/dist/helpers/get-moc-path.d.ts +1 -0
  40. package/dist/helpers/get-moc-path.js +11 -0
  41. package/dist/helpers/get-moc-version.d.ts +1 -0
  42. package/dist/helpers/get-moc-version.js +7 -0
  43. package/dist/notify-installs.js +2 -2
  44. package/dist/package.json +1 -1
  45. package/mops.toml +7 -0
  46. package/notify-installs.ts +2 -2
  47. package/package.json +1 -1
  48. package/src/lib.mo +15 -0
@@ -0,0 +1,242 @@
1
+ export const idlFactory = ({ IDL }) => {
2
+ const TestsChanges = IDL.Record({
3
+ 'addedNames': IDL.Vec(IDL.Text),
4
+ 'removedNames': IDL.Vec(IDL.Text),
5
+ });
6
+ const DepChange = IDL.Record({
7
+ 'oldVersion': IDL.Text,
8
+ 'name': IDL.Text,
9
+ 'newVersion': IDL.Text,
10
+ });
11
+ const PackageChanges__1 = IDL.Record({
12
+ 'tests': TestsChanges,
13
+ 'deps': IDL.Vec(DepChange),
14
+ 'notes': IDL.Text,
15
+ 'devDeps': IDL.Vec(DepChange),
16
+ });
17
+ const PublishingId = IDL.Text;
18
+ const Err = IDL.Text;
19
+ const Result = IDL.Variant({ 'ok': IDL.Null, 'err': Err });
20
+ const Text = IDL.Text;
21
+ const PackageName__1 = IDL.Text;
22
+ const PackageVersion = IDL.Text;
23
+ const PackageId = IDL.Text;
24
+ const Time = IDL.Int;
25
+ const DownloadsSnapshot__1 = IDL.Record({
26
+ 'startTime': Time,
27
+ 'endTime': Time,
28
+ 'downloads': IDL.Nat,
29
+ });
30
+ const FileId = IDL.Text;
31
+ const Result_7 = IDL.Variant({ 'ok': IDL.Vec(FileId), 'err': Err });
32
+ const SemverPart = IDL.Variant({
33
+ 'major': IDL.Null,
34
+ 'minor': IDL.Null,
35
+ 'patch': IDL.Null,
36
+ });
37
+ const Result_6 = IDL.Variant({
38
+ 'ok': IDL.Vec(IDL.Tuple(PackageName__1, PackageVersion)),
39
+ 'err': Err,
40
+ });
41
+ const Result_5 = IDL.Variant({ 'ok': PackageVersion, 'err': Err });
42
+ const User = IDL.Record({
43
+ 'id': IDL.Principal,
44
+ 'emailVerified': IDL.Bool,
45
+ 'twitter': IDL.Text,
46
+ 'displayName': IDL.Text,
47
+ 'name': IDL.Text,
48
+ 'site': IDL.Text,
49
+ 'email': IDL.Text,
50
+ 'twitterVerified': IDL.Bool,
51
+ 'githubVerified': IDL.Bool,
52
+ 'github': IDL.Text,
53
+ });
54
+ const Script = IDL.Record({ 'value': IDL.Text, 'name': IDL.Text });
55
+ const PackageName = IDL.Text;
56
+ const DependencyV2 = IDL.Record({
57
+ 'name': PackageName,
58
+ 'repo': IDL.Text,
59
+ 'version': IDL.Text,
60
+ });
61
+ const PackageConfigV2__1 = IDL.Record({
62
+ 'dfx': IDL.Text,
63
+ 'moc': IDL.Text,
64
+ 'scripts': IDL.Vec(Script),
65
+ 'baseDir': IDL.Text,
66
+ 'documentation': IDL.Text,
67
+ 'name': PackageName,
68
+ 'homepage': IDL.Text,
69
+ 'description': IDL.Text,
70
+ 'version': IDL.Text,
71
+ 'keywords': IDL.Vec(IDL.Text),
72
+ 'donation': IDL.Text,
73
+ 'devDependencies': IDL.Vec(DependencyV2),
74
+ 'repository': IDL.Text,
75
+ 'dependencies': IDL.Vec(DependencyV2),
76
+ 'license': IDL.Text,
77
+ 'readme': IDL.Text,
78
+ });
79
+ const PackagePublication = IDL.Record({
80
+ 'storage': IDL.Principal,
81
+ 'time': Time,
82
+ 'user': IDL.Principal,
83
+ });
84
+ const PackageSummary = IDL.Record({
85
+ 'ownerInfo': User,
86
+ 'owner': IDL.Principal,
87
+ 'downloadsTotal': IDL.Nat,
88
+ 'downloadsInLast30Days': IDL.Nat,
89
+ 'downloadsInLast7Days': IDL.Nat,
90
+ 'config': PackageConfigV2__1,
91
+ 'publication': PackagePublication,
92
+ });
93
+ const PackageSummary__1 = IDL.Record({
94
+ 'ownerInfo': User,
95
+ 'owner': IDL.Principal,
96
+ 'downloadsTotal': IDL.Nat,
97
+ 'downloadsInLast30Days': IDL.Nat,
98
+ 'downloadsInLast7Days': IDL.Nat,
99
+ 'config': PackageConfigV2__1,
100
+ 'publication': PackagePublication,
101
+ });
102
+ const TestStats__1 = IDL.Record({
103
+ 'passedNames': IDL.Vec(IDL.Text),
104
+ 'passed': IDL.Nat,
105
+ });
106
+ const DownloadsSnapshot = IDL.Record({
107
+ 'startTime': Time,
108
+ 'endTime': Time,
109
+ 'downloads': IDL.Nat,
110
+ });
111
+ const PackageFileStatsPublic = IDL.Record({
112
+ 'sourceFiles': IDL.Nat,
113
+ 'sourceSize': IDL.Nat,
114
+ });
115
+ const PackageChanges = IDL.Record({
116
+ 'tests': TestsChanges,
117
+ 'deps': IDL.Vec(DepChange),
118
+ 'notes': IDL.Text,
119
+ 'devDeps': IDL.Vec(DepChange),
120
+ });
121
+ const PackageSummaryWithChanges__1 = IDL.Record({
122
+ 'ownerInfo': User,
123
+ 'owner': IDL.Principal,
124
+ 'downloadsTotal': IDL.Nat,
125
+ 'downloadsInLast30Days': IDL.Nat,
126
+ 'downloadsInLast7Days': IDL.Nat,
127
+ 'config': PackageConfigV2__1,
128
+ 'changes': PackageChanges,
129
+ 'publication': PackagePublication,
130
+ });
131
+ const PackageDetails = IDL.Record({
132
+ 'ownerInfo': User,
133
+ 'owner': IDL.Principal,
134
+ 'deps': IDL.Vec(PackageSummary__1),
135
+ 'testStats': TestStats__1,
136
+ 'downloadsTotal': IDL.Nat,
137
+ 'downloadsInLast30Days': IDL.Nat,
138
+ 'downloadTrend': IDL.Vec(DownloadsSnapshot),
139
+ 'fileStats': PackageFileStatsPublic,
140
+ 'versionHistory': IDL.Vec(PackageSummaryWithChanges__1),
141
+ 'dependents': IDL.Vec(PackageSummary__1),
142
+ 'devDeps': IDL.Vec(PackageSummary__1),
143
+ 'downloadsInLast7Days': IDL.Nat,
144
+ 'config': PackageConfigV2__1,
145
+ 'changes': PackageChanges,
146
+ 'publication': PackagePublication,
147
+ });
148
+ const Result_4 = IDL.Variant({ 'ok': PackageDetails, 'err': Err });
149
+ const PackageSummaryWithChanges = IDL.Record({
150
+ 'ownerInfo': User,
151
+ 'owner': IDL.Principal,
152
+ 'downloadsTotal': IDL.Nat,
153
+ 'downloadsInLast30Days': IDL.Nat,
154
+ 'downloadsInLast7Days': IDL.Nat,
155
+ 'config': PackageConfigV2__1,
156
+ 'changes': PackageChanges,
157
+ 'publication': PackagePublication,
158
+ });
159
+ const StorageId = IDL.Principal;
160
+ const StorageStats = IDL.Record({
161
+ 'fileCount': IDL.Nat,
162
+ 'cyclesBalance': IDL.Nat,
163
+ 'memorySize': IDL.Nat,
164
+ });
165
+ const User__1 = IDL.Record({
166
+ 'id': IDL.Principal,
167
+ 'emailVerified': IDL.Bool,
168
+ 'twitter': IDL.Text,
169
+ 'displayName': IDL.Text,
170
+ 'name': IDL.Text,
171
+ 'site': IDL.Text,
172
+ 'email': IDL.Text,
173
+ 'twitterVerified': IDL.Bool,
174
+ 'githubVerified': IDL.Bool,
175
+ 'github': IDL.Text,
176
+ });
177
+ const PageCount = IDL.Nat;
178
+ const Result_3 = IDL.Variant({ 'ok': IDL.Null, 'err': IDL.Text });
179
+ const Result_2 = IDL.Variant({ 'ok': FileId, 'err': Err });
180
+ const PackageConfigV2 = IDL.Record({
181
+ 'dfx': IDL.Text,
182
+ 'moc': IDL.Text,
183
+ 'scripts': IDL.Vec(Script),
184
+ 'baseDir': IDL.Text,
185
+ 'documentation': IDL.Text,
186
+ 'name': PackageName,
187
+ 'homepage': IDL.Text,
188
+ 'description': IDL.Text,
189
+ 'version': IDL.Text,
190
+ 'keywords': IDL.Vec(IDL.Text),
191
+ 'donation': IDL.Text,
192
+ 'devDependencies': IDL.Vec(DependencyV2),
193
+ 'repository': IDL.Text,
194
+ 'dependencies': IDL.Vec(DependencyV2),
195
+ 'license': IDL.Text,
196
+ 'readme': IDL.Text,
197
+ });
198
+ const PublishingErr = IDL.Text;
199
+ const Result_1 = IDL.Variant({ 'ok': PublishingId, 'err': PublishingErr });
200
+ const TestStats = IDL.Record({
201
+ 'passedNames': IDL.Vec(IDL.Text),
202
+ 'passed': IDL.Nat,
203
+ });
204
+ return IDL.Service({
205
+ 'backup': IDL.Func([], [], []),
206
+ 'claimAirdrop': IDL.Func([IDL.Principal], [IDL.Text], []),
207
+ 'diff': IDL.Func([IDL.Text, IDL.Text], [PackageChanges__1], ['query']),
208
+ 'finishPublish': IDL.Func([PublishingId], [Result], []),
209
+ 'getAirdropAmount': IDL.Func([], [IDL.Nat], ['query']),
210
+ 'getAirdropAmountAll': IDL.Func([], [IDL.Nat], ['query']),
211
+ 'getApiVersion': IDL.Func([], [Text], ['query']),
212
+ 'getBackupCanisterId': IDL.Func([], [IDL.Principal], ['query']),
213
+ 'getDefaultPackages': IDL.Func([IDL.Text], [IDL.Vec(IDL.Tuple(PackageName__1, PackageVersion))], ['query']),
214
+ 'getDownloadTrendByPackageId': IDL.Func([PackageId], [IDL.Vec(DownloadsSnapshot__1)], ['query']),
215
+ 'getDownloadTrendByPackageName': IDL.Func([PackageName__1], [IDL.Vec(DownloadsSnapshot__1)], ['query']),
216
+ 'getFileIds': IDL.Func([PackageName__1, PackageVersion], [Result_7], ['query']),
217
+ 'getHighestSemverBatch': IDL.Func([IDL.Vec(IDL.Tuple(PackageName__1, PackageVersion, SemverPart))], [Result_6], ['query']),
218
+ 'getHighestVersion': IDL.Func([PackageName__1], [Result_5], ['query']),
219
+ 'getMostDownloadedPackages': IDL.Func([], [IDL.Vec(PackageSummary)], ['query']),
220
+ 'getMostDownloadedPackagesIn7Days': IDL.Func([], [IDL.Vec(PackageSummary)], ['query']),
221
+ 'getNewPackages': IDL.Func([], [IDL.Vec(PackageSummary)], ['query']),
222
+ 'getPackageDetails': IDL.Func([PackageName__1, PackageVersion], [Result_4], ['query']),
223
+ 'getPackagesByCategory': IDL.Func([], [IDL.Vec(IDL.Tuple(IDL.Text, IDL.Vec(PackageSummary)))], ['query']),
224
+ 'getRecentlyUpdatedPackages': IDL.Func([], [IDL.Vec(PackageSummaryWithChanges)], ['query']),
225
+ 'getStoragesStats': IDL.Func([], [IDL.Vec(IDL.Tuple(StorageId, StorageStats))], ['query']),
226
+ 'getTotalDownloads': IDL.Func([], [IDL.Nat], ['query']),
227
+ 'getTotalPackages': IDL.Func([], [IDL.Nat], ['query']),
228
+ 'getUser': IDL.Func([IDL.Principal], [IDL.Opt(User__1)], ['query']),
229
+ 'notifyInstall': IDL.Func([PackageName__1, PackageVersion], [], ['oneway']),
230
+ 'notifyInstalls': IDL.Func([IDL.Vec(IDL.Tuple(PackageName__1, PackageVersion))], [], ['oneway']),
231
+ 'restore': IDL.Func([IDL.Nat, IDL.Nat], [], []),
232
+ 'search': IDL.Func([Text, IDL.Opt(IDL.Nat), IDL.Opt(IDL.Nat)], [IDL.Vec(PackageSummary), PageCount], ['query']),
233
+ 'setUserProp': IDL.Func([IDL.Text, IDL.Text], [Result_3], []),
234
+ 'startFileUpload': IDL.Func([PublishingId, Text, IDL.Nat, IDL.Vec(IDL.Nat8)], [Result_2], []),
235
+ 'startPublish': IDL.Func([PackageConfigV2], [Result_1], []),
236
+ 'takeAirdropSnapshot': IDL.Func([], [], ['oneway']),
237
+ 'uploadFileChunk': IDL.Func([PublishingId, FileId, IDL.Nat, IDL.Vec(IDL.Nat8)], [Result], []),
238
+ 'uploadNotes': IDL.Func([PublishingId, IDL.Text], [Result], []),
239
+ 'uploadTestStats': IDL.Func([PublishingId, TestStats], [Result], []),
240
+ });
241
+ };
242
+ export const init = ({ IDL }) => { return []; };
@@ -0,0 +1,4 @@
1
+ export function createActor(canisterId: string | import("@dfinity/principal").Principal, options?: {
2
+ agentOptions?: import("@dfinity/agent").HttpAgentOptions;
3
+ actorOptions?: import("@dfinity/agent").ActorConfig;
4
+ } | undefined): import("@dfinity/agent").ActorSubclass<import("./storage.did.js")._SERVICE>;
@@ -0,0 +1,26 @@
1
+ import { Actor, HttpAgent } from "@dfinity/agent";
2
+ // Imports and re-exports candid interface
3
+ import { idlFactory } from './storage.did.js';
4
+ export { idlFactory } from './storage.did.js';
5
+ /**
6
+ *
7
+ * @param {string | import("@dfinity/principal").Principal} canisterId Canister ID of Agent
8
+ * @param {{agentOptions?: import("@dfinity/agent").HttpAgentOptions; actorOptions?: import("@dfinity/agent").ActorConfig}} [options]
9
+ * @return {import("@dfinity/agent").ActorSubclass<import("./storage.did.js")._SERVICE>}
10
+ */
11
+ export const createActor = (canisterId, options) => {
12
+ const agent = new HttpAgent({ ...options?.agentOptions });
13
+ // Fetch root key for certificate validation during development
14
+ if (process.env.NODE_ENV !== "production") {
15
+ agent.fetchRootKey().catch(err => {
16
+ console.warn("Unable to fetch root key. Check to ensure that your local replica is running");
17
+ console.error(err);
18
+ });
19
+ }
20
+ // Creates an actor with using the candid interface and the HttpAgent
21
+ return Actor.createActor(idlFactory, {
22
+ agent,
23
+ canisterId,
24
+ ...options?.actorOptions,
25
+ });
26
+ };
@@ -0,0 +1,6 @@
1
+ export function idlFactory({ IDL }: {
2
+ IDL: any;
3
+ }): any;
4
+ export function init({ IDL }: {
5
+ IDL: any;
6
+ }): never[];
@@ -0,0 +1,34 @@
1
+ export const idlFactory = ({ IDL }) => {
2
+ const FileId = IDL.Text;
3
+ const Chunk = IDL.Vec(IDL.Nat8);
4
+ const Err = IDL.Text;
5
+ const Result_2 = IDL.Variant({ 'ok': Chunk, 'err': Err });
6
+ const FileId__1 = IDL.Text;
7
+ const FileMeta = IDL.Record({
8
+ 'id': FileId__1,
9
+ 'owners': IDL.Vec(IDL.Principal),
10
+ 'path': IDL.Text,
11
+ 'chunkCount': IDL.Nat,
12
+ });
13
+ const Result_1 = IDL.Variant({ 'ok': FileMeta, 'err': Err });
14
+ const StorageStats = IDL.Record({
15
+ 'fileCount': IDL.Nat,
16
+ 'cyclesBalance': IDL.Nat,
17
+ 'memorySize': IDL.Nat,
18
+ });
19
+ const Result = IDL.Variant({ 'ok': IDL.Null, 'err': Err });
20
+ const Storage = IDL.Service({
21
+ 'acceptCycles': IDL.Func([], [], []),
22
+ 'deleteFile': IDL.Func([FileId], [], []),
23
+ 'downloadChunk': IDL.Func([FileId, IDL.Nat], [Result_2], ['query']),
24
+ 'finishUpload': IDL.Func([FileId], [], []),
25
+ 'getFileIdsRange': IDL.Func([IDL.Nat, IDL.Nat], [IDL.Vec(FileId)], ['query']),
26
+ 'getFileMeta': IDL.Func([FileId], [Result_1], ['query']),
27
+ 'getStats': IDL.Func([], [StorageStats], ['query']),
28
+ 'startUpload': IDL.Func([FileMeta], [Result], []),
29
+ 'updateFileOwners': IDL.Func([FileId, IDL.Vec(IDL.Principal)], [], []),
30
+ 'uploadChunk': IDL.Func([FileId, IDL.Nat, Chunk], [], []),
31
+ });
32
+ return Storage;
33
+ };
34
+ export const init = ({ IDL }) => { return []; };
@@ -0,0 +1,14 @@
1
+ import Nat "mo:base/Nat";
2
+ import Iter "mo:base/Iter";
3
+ import Buffer "mo:base/Buffer";
4
+ import Vector "mo:vector/Class";
5
+ import Bench "mo:bench";
6
+
7
+ // placeholder file that will be replaced with the *.bench.mo file
8
+ module {
9
+ public func init() : Bench.Bench {
10
+ let bench = Bench.Bench();
11
+ // benchmark code goes here...
12
+ bench;
13
+ };
14
+ };
@@ -0,0 +1,10 @@
1
+ type BenchOptions = {
2
+ verbose?: boolean;
3
+ save?: boolean;
4
+ compare?: boolean;
5
+ dfx?: string;
6
+ moc?: string;
7
+ gc?: 'copying' | 'compacting' | 'generational' | 'incremental' | 'none';
8
+ };
9
+ export declare function bench(filter?: string, options?: BenchOptions): Promise<boolean>;
10
+ export {};
@@ -0,0 +1,214 @@
1
+ import { execSync } from 'node:child_process';
2
+ import path from 'node:path';
3
+ import fs from 'node:fs';
4
+ // import os from 'node:os';
5
+ import chalk from 'chalk';
6
+ import { globSync } from 'glob';
7
+ import { markdownTable } from 'markdown-table';
8
+ import logUpdate from 'log-update';
9
+ import { getRootDir } from '../mops.js';
10
+ import { parallel } from '../parallel.js';
11
+ import { createActor } from '../declarations/bench/index.js';
12
+ import { absToRel } from './test/utils.js';
13
+ import { getMocVersion } from '../helpers/get-moc-version.js';
14
+ import { getDfxVersion } from '../helpers/get-dfx-version.js';
15
+ let ignore = [
16
+ '**/node_modules/**',
17
+ '**/.mops/**',
18
+ '**/.vessel/**',
19
+ '**/.git/**',
20
+ ];
21
+ let globConfig = {
22
+ nocase: true,
23
+ ignore: ignore,
24
+ };
25
+ export async function bench(filter = '', options = {}) {
26
+ let rootDir = getRootDir();
27
+ let globStr = '**/bench?(mark)/**/*.bench.mo';
28
+ if (filter) {
29
+ globStr = `**/bench?(mark)/**/*${filter}*.mo`;
30
+ }
31
+ let files = globSync(path.join(rootDir, globStr), globConfig);
32
+ if (!files.length) {
33
+ if (filter) {
34
+ console.log(`No benchmark files found for filter '${filter}'`);
35
+ return false;
36
+ }
37
+ console.log('No *.bench.mo files found');
38
+ console.log('Put your benchmark files in \'bench\' directory in *.bench.mo files');
39
+ return false;
40
+ }
41
+ files.sort();
42
+ let benchDir = `${getRootDir()}/.mops/.bench/`;
43
+ fs.rmSync(benchDir, { recursive: true, force: true });
44
+ fs.mkdirSync(benchDir, { recursive: true });
45
+ console.log('Benchmark files:');
46
+ for (let file of files) {
47
+ console.log(chalk.gray(`• ${absToRel(file)}`));
48
+ }
49
+ console.log('');
50
+ console.log('='.repeat(50));
51
+ console.log('Starting dfx replica...');
52
+ startDfx(options.verbose);
53
+ let resultsByName = new Map();
54
+ // await parallel(os.cpus().length, files, async (file: string) => {
55
+ await parallel(1, files, async (file) => {
56
+ console.log('\n' + '—'.repeat(50));
57
+ console.log(`\nRunning ${chalk.gray(absToRel(file))}...`);
58
+ console.log('');
59
+ try {
60
+ let { schema, results } = await runBenchFile(file, options);
61
+ resultsByName.set(schema.name || absToRel(file), results);
62
+ }
63
+ catch (err) {
64
+ console.error('Unexpected error. Stopping dfx replica...');
65
+ stopDfx(options.verbose);
66
+ throw err;
67
+ }
68
+ });
69
+ if (options.save) {
70
+ console.log('Saving results to mops.bench.json...');
71
+ let json = {
72
+ version: 1,
73
+ moc: options.moc || getMocVersion(),
74
+ dfx: options.dfx || getDfxVersion(),
75
+ gc: options.gc || 'incremental',
76
+ results: {},
77
+ };
78
+ resultsByName.forEach((results, name) => {
79
+ json.results[name] = Array.from(results.entries());
80
+ });
81
+ fs.writeFileSync(path.join(rootDir, 'mops.bench.json'), JSON.stringify(json, (_, val) => {
82
+ if (typeof val === 'bigint') {
83
+ return Number(val);
84
+ }
85
+ else {
86
+ return val;
87
+ }
88
+ }, 2));
89
+ }
90
+ console.log('Stopping dfx replica...');
91
+ stopDfx(options.verbose);
92
+ fs.rmSync(benchDir, { recursive: true, force: true });
93
+ return true;
94
+ }
95
+ function dfxJson(canisterName) {
96
+ return {
97
+ version: 1,
98
+ canisters: {
99
+ [canisterName]: {
100
+ type: 'motoko',
101
+ main: 'canister.mo',
102
+ args: '--force-gc --incremental-gc',
103
+ }
104
+ },
105
+ defaults: {
106
+ build: {
107
+ packtool: 'mops sources',
108
+ },
109
+ },
110
+ networks: {
111
+ local: {
112
+ type: 'ephemeral',
113
+ bind: '127.0.0.1:4947',
114
+ },
115
+ },
116
+ };
117
+ }
118
+ function startDfx(verbose = false) {
119
+ stopDfx(verbose);
120
+ let dir = path.join(getRootDir(), '.mops/.bench');
121
+ fs.writeFileSync(path.join(dir, 'dfx.json'), JSON.stringify(dfxJson(''), null, 2));
122
+ execSync('dfx start --background --clean', { cwd: dir, stdio: ['inherit', verbose ? 'inherit' : 'ignore', 'inherit'] });
123
+ }
124
+ function stopDfx(verbose = false) {
125
+ let dir = path.join(getRootDir(), '.mops/.bench');
126
+ execSync('dfx stop', { cwd: dir, stdio: ['pipe', verbose ? 'inherit' : 'ignore', 'pipe'] });
127
+ }
128
+ async function runBenchFile(file, options = {}) {
129
+ let rootDir = getRootDir();
130
+ let tempDir = path.join(rootDir, '.mops/.bench/', path.parse(file).name);
131
+ fs.mkdirSync(tempDir, { recursive: true });
132
+ let canisterName = Date.now().toString(36);
133
+ // prepare temp files
134
+ fs.writeFileSync(path.join(tempDir, 'dfx.json'), JSON.stringify(dfxJson(canisterName), null, 2));
135
+ fs.cpSync(new URL('./bench/bench-canister.mo', import.meta.url), path.join(tempDir, 'canister.mo'));
136
+ fs.cpSync(file, path.join(tempDir, 'user-bench.mo'));
137
+ // deploy canister
138
+ execSync(`dfx deploy ${canisterName} --mode reinstall --yes --identity anonymous`, { cwd: tempDir, stdio: options.verbose ? 'pipe' : ['pipe', 'ignore', 'pipe'] });
139
+ let canisterId = execSync(`dfx canister id ${canisterName}`, { cwd: tempDir }).toString().trim();
140
+ let actor = await createActor(canisterId, {
141
+ agentOptions: {
142
+ host: 'http://127.0.0.1:4947',
143
+ },
144
+ });
145
+ let schema = await actor.init();
146
+ // load previous results
147
+ let prevResults;
148
+ if (options.compare) {
149
+ let prevResultsJson = JSON.parse(fs.readFileSync(path.join(rootDir, 'mops.bench.json')).toString());
150
+ if (prevResultsJson.results[schema.name]) {
151
+ prevResults = new Map(prevResultsJson.results[schema.name]);
152
+ }
153
+ else {
154
+ console.log(chalk.yellow(`No previous results found for benchmark with name "${schema.name}"`));
155
+ }
156
+ }
157
+ let results = new Map();
158
+ let formatNumber = (n) => {
159
+ return n.toLocaleString('en-US').replaceAll(',', '_');
160
+ };
161
+ let getTable = (prop) => {
162
+ let resArr = [['', ...schema.cols]];
163
+ for (let [_rowIndex, row] of schema.rows.entries()) {
164
+ let curRow = [row];
165
+ for (let [_colIndex, col] of schema.cols.entries()) {
166
+ let res = results.get(`${row}:${col}`);
167
+ if (res) {
168
+ // compare with previous results
169
+ let diff = '';
170
+ if (options.compare && prevResults) {
171
+ let prevRes = prevResults.get(`${row}:${col}`);
172
+ if (prevRes) {
173
+ let percent = (Number(res[prop]) - Number(prevRes[prop])) / Number(prevRes[prop]) * 100;
174
+ let sign = percent > 0 ? '+' : '';
175
+ let percentText = percent == 0 ? '0%' : sign + percent.toFixed(2) + '%';
176
+ // diff = ' (' + (percent > 0 ? chalk.red(percentText) : chalk.green(percentText)) + ')'; // alignment is broken
177
+ diff = ' (' + percentText + ')';
178
+ }
179
+ else {
180
+ diff = chalk.yellow(' (no previous results)');
181
+ }
182
+ }
183
+ // add to table
184
+ curRow.push(formatNumber(res[prop]) + diff);
185
+ }
186
+ else {
187
+ curRow.push('');
188
+ }
189
+ }
190
+ resArr.push(curRow);
191
+ }
192
+ return markdownTable(resArr, { align: ['l', ...'r'.repeat(schema.cols.length)] });
193
+ };
194
+ let printResults = () => {
195
+ logUpdate(`
196
+ \n${chalk.bold(schema.name)}
197
+ ${schema.description ? '\n' + chalk.gray(schema.description) : ''}
198
+ \n\n${chalk.blue('Instructions')}\n\n${getTable('instructions')}
199
+ \n\n${chalk.blue('Heap')}\n\n${getTable('rts_heap_size')}
200
+ `);
201
+ };
202
+ printResults();
203
+ // run all cells
204
+ for (let [rowIndex, row] of schema.rows.entries()) {
205
+ for (let [colIndex, col] of schema.cols.entries()) {
206
+ // let res = await actor.runCellQuery(BigInt(rowIndex), BigInt(colIndex));
207
+ let res = await actor.runCellUpdate(BigInt(rowIndex), BigInt(colIndex));
208
+ results.set(`${row}:${col}`, res);
209
+ printResults();
210
+ }
211
+ }
212
+ logUpdate.done();
213
+ return { schema, results };
214
+ }
@@ -146,15 +146,22 @@ async function applyInit({ type, config, setupWorkflow, addTest, copyrightOwner
146
146
  let dfxJsonData;
147
147
  if (existsSync(dfxJson)) {
148
148
  let dfxJsonText = readFileSync(dfxJson).toString();
149
- dfxJsonData = JSON.parse(dfxJsonText);
150
- console.log('Setting packtool in dfx.json...');
151
- dfxJsonData.defaults = dfxJsonData.defaults || {};
152
- dfxJsonData.defaults.build = dfxJsonData.defaults.build || {};
153
- if (dfxJsonData.defaults.build.packtool !== 'mops sources') {
154
- dfxJsonData.defaults.build.packtool = 'mops sources';
155
- let indent = dfxJsonText.match(/([ \t]+)"/)?.[1] || ' ';
156
- writeFileSync(path.join(process.cwd(), 'dfx.json'), JSON.stringify(dfxJsonData, null, indent));
157
- console.log(chalk.green('packtool set to "mops sources"'));
149
+ try {
150
+ dfxJsonData = JSON.parse(dfxJsonText);
151
+ }
152
+ catch (err) {
153
+ console.log(chalk.yellow('Failed to parse dfx.json'));
154
+ }
155
+ if (dfxJsonData) {
156
+ console.log('Setting packtool in dfx.json...');
157
+ dfxJsonData.defaults = dfxJsonData.defaults || {};
158
+ dfxJsonData.defaults.build = dfxJsonData.defaults.build || {};
159
+ if (dfxJsonData.defaults.build.packtool !== 'mops sources') {
160
+ dfxJsonData.defaults.build.packtool = 'mops sources';
161
+ let indent = dfxJsonText.match(/([ \t]+)"/)?.[1] || ' ';
162
+ writeFileSync(path.join(process.cwd(), 'dfx.json'), JSON.stringify(dfxJsonData, null, indent));
163
+ console.log(chalk.green('packtool set to "mops sources"'));
164
+ }
158
165
  }
159
166
  }
160
167
  // get default packages
@@ -0,0 +1,24 @@
1
+ type anon_class_10_1 =
2
+ service {
3
+ getStats: () -> (BenchResult) query;
4
+ init: () -> (BenchSchema);
5
+ runCellQuery: (nat, nat) -> (BenchResult) query;
6
+ runCellUpdate: (nat, nat) -> (BenchResult);
7
+ };
8
+ type BenchSchema =
9
+ record {
10
+ cols: vec text;
11
+ description: text;
12
+ name: text;
13
+ rows: vec text;
14
+ };
15
+ type BenchResult =
16
+ record {
17
+ instructions: int;
18
+ rts_collector_instructions: int;
19
+ rts_heap_size: int;
20
+ rts_memory_size: int;
21
+ rts_mutator_instructions: int;
22
+ rts_total_allocation: int;
23
+ };
24
+ service : () -> anon_class_10_1
@@ -0,0 +1,24 @@
1
+ import type { Principal } from '@dfinity/principal';
2
+ import type { ActorMethod } from '@dfinity/agent';
3
+
4
+ export interface BenchResult {
5
+ 'instructions' : bigint,
6
+ 'rts_memory_size' : bigint,
7
+ 'rts_total_allocation' : bigint,
8
+ 'rts_collector_instructions' : bigint,
9
+ 'rts_mutator_instructions' : bigint,
10
+ 'rts_heap_size' : bigint,
11
+ }
12
+ export interface BenchSchema {
13
+ 'cols' : Array<string>,
14
+ 'name' : string,
15
+ 'rows' : Array<string>,
16
+ 'description' : string,
17
+ }
18
+ export interface anon_class_10_1 {
19
+ 'getStats' : ActorMethod<[], BenchResult>,
20
+ 'init' : ActorMethod<[], BenchSchema>,
21
+ 'runCellQuery' : ActorMethod<[bigint, bigint], BenchResult>,
22
+ 'runCellUpdate' : ActorMethod<[bigint, bigint], BenchResult>,
23
+ }
24
+ export interface _SERVICE extends anon_class_10_1 {}
@@ -0,0 +1,24 @@
1
+ export const idlFactory = ({ IDL }) => {
2
+ const BenchResult = IDL.Record({
3
+ 'instructions' : IDL.Int,
4
+ 'rts_memory_size' : IDL.Int,
5
+ 'rts_total_allocation' : IDL.Int,
6
+ 'rts_collector_instructions' : IDL.Int,
7
+ 'rts_mutator_instructions' : IDL.Int,
8
+ 'rts_heap_size' : IDL.Int,
9
+ });
10
+ const BenchSchema = IDL.Record({
11
+ 'cols' : IDL.Vec(IDL.Text),
12
+ 'name' : IDL.Text,
13
+ 'rows' : IDL.Vec(IDL.Text),
14
+ 'description' : IDL.Text,
15
+ });
16
+ const anon_class_10_1 = IDL.Service({
17
+ 'getStats' : IDL.Func([], [BenchResult], ['query']),
18
+ 'init' : IDL.Func([], [BenchSchema], []),
19
+ 'runCellQuery' : IDL.Func([IDL.Nat, IDL.Nat], [BenchResult], ['query']),
20
+ 'runCellUpdate' : IDL.Func([IDL.Nat, IDL.Nat], [BenchResult], []),
21
+ });
22
+ return anon_class_10_1;
23
+ };
24
+ export const init = ({ IDL }) => { return []; };