Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 22 additions & 0 deletions JetStreamDriver.js
Original file line number Diff line number Diff line change
Expand Up @@ -1826,6 +1826,28 @@ let BENCHMARKS = [
deterministicRandom: true,
tags: ["Default", "Octane"],
}),
new AsyncBenchmark({
name: "prismjs-startup",
files: [
"./startup-helper/StartupBenchmark.js",
"./prismjs/benchmark.js",
],
preload: {
// Use non-minified bundle for better local profiling.
// BUNDLE: "./prismjs/dist/bundle.es5.js",
BUNDLE: "./prismjs/dist/bundle.es5.min.js",
SAMPLE_CPP: "./prismjs/data/sample.cpp",
SAMPLE_CSS: "./prismjs/data/sample.css",
SAMPLE_HTML: "./prismjs/data/sample.html",
SAMPLE_JS: "./prismjs/data/sample.js",
SAMPLE_JSON: "./prismjs/data/sample.json",
SAMPLE_MD: "./prismjs/data/sample.md",
SAMPLE_PY: "./prismjs/data/sample.py",
SAMPLE_SQL: "./prismjs/data/sample.sql",
SAMPLE_TS: "./prismjs/data/sample.TS",
},
tags: ["Default", "parser", "regexp", "startup"],
}),
// RexBench
new DefaultBenchmark({
name: "FlightPlanner",
Expand Down
12 changes: 12 additions & 0 deletions prismjs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# prism.js test for JetStream

Measures the performance of the prism.js library by parsing and formatting sample files.

## Build Instructions

```bash
# install required node packages.
npm ci
# build the workload, output is ./dist
npm run build
```
38 changes: 38 additions & 0 deletions prismjs/benchmark-node.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import fs from "fs";
import path from "path";
import { fileURLToPath } from "url";
import { runTest } from "./src/test.mjs";

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

const samples = [
{ file: "data/sample.html", lang: "markup" },
{ file: "data/sample.js", lang: "javascript" },
{ file: "data/sample.css", lang: "css" },
{ file: "data/sample.cpp", lang: "cpp" },
{ file: "data/sample.md", lang: "markdown" },
{ file: "data/sample.json", lang: "json" },
{ file: "data/sample.sql", lang: "sql" },
{ file: "data/sample.py", lang: "python" },
{ file: "data/sample.ts", lang: "typescript" },
];

const samplesWithContent = samples.map((sample) => {
const content = fs.readFileSync(path.join(__dirname, sample.file), "utf8");
return { ...sample, content };
});

const startTime = process.hrtime.bigint();
const results = runTest(samplesWithContent);
const endTime = process.hrtime.bigint();

const duration = Number(endTime - startTime) / 1e6; // milliseconds

for (const result of results) {
console.log(`Output size: ${result.html.length} characters`);
}

console.log(
`\nTotal highlighting time for all files: ${duration.toFixed(2)}ms`
);
89 changes: 89 additions & 0 deletions prismjs/benchmark.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/*
* Copyright (C) 2025 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
* OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/

const EXPECTED_ASSERTION_COUNT = 1213680;

class Benchmark extends StartupBenchmark {
lastResult;
totalHash = 0xdeadbeef;
samples = [];

constructor(iterationCount) {
super({
iterationCount,
expectedCacheCommentCount: 71,
sourceCodeReuseCount: 1,
});
}

async init() {
await Promise.all([
super.init(),
this.loadData("cpp", JetStream.preload.SAMPLE_CPP, -1086372285),
this.loadData("css", JetStream.preload.SAMPLE_CSS, 1173668337),
this.loadData("markup", JetStream.preload.SAMPLE_HTML, -270772291),
this.loadData("js", JetStream.preload.SAMPLE_JS, -838545229),
this.loadData("markdown", JetStream.preload.SAMPLE_MD, 5859883),
this.loadData("sql", JetStream.preload.SAMPLE_SQL, 5859941),
this.loadData("json", JetStream.preload.SAMPLE_JSON, 5859883),
this.loadData("typescript", JetStream.preload.SAMPLE_TS, 133251625),
]);
}

async loadData(lang, file, hash) {
const sample = { lang, hash };
// Push eagerly to have deterministic order.
this.samples.push(sample);
sample.content = await JetStream.getString(file);
// Warm up quickHash and force good string representation.
this.quickHash(sample.content);
console.assert(sample.content.length > 0);
}

runIteration(iteration) {
// Module is loaded into PrismJSBenchmark
let PrismJSBenchmark;
eval(this.iterationSourceCodes[iteration]);
this.lastResult = PrismJSBenchmark.runTest(this.samples);

for (const result of this.lastResult) {
result.hash = this.quickHash(result.html);
this.totalHash ^= result.hash;
}
}

validate() {
console.assert(this.lastResult.length == this.samples.length);
for (let i = 0; i < this.samples.length; i++) {
const sample = this.samples[i];
const result = this.lastResult[i];
console.assert(result.html.length > 0);
console.assert(
result.hash == sample.hash,
`Invalid result.hash = ${result.hash}, expected ${sample.hash}`
);
}
}
}
42 changes: 42 additions & 0 deletions prismjs/data/sample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>

class MyClass {
public:
MyClass(const std::string& name) : name_(name) {}

void printName() const {
std::cout << "Name: " << name_ << std::endl;
}

private:
std::string name_;
};

template<typename T>
void printVector(const std::vector<T>& vec) {
for (const auto& item : vec) {
std::cout << item << " ";
}
std::cout << std::endl;
}

int main() {
std::cout << "Hello, C++ World!" << std::endl;

std::vector<int> numbers = {1, 2, 3, 4, 5};
printVector(numbers);

std::vector<std::string> strings = {"apple", "banana", "cherry"};
printVector(strings);

std::sort(strings.begin(), strings.end());
printVector(strings);

MyClass obj("Test Object");
obj.printName();

return 0;
}
129 changes: 129 additions & 0 deletions prismjs/data/sample.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
/* Large CSS file for testing */

body {
font-family: Arial, sans-serif;
line-height: 1.6;
color: #333;
}

.container {
width: 90%;
margin: 0 auto;
padding: 20px;
}

.header {
background: #f4f4f4;
padding: 1rem;
border-bottom: 1px solid #ddd;
}

.header h1 {
margin: 0;
}

.nav {
background: #333;
color: #fff;
padding: 0.5rem;
}

.nav ul {
padding: 0;
list-style: none;
}

.nav ul li {
display: inline;
margin-right: 20px;
}

.nav a {
color: #fff;
text-decoration: none;
}

.main {
padding: 1rem 0;
}

.footer {
background: #333;
color: #fff;
text-align: center;
padding: 1rem;
margin-top: 20px;
}

.btn {
display: inline-block;
background: #5cb85c;
color: #fff;
padding: 10px 20px;
border: none;
cursor: pointer;
}

.btn:hover {
background: #4cae4c;
}

.grid {
display: grid;
grid-template-columns: repeat(4, 1fr);
gap: 1rem;
}

.card {
border: 1px solid #ccc;
padding: 1rem;
box-shadow: 2px 2px 5px rgba(0,0,0,0.1);
}

.table {
width: 100%;
border-collapse: collapse;
}

.table th, .table td {
border: 1px solid #ddd;
padding: 8px;
}

.table th {
background-color: #f2f2f2;
}

.form-group {
margin-bottom: 15px;
}

.form-group label {
display: block;
margin-bottom: 5px;
}

.form-group input {
width: 100%;
padding: 8px;
border: 1px solid #ccc;
}

.alert {
padding: 15px;
margin-bottom: 20px;
border: 1px solid transparent;
border-radius: 4px;
}

.alert-success {
color: #3c763d;
background-color: #dff0d8;
border-color: #d6e9c6;
}

.alert-danger {
color: #a94442;
background-color: #f2dede;
border-color: #ebccd1;
}
Loading
Loading