aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorJeremy Rifkin <51220084+jeremy-rifkin@users.noreply.github.com>2023-06-11 19:10:30 -0400
committerGitHub <noreply@github.com>2023-06-11 19:10:30 -0400
commit60ce06b02f8ece8bbbecb26cb69f9ad45e75aa16 (patch)
treea10d1bd160dd06f5b191adb1ad5cd12403790d48 /lib
parent910d69f233414ebfb0b680e012f44ced14505016 (diff)
downloadcompiler-explorer-gh-7689.tar.gz
compiler-explorer-gh-7689.zip
Improve cache handling on the frontend, cache executions on the backend, and improve controls on the exec pane (#5111)gh-7689
Diffstat (limited to 'lib')
-rw-r--r--lib/base-compiler.ts69
-rw-r--r--lib/compilers/java.ts3
-rw-r--r--lib/compilers/kotlin.ts3
-rw-r--r--lib/compilers/win32-mingw-clang.ts11
-rw-r--r--lib/compilers/win32-mingw-gcc.ts11
-rw-r--r--lib/handlers/compile.interfaces.ts6
-rw-r--r--lib/handlers/compile.ts25
-rw-r--r--lib/llvm-ir.ts4
8 files changed, 94 insertions, 38 deletions
diff --git a/lib/base-compiler.ts b/lib/base-compiler.ts
index d72adeda6..77aff9750 100644
--- a/lib/base-compiler.ts
+++ b/lib/base-compiler.ts
@@ -29,15 +29,18 @@ import * as PromClient from 'prom-client';
import temp from 'temp';
import _ from 'underscore';
-import type {
+import {
BufferOkFunc,
BuildResult,
BuildStep,
+ BypassCache,
CompilationCacheKey,
CompilationInfo,
CompilationResult,
CustomInputForTool,
ExecutionOptions,
+ bypassCompilationCache,
+ bypassExecutionCache,
} from '../types/compilation/compilation.interfaces.js';
import type {
LLVMOptPipelineBackendOptions,
@@ -489,7 +492,7 @@ export class BaseCompiler implements ICompiler {
maxSize: number,
intelAsm,
demangle,
- staticReloc: boolean,
+ staticReloc: boolean | undefined,
dynamicReloc: boolean,
filters: ParseFiltersAndOutputOptions,
) {
@@ -1718,11 +1721,13 @@ export class BaseCompiler implements ICompiler {
};
}
- async getOrBuildExecutable(key) {
+ async getOrBuildExecutable(key, bypassCache: BypassCache) {
const dirPath = await this.newTempDir();
- const buildResults = await this.loadPackageWithExecutable(key, dirPath);
- if (buildResults) return buildResults;
+ if (!bypassCompilationCache(bypassCache)) {
+ const buildResults = await this.loadPackageWithExecutable(key, dirPath);
+ if (buildResults) return buildResults;
+ }
let compilationResult;
try {
@@ -1843,9 +1848,11 @@ export class BaseCompiler implements ICompiler {
};
}
- async handleExecution(key, executeParameters): Promise<CompilationResult> {
- if (this.compiler.interpreted) return this.handleInterpreting(key, executeParameters);
- const buildResult = await this.getOrBuildExecutable(key);
+ async doExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
+ if (this.compiler.interpreted) {
+ return this.handleInterpreting(key, executeParameters);
+ }
+ const buildResult = await this.getOrBuildExecutable(key, bypassCache);
if (buildResult.code !== 0) {
return {
code: -1,
@@ -1892,6 +1899,23 @@ export class BaseCompiler implements ICompiler {
};
}
+ async handleExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
+ // stringify now so shallow copying isn't a problem, I think the executeParameters get modified
+ const execKey = JSON.stringify({key, executeParameters});
+ if (!bypassExecutionCache(bypassCache)) {
+ const cacheResult = await this.env.cacheGet(execKey as any);
+ if (cacheResult) {
+ return cacheResult;
+ }
+ }
+
+ const result = await this.doExecution(key, executeParameters, bypassCache);
+ if (!bypassExecutionCache(bypassCache)) {
+ await this.env.cachePut(execKey, result, undefined);
+ }
+ return result;
+ }
+
getCacheKey(source, options, backendOptions, filters, tools, libraries, files) {
return {compiler: this.compiler, source, options, backendOptions, filters, tools, libraries, files};
}
@@ -2262,7 +2286,7 @@ export class BaseCompiler implements ICompiler {
}
}
- async cmake(files, key) {
+ async cmake(files, key, bypassCache: BypassCache) {
// key = {source, options, backendOptions, filters, bypassCache, tools, executionParameters, libraries};
if (!this.compiler.supportsBinary) {
@@ -2300,7 +2324,9 @@ export class BaseCompiler implements ICompiler {
const outputFilename = this.getExecutableFilename(path.join(dirPath, 'build'), this.outputFilebase, key);
- let fullResult = await this.loadPackageWithExecutable(cacheKey, dirPath);
+ let fullResult = !bypassExecutionCache(bypassCache)
+ ? await this.loadPackageWithExecutable(cacheKey, dirPath)
+ : null;
if (fullResult) {
fullResult.fetchedFromCache = true;
@@ -2421,6 +2447,7 @@ export class BaseCompiler implements ICompiler {
cacheKey.filters,
libsAndOptions.options,
optOutput,
+ bypassCache,
path.join(dirPath, 'build'),
);
@@ -2469,7 +2496,17 @@ export class BaseCompiler implements ICompiler {
}
}
- async compile(source, options, backendOptions, filters, bypassCache, tools, executionParameters, libraries, files) {
+ async compile(
+ source,
+ options,
+ backendOptions,
+ filters,
+ bypassCache: BypassCache,
+ tools,
+ executionParameters,
+ libraries,
+ files,
+ ) {
const optionsError = this.checkOptions(options);
if (optionsError) throw optionsError;
const sourceError = this.checkSource(source);
@@ -2494,7 +2531,7 @@ export class BaseCompiler implements ICompiler {
filters = Object.assign({}, filters);
filters.execute = false;
- if (!bypassCache) {
+ if (!bypassCompilationCache(bypassCache)) {
const cacheRetreiveTimeStart = process.hrtime.bigint();
// TODO: We should be able to eliminate this any cast. `key` should be cacheable (if it's not that's a big
// problem) Because key coantains a CompilerInfo which contains a function member it can't be assigned to a
@@ -2512,7 +2549,7 @@ export class BaseCompiler implements ICompiler {
result.execResult = await this.env.enqueue(async () => {
const start = performance.now();
executionQueueTimeHistogram.observe((start - queueTime) / 1000);
- const res = await this.handleExecution(key, executeParameters);
+ const res = await this.handleExecution(key, executeParameters, bypassCache);
executionTimeHistogram.observe((performance.now() - start) / 1000);
return res;
});
@@ -2532,7 +2569,7 @@ export class BaseCompiler implements ICompiler {
source = this.preProcess(source, filters);
if (backendOptions.executorRequest) {
- const execResult = await this.handleExecution(key, executeParameters);
+ const execResult = await this.handleExecution(key, executeParameters, bypassCache);
if (execResult && execResult.buildResult) {
this.doTempfolderCleanup(execResult.buildResult);
}
@@ -2570,6 +2607,7 @@ export class BaseCompiler implements ICompiler {
filters,
options,
optOutput,
+ bypassCache,
);
})();
compilationTimeHistogram.observe((performance.now() - start) / 1000);
@@ -2587,10 +2625,11 @@ export class BaseCompiler implements ICompiler {
filters,
options,
optOutput,
+ bypassCache: BypassCache,
customBuildPath?,
) {
// Start the execution as soon as we can, but only await it at the end.
- const execPromise = doExecute ? this.handleExecution(key, executeParameters) : null;
+ const execPromise = doExecute ? this.handleExecution(key, executeParameters, bypassCache) : null;
if (result.hasOptOutput) {
delete result.optPath;
diff --git a/lib/compilers/java.ts b/lib/compilers/java.ts
index 320469f6e..c01940c57 100644
--- a/lib/compilers/java.ts
+++ b/lib/compilers/java.ts
@@ -35,6 +35,7 @@ import {logger} from '../logger.js';
import * as utils from '../utils.js';
import {JavaParser} from './argument-parsers.js';
+import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
export class JavaCompiler extends BaseCompiler {
static get key() {
@@ -128,7 +129,7 @@ export class JavaCompiler extends BaseCompiler {
}
override async handleInterpreting(key, executeParameters) {
- const compileResult = await this.getOrBuildExecutable(key);
+ const compileResult = await this.getOrBuildExecutable(key, BypassCache.None);
if (compileResult.code === 0) {
executeParameters.args = [
'-Xss136K', // Reduce thread stack size
diff --git a/lib/compilers/kotlin.ts b/lib/compilers/kotlin.ts
index 0b5cce585..9b1bab103 100644
--- a/lib/compilers/kotlin.ts
+++ b/lib/compilers/kotlin.ts
@@ -22,6 +22,7 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
+import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
import type {PreliminaryCompilerInfo} from '../../types/compiler.interfaces.js';
import type {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
@@ -98,7 +99,7 @@ export class KotlinCompiler extends JavaCompiler {
...key,
options: ['-include-runtime', '-d', 'example.jar'],
};
- const compileResult = await this.getOrBuildExecutable(alteredKey);
+ const compileResult = await this.getOrBuildExecutable(alteredKey, BypassCache.None);
executeParameters.args = [
'-Xss136K', // Reduce thread stack size
'-XX:CICompilerCount=2', // Reduce JIT compilation threads. 2 is minimum
diff --git a/lib/compilers/win32-mingw-clang.ts b/lib/compilers/win32-mingw-clang.ts
index 83c98c52e..47a6159a8 100644
--- a/lib/compilers/win32-mingw-clang.ts
+++ b/lib/compilers/win32-mingw-clang.ts
@@ -24,7 +24,12 @@
import path from 'path';
-import {BuildResult, CompilationResult, ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
+import {
+ BuildResult,
+ BypassCache,
+ CompilationResult,
+ ExecutionOptions,
+} from '../../types/compilation/compilation.interfaces.js';
import {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
import {copyNeededDlls} from '../win-utils.js';
@@ -102,8 +107,8 @@ export class Win32MingWClang extends ClangCompiler {
return result;
}
- override async handleExecution(key, executeParameters): Promise<CompilationResult> {
+ override async handleExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
const execOptions = this.getDefaultExecOptions();
- return super.handleExecution(key, {...executeParameters, env: execOptions.env});
+ return super.handleExecution(key, {...executeParameters, env: execOptions.env}, bypassCache);
}
}
diff --git a/lib/compilers/win32-mingw-gcc.ts b/lib/compilers/win32-mingw-gcc.ts
index 4e3106bc5..04b43f985 100644
--- a/lib/compilers/win32-mingw-gcc.ts
+++ b/lib/compilers/win32-mingw-gcc.ts
@@ -24,7 +24,12 @@
import path from 'path';
-import {BuildResult, CompilationResult, ExecutionOptions} from '../../types/compilation/compilation.interfaces.js';
+import {
+ BuildResult,
+ BypassCache,
+ CompilationResult,
+ ExecutionOptions,
+} from '../../types/compilation/compilation.interfaces.js';
import {ParseFiltersAndOutputOptions} from '../../types/features/filters.interfaces.js';
import {copyNeededDlls} from '../win-utils.js';
@@ -102,8 +107,8 @@ export class Win32MingWGcc extends GCCCompiler {
return result;
}
- override async handleExecution(key, executeParameters): Promise<CompilationResult> {
+ override async handleExecution(key, executeParameters, bypassCache: BypassCache): Promise<CompilationResult> {
const execOptions = this.getDefaultExecOptions();
- return super.handleExecution(key, {...executeParameters, env: execOptions.env});
+ return super.handleExecution(key, {...executeParameters, env: execOptions.env}, bypassCache);
}
}
diff --git a/lib/handlers/compile.interfaces.ts b/lib/handlers/compile.interfaces.ts
index 104450b44..af4204066 100644
--- a/lib/handlers/compile.interfaces.ts
+++ b/lib/handlers/compile.interfaces.ts
@@ -22,6 +22,8 @@
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
+import {BypassCache} from '../../types/compilation/compilation.interfaces.js';
+
// IF YOU MODIFY ANYTHING HERE PLEASE UPDATE THE DOCUMENTATION!
// This type models a request so all fields must be optional strings.
@@ -52,12 +54,12 @@ export type CompilationRequestArgs = {
export type CompileRequestJsonBody = {
options: CompilationRequestArgs;
source: string;
- bypassCache: boolean;
+ bypassCache: BypassCache;
};
export type CompileRequestTextBody = {
source: string;
- bypassCache: boolean;
+ bypassCache: BypassCache;
options: any;
userArguments: string;
executeParametersArgs: any;
diff --git a/lib/handlers/compile.ts b/lib/handlers/compile.ts
index ac19c7972..6ec2782f6 100644
--- a/lib/handlers/compile.ts
+++ b/lib/handlers/compile.ts
@@ -50,6 +50,7 @@ import {
} from './compile.interfaces.js';
import {remove} from '../common-utils.js';
import {CompilerOverrideOptions} from '../../types/compilation/compiler-overrides.interfaces.js';
+import {BypassCache, CompileChildLibraries, ExecutionParams} from '../../types/compilation/compilation.interfaces.js';
import {SentryCapture} from '../sentry.js';
temp.track();
@@ -82,20 +83,15 @@ function initialise(compilerEnv: CompilationEnvironment) {
}, tempDirCleanupSecs * 1000);
}
-export type ExecutionParams = {
- args: string[];
- stdin: string;
-};
-
type ParsedRequest = {
source: string;
options: string[];
backendOptions: Record<string, any>;
filters: ParseFiltersAndOutputOptions;
- bypassCache: boolean;
+ bypassCache: BypassCache;
tools: any;
executionParameters: ExecutionParams;
- libraries: any[];
+ libraries: CompileChildLibraries[];
};
export class CompileHandler {
@@ -353,7 +349,7 @@ export class CompileHandler {
options: string,
backendOptions: Record<string, any> = {},
filters: ParseFiltersAndOutputOptions,
- bypassCache = false,
+ bypassCache = BypassCache.None,
tools;
const execReqParams: ExecutionRequestParams = {};
let libraries: any[] = [];
@@ -363,7 +359,7 @@ export class CompileHandler {
const jsonRequest = this.checkRequestRequirements(req);
const requestOptions = jsonRequest.options;
source = jsonRequest.source;
- if (jsonRequest.bypassCache) bypassCache = true;
+ if (jsonRequest.bypassCache) bypassCache = jsonRequest.bypassCache;
options = requestOptions.userArguments;
const execParams = requestOptions.executeParameters || {};
execReqParams.args = execParams.args;
@@ -375,7 +371,7 @@ export class CompileHandler {
} else if (req.body && req.body.compiler) {
const textRequest = req.body as CompileRequestTextBody;
source = textRequest.source;
- if (textRequest.bypassCache) bypassCache = true;
+ if (textRequest.bypassCache) bypassCache = textRequest.bypassCache;
options = textRequest.userArguments;
execReqParams.args = textRequest.executeParametersArgs;
execReqParams.stdin = textRequest.executeParametersStdin;
@@ -423,6 +419,11 @@ export class CompileHandler {
for (const tool of tools) {
tool.args = utils.splitArguments(tool.args);
}
+
+ // Backwards compatibility: bypassCache used to be a boolean.
+ // Convert a boolean input to an enum's underlying numeric value
+ bypassCache = 1 * bypassCache;
+
return {
source,
options: utils.splitArguments(options),
@@ -497,7 +498,9 @@ export class CompileHandler {
this.cmakeCounter.inc({language: compiler.lang.id});
const options = this.parseRequest(req, compiler);
compiler
- .cmake(req.body.files, options)
+ // Backwards compatibility: bypassCache used to be a boolean.
+ // Convert a boolean input to an enum's underlying numeric value
+ .cmake(req.body.files, options, req.body.bypassCache * 1)
.then(result => {
if (result.didExecute || (result.execResult && result.execResult.didExecute))
this.cmakeExecuteCounter.inc({language: compiler.lang.id});
diff --git a/lib/llvm-ir.ts b/lib/llvm-ir.ts
index 5bdf7e651..4ddf9e58f 100644
--- a/lib/llvm-ir.ts
+++ b/lib/llvm-ir.ts
@@ -249,9 +249,9 @@ export class LlvmIrParser {
if (_.isString(ir)) {
return await this.processIr(ir, {
filterDebugInfo: !!filters.debugCalls,
- filterIRMetadata: filters.directives,
+ filterIRMetadata: !!filters.directives,
filterAttributes: false,
- demangle: filters.demangle,
+ demangle: !!filters.demangle,
// discard value names is handled earlier
});
}