Skip to content
Merged
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
27 changes: 25 additions & 2 deletions coz
Original file line number Diff line number Diff line change
Expand Up @@ -914,8 +914,31 @@ def _coz_plot(args):
try:
with open(profile_path, 'r') as f:
lines = f.readlines()
# Filter out coz.h self-instrumentation from old profiles
filtered = [l for l in lines if '/coz.h:' not in l]
# Filter out coz.h self-instrumentation experiments.
# Must skip both the experiment line AND subsequent data point lines,
# since data points reference the preceding experiment.
filtered = []
skip_data = False
for line in lines:
stripped = line.strip()
if not stripped:
continue
if stripped.startswith('{'):
# JSON Lines format
if '"type":"experiment"' in stripped and '/coz.h:' in stripped:
skip_data = True
continue
if '"type":"experiment"' in stripped:
skip_data = False
else:
# Legacy tab-separated format
if stripped.startswith('experiment\t') and '/coz.h:' in stripped:
skip_data = True
continue
if stripped.startswith('experiment\t'):
skip_data = False
if not skip_data:
filtered.append(line)
content = ''.join(filtered).encode('utf-8')
self.send_response(200)
self.send_header('Content-Type', 'text/plain')
Expand Down
17 changes: 15 additions & 2 deletions libcoz/profiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,17 @@ static string line_to_json_string(const line* l) {
return json_escape(f->get_name() + ":" + to_string(l->get_line()));
}

/// Check if a line is from the coz.h instrumentation header
static bool is_coz_header(const line* l) {
auto f = l->get_file();
if(!f) return false;
const auto& name = f->get_name();
if(name.length() < 6) return false;
// Check for coz.h preceded by a directory separator (/ on Unix, \ on Windows)
char sep = name[name.length() - 6];
return (sep == '/' || sep == '\\') && name.compare(name.length() - 5, 5, "coz.h") == 0;
}

/**
* Start the profiler
*/
Expand Down Expand Up @@ -723,7 +734,8 @@ void profiler::process_samples(thread_state* state) {
if(sampled_line.second)
state->local_delay.fetch_add(_delay_size.load());

} else if(sampled_line.first != nullptr && _next_line.load() == nullptr) {
} else if(sampled_line.first != nullptr && _next_line.load() == nullptr
&& !is_coz_header(sampled_line.first)) {
_next_line.store(sampled_line.first);
}
}
Expand Down Expand Up @@ -786,7 +798,8 @@ void profiler::process_all_samples() {
}
needs_signal = true;
}
} else if(!experiment_active && sampled_line.first != nullptr && _next_line.load() == nullptr) {
} else if(!experiment_active && sampled_line.first != nullptr && _next_line.load() == nullptr
&& !is_coz_header(sampled_line.first)) {
// When not in an experiment, select this line for the next experiment
_next_line.store(sampled_line.first);
}
Expand Down
14 changes: 7 additions & 7 deletions viewer/index.htm
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ <h1>Welcome to Coz</h1>
<div id="drop-zone" class="drop-zone">
<div class="drop-zone-content">
<i class="fa fa-cloud-upload drop-icon"></i>
<p class="drop-text">Drag & drop your <code>.coz</code> file here</p>
<p class="drop-text">Drag & drop your <code>.coz</code> or <code>.jsonl</code> file here</p>
<p class="drop-subtext">or click to browse</p>
<input type="file" id="drop-zone-input" accept=".coz" hidden>
<input type="file" id="drop-zone-input" accept=".coz,.jsonl" hidden>
</div>
<div class="drop-zone-hover">
<i class="fa fa-download"></i>
Expand Down Expand Up @@ -207,7 +207,7 @@ <h4>Run with Coz</h4>
<div class="step-number">4</div>
<div class="step-content">
<h4>Analyze Results</h4>
<p>Load your <code>profile.coz</code> file here to visualize optimization opportunities.</p>
<p>Load your <code>profile.jsonl</code> or <code>profile.coz</code> file here to visualize optimization opportunities.</p>
</div>
</div>
</div>
Expand Down Expand Up @@ -312,7 +312,7 @@ <h5>Source Scope Filtering</h5>

<h5>Environment Variables</h5>
<ul class="env-list">
<li><code>COZ_OUTPUT</code> &mdash; Output file path (default: profile.coz)</li>
<li><code>COZ_OUTPUT</code> &mdash; Output file path (default: profile.jsonl)</li>
<li><code>COZ_SOURCE_SCOPE</code> &mdash; Glob pattern for source files</li>
<li><code>COZ_BINARY_SCOPE</code> &mdash; Binary scope filter</li>
<li><code>COZ_FILTER_SYSTEM</code> &mdash; Set to 1 to drop system headers</li>
Expand Down Expand Up @@ -346,7 +346,7 @@ <h4 class="modal-title" id="load-profile-dlg-title">
<div id="modal-drop-zone" class="modal-drop-zone">
<div class="drop-zone-content">
<i class="fa fa-cloud-upload drop-icon"></i>
<p class="drop-text">Drag & drop your <code>.coz</code> file here</p>
<p class="drop-text">Drag & drop your <code>.coz</code> or <code>.jsonl</code> file here</p>
<p class="drop-subtext">or</p>
</div>
<div class="drop-zone-hover">
Expand All @@ -359,7 +359,7 @@ <h4 class="modal-title" id="load-profile-dlg-title">
<label for="load-profile-file" class="btn btn-outline btn-block">
<i class="fa fa-file-text-o"></i> Browse Files
</label>
<input type="file" class="hidden-input" id="load-profile-file" accept=".coz" />
<input type="file" class="hidden-input" id="load-profile-file" accept=".coz,.jsonl" />
</form>

<div class="divider">
Expand Down Expand Up @@ -483,7 +483,7 @@ <h5>Source Scope Filtering</h5>

<h5>Environment Variables</h5>
<ul class="env-list">
<li><code>COZ_OUTPUT</code> &mdash; Output file path (default: profile.coz)</li>
<li><code>COZ_OUTPUT</code> &mdash; Output file path (default: profile.jsonl)</li>
<li><code>COZ_SOURCE_SCOPE</code> &mdash; Glob pattern for source files</li>
<li><code>COZ_BINARY_SCOPE</code> &mdash; Binary scope filter</li>
<li><code>COZ_FILTER_SYSTEM</code> &mdash; Set to 1 to drop system headers</li>
Expand Down
16 changes: 13 additions & 3 deletions viewer/js/profile.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion viewer/js/profile.js.map

Large diffs are not rendered by default.

11 changes: 6 additions & 5 deletions viewer/js/ui.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion viewer/js/ui.js.map

Large diffs are not rendered by default.

15 changes: 12 additions & 3 deletions viewer/ts/profile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1017,11 +1017,20 @@ class Profile {
} else if (entry.type === 'runtime') {
// Do nothing
} else if (entry.type === 'experiment') {
experiment = entry;
// Skip experiments targeting coz.h instrumentation overhead
if ((<Experiment>entry).selected && (<Experiment>entry).selected.indexOf('/coz.h:') !== -1) {
experiment = null;
} else {
experiment = entry;
}
} else if (entry.type === 'throughput-point' || entry.type === 'progress-point' || entry.type === 'throughput_point') {
this.addThroughputMeasurement(experiment, entry);
if (experiment !== null) {
this.addThroughputMeasurement(experiment, entry);
}
} else if (entry.type === 'latency-point') {
this.addLatencyMeasurement(experiment, entry);
if (experiment !== null) {
this.addLatencyMeasurement(experiment, entry);
}
} else {
display_warning('Invalid Profile', 'The profile you loaded contains an invalid line: <pre>' + lines[i] + '</pre>');
}
Expand Down
11 changes: 6 additions & 5 deletions viewer/ts/ui.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,8 +230,8 @@ function autoAdjustMinPoints() {

// Handle file loading from a File object
function handleFileLoad(file: File) {
if (!file.name.endsWith('.coz')) {
display_warning('Invalid File', 'Please select a .coz profile file');
if (!file.name.endsWith('.coz') && !file.name.endsWith('.jsonl')) {
display_warning('Invalid File', 'Please select a .coz or .jsonl profile file');
return;
}

Expand Down Expand Up @@ -324,7 +324,7 @@ document.body.addEventListener('dragover', (e) => {
document.body.addEventListener('drop', (e: DragEvent) => {
e.preventDefault();
const files = e.dataTransfer ? e.dataTransfer.files : null;
if (files && files.length > 0 && files[0].name.endsWith('.coz')) {
if (files && files.length > 0 && (files[0].name.endsWith('.coz') || files[0].name.endsWith('.jsonl'))) {
handleFileLoad(files[0]);
}
}, false);
Expand Down Expand Up @@ -647,5 +647,6 @@ function checkAutoLoad() {
}
}

// Auto-load on page ready
document.addEventListener('DOMContentLoaded', checkAutoLoad);
// Auto-load profile from ?load= query parameter.
// Call directly since this script is at the bottom of <body> and all DOM elements exist.
checkAutoLoad();