osprey 0.1.0

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.
data/flamegraph.svg ADDED
@@ -0,0 +1,491 @@
1
+ <?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" width="1200" height="390" onload="init(evt)" viewBox="0 0 1200 390" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:fg="http://github.com/jonhoo/inferno"><!--Flame graph stack visualization. See https://github.com/brendangregg/FlameGraph for latest version, and http://www.brendangregg.com/flamegraphs.html for examples.--><!--NOTES: --><defs><linearGradient id="background" y1="0" y2="1" x1="0" x2="0"><stop stop-color="#eeeeee" offset="5%"/><stop stop-color="#eeeeb0" offset="95%"/></linearGradient></defs><style type="text/css">
2
+ text { font-family:monospace; font-size:12px }
3
+ #title { text-anchor:middle; font-size:17px; }
4
+ #matched { text-anchor:end; }
5
+ #search { text-anchor:end; opacity:0.1; cursor:pointer; }
6
+ #search:hover, #search.show { opacity:1; }
7
+ #subtitle { text-anchor:middle; font-color:rgb(160,160,160); }
8
+ #unzoom { cursor:pointer; }
9
+ #frames > *:hover { stroke:black; stroke-width:0.5; cursor:pointer; }
10
+ .hide { display:none; }
11
+ .parent { opacity:0.5; }
12
+ </style><script type="text/ecmascript"><![CDATA[
13
+ var nametype = 'Function:';
14
+ var fontsize = 12;
15
+ var fontwidth = 0.59;
16
+ var xpad = 10;
17
+ var inverted = false;
18
+ var searchcolor = 'rgb(230,0,230)';
19
+ var fluiddrawing = true;
20
+ var truncate_text_right = false;
21
+ ]]><![CDATA["use strict";
22
+ var details, searchbtn, unzoombtn, matchedtxt, svg, searching, frames, known_font_width;
23
+ function init(evt) {
24
+ details = document.getElementById("details").firstChild;
25
+ searchbtn = document.getElementById("search");
26
+ unzoombtn = document.getElementById("unzoom");
27
+ matchedtxt = document.getElementById("matched");
28
+ svg = document.getElementsByTagName("svg")[0];
29
+ frames = document.getElementById("frames");
30
+ known_font_width = get_monospace_width(frames);
31
+ total_samples = parseInt(frames.attributes.total_samples.value);
32
+ searching = 0;
33
+
34
+ // Use GET parameters to restore a flamegraph's state.
35
+ var restore_state = function() {
36
+ var params = get_params();
37
+ if (params.x && params.y)
38
+ zoom(find_group(document.querySelector('[*|x="' + params.x + '"][y="' + params.y + '"]')));
39
+ if (params.s)
40
+ search(params.s);
41
+ };
42
+
43
+ if (fluiddrawing) {
44
+ // Make width dynamic so the SVG fits its parent's width.
45
+ svg.removeAttribute("width");
46
+ // Edge requires us to have a viewBox that gets updated with size changes.
47
+ var isEdge = /Edge\/\d./i.test(navigator.userAgent);
48
+ if (!isEdge) {
49
+ svg.removeAttribute("viewBox");
50
+ }
51
+ var update_for_width_change = function() {
52
+ if (isEdge) {
53
+ svg.attributes.viewBox.value = "0 0 " + svg.width.baseVal.value + " " + svg.height.baseVal.value;
54
+ }
55
+
56
+ // Keep consistent padding on left and right of frames container.
57
+ frames.attributes.width.value = svg.width.baseVal.value - xpad * 2;
58
+
59
+ // Text truncation needs to be adjusted for the current width.
60
+ update_text_for_elements(frames.children);
61
+
62
+ // Keep search elements at a fixed distance from right edge.
63
+ var svgWidth = svg.width.baseVal.value;
64
+ searchbtn.attributes.x.value = svgWidth - xpad;
65
+ matchedtxt.attributes.x.value = svgWidth - xpad;
66
+ };
67
+ window.addEventListener('resize', function() {
68
+ update_for_width_change();
69
+ });
70
+ // This needs to be done asynchronously for Safari to work.
71
+ setTimeout(function() {
72
+ unzoom();
73
+ update_for_width_change();
74
+ restore_state();
75
+ }, 0);
76
+ } else {
77
+ restore_state();
78
+ }
79
+ }
80
+ // event listeners
81
+ window.addEventListener("click", function(e) {
82
+ var target = find_group(e.target);
83
+ if (target) {
84
+ if (target.nodeName == "a") {
85
+ if (e.ctrlKey === false) return;
86
+ e.preventDefault();
87
+ }
88
+ if (target.classList.contains("parent")) unzoom();
89
+ zoom(target);
90
+
91
+ // set parameters for zoom state
92
+ var el = target.querySelector("rect");
93
+ if (el && el.attributes && el.attributes.y && el.attributes["fg:x"]) {
94
+ var params = get_params()
95
+ params.x = el.attributes["fg:x"].value;
96
+ params.y = el.attributes.y.value;
97
+ history.replaceState(null, null, parse_params(params));
98
+ }
99
+ }
100
+ else if (e.target.id == "unzoom") {
101
+ unzoom();
102
+
103
+ // remove zoom state
104
+ var params = get_params();
105
+ if (params.x) delete params.x;
106
+ if (params.y) delete params.y;
107
+ history.replaceState(null, null, parse_params(params));
108
+ }
109
+ else if (e.target.id == "search") search_prompt();
110
+ }, false)
111
+ // mouse-over for info
112
+ // show
113
+ window.addEventListener("mouseover", function(e) {
114
+ var target = find_group(e.target);
115
+ if (target) details.nodeValue = nametype + " " + g_to_text(target);
116
+ }, false)
117
+ // clear
118
+ window.addEventListener("mouseout", function(e) {
119
+ var target = find_group(e.target);
120
+ if (target) details.nodeValue = ' ';
121
+ }, false)
122
+ // ctrl-F for search
123
+ window.addEventListener("keydown",function (e) {
124
+ if (e.keyCode === 114 || (e.ctrlKey && e.keyCode === 70)) {
125
+ e.preventDefault();
126
+ search_prompt();
127
+ }
128
+ }, false)
129
+ // functions
130
+ function get_params() {
131
+ var params = {};
132
+ var paramsarr = window.location.search.substr(1).split('&');
133
+ for (var i = 0; i < paramsarr.length; ++i) {
134
+ var tmp = paramsarr[i].split("=");
135
+ if (!tmp[0] || !tmp[1]) continue;
136
+ params[tmp[0]] = decodeURIComponent(tmp[1]);
137
+ }
138
+ return params;
139
+ }
140
+ function parse_params(params) {
141
+ var uri = "?";
142
+ for (var key in params) {
143
+ uri += key + '=' + encodeURIComponent(params[key]) + '&';
144
+ }
145
+ if (uri.slice(-1) == "&")
146
+ uri = uri.substring(0, uri.length - 1);
147
+ if (uri == '?')
148
+ uri = window.location.href.split('?')[0];
149
+ return uri;
150
+ }
151
+ function find_child(node, selector) {
152
+ var children = node.querySelectorAll(selector);
153
+ if (children.length) return children[0];
154
+ return;
155
+ }
156
+ function find_group(node) {
157
+ var parent = node.parentElement;
158
+ if (!parent) return;
159
+ if (parent.id == "frames") return node;
160
+ return find_group(parent);
161
+ }
162
+ function orig_save(e, attr, val) {
163
+ if (e.attributes["fg:orig_" + attr] != undefined) return;
164
+ if (e.attributes[attr] == undefined) return;
165
+ if (val == undefined) val = e.attributes[attr].value;
166
+ e.setAttribute("fg:orig_" + attr, val);
167
+ }
168
+ function orig_load(e, attr) {
169
+ if (e.attributes["fg:orig_"+attr] == undefined) return;
170
+ e.attributes[attr].value = e.attributes["fg:orig_" + attr].value;
171
+ e.removeAttribute("fg:orig_" + attr);
172
+ }
173
+ function g_to_text(e) {
174
+ var text = find_child(e, "title").firstChild.nodeValue;
175
+ return (text)
176
+ }
177
+ function g_to_func(e) {
178
+ var func = g_to_text(e);
179
+ // if there's any manipulation we want to do to the function
180
+ // name before it's searched, do it here before returning.
181
+ return (func);
182
+ }
183
+ function get_monospace_width(frames) {
184
+ // Given the id="frames" element, return the width of text characters if
185
+ // this is a monospace font, otherwise return 0.
186
+ text = find_child(frames.children[0], "text");
187
+ originalContent = text.textContent;
188
+ text.textContent = "!";
189
+ bangWidth = text.getComputedTextLength();
190
+ text.textContent = "W";
191
+ wWidth = text.getComputedTextLength();
192
+ text.textContent = originalContent;
193
+ if (bangWidth === wWidth) {
194
+ return bangWidth;
195
+ } else {
196
+ return 0;
197
+ }
198
+ }
199
+ function update_text_for_elements(elements) {
200
+ // In order to render quickly in the browser, you want to do one pass of
201
+ // reading attributes, and one pass of mutating attributes. See
202
+ // https://web.dev/avoid-large-complex-layouts-and-layout-thrashing/ for details.
203
+
204
+ // Fall back to inefficient calculation, if we're variable-width font.
205
+ // TODO This should be optimized somehow too.
206
+ if (known_font_width === 0) {
207
+ for (var i = 0; i < elements.length; i++) {
208
+ update_text(elements[i]);
209
+ }
210
+ return;
211
+ }
212
+
213
+ var textElemNewAttributes = [];
214
+ for (var i = 0; i < elements.length; i++) {
215
+ var e = elements[i];
216
+ var r = find_child(e, "rect");
217
+ var t = find_child(e, "text");
218
+ var w = parseFloat(r.attributes.width.value) * frames.attributes.width.value / 100 - 3;
219
+ var txt = find_child(e, "title").textContent.replace(/\([^(]*\)$/,"");
220
+ var newX = format_percent((parseFloat(r.attributes.x.value) + (100 * 3 / frames.attributes.width.value)));
221
+
222
+ // Smaller than this size won't fit anything
223
+ if (w < 2 * known_font_width) {
224
+ textElemNewAttributes.push([newX, ""]);
225
+ continue;
226
+ }
227
+
228
+ // Fit in full text width
229
+ if (txt.length * known_font_width < w) {
230
+ textElemNewAttributes.push([newX, txt]);
231
+ continue;
232
+ }
233
+
234
+ var substringLength = Math.floor(w / known_font_width) - 2;
235
+ if (truncate_text_right) {
236
+ // Truncate the right side of the text.
237
+ textElemNewAttributes.push([newX, txt.substring(0, substringLength) + ".."]);
238
+ continue;
239
+ } else {
240
+ // Truncate the left side of the text.
241
+ textElemNewAttributes.push([newX, ".." + txt.substring(txt.length - substringLength, txt.length)]);
242
+ continue;
243
+ }
244
+ }
245
+
246
+ console.assert(textElemNewAttributes.length === elements.length, "Resize failed, please file a bug at https://github.com/jonhoo/inferno/");
247
+
248
+ // Now that we know new textContent, set it all in one go so we don't refresh a bazillion times.
249
+ for (var i = 0; i < elements.length; i++) {
250
+ var e = elements[i];
251
+ var values = textElemNewAttributes[i];
252
+ var t = find_child(e, "text");
253
+ t.attributes.x.value = values[0];
254
+ t.textContent = values[1];
255
+ }
256
+ }
257
+
258
+ function update_text(e) {
259
+ var r = find_child(e, "rect");
260
+ var t = find_child(e, "text");
261
+ var w = parseFloat(r.attributes.width.value) * frames.attributes.width.value / 100 - 3;
262
+ var txt = find_child(e, "title").textContent.replace(/\([^(]*\)$/,"");
263
+ t.attributes.x.value = format_percent((parseFloat(r.attributes.x.value) + (100 * 3 / frames.attributes.width.value)));
264
+
265
+ // Smaller than this size won't fit anything
266
+ if (w < 2 * fontsize * fontwidth) {
267
+ t.textContent = "";
268
+ return;
269
+ }
270
+ t.textContent = txt;
271
+ // Fit in full text width
272
+ if (t.getComputedTextLength() < w)
273
+ return;
274
+ if (truncate_text_right) {
275
+ // Truncate the right side of the text.
276
+ for (var x = txt.length - 2; x > 0; x--) {
277
+ if (t.getSubStringLength(0, x + 2) <= w) {
278
+ t.textContent = txt.substring(0, x) + "..";
279
+ return;
280
+ }
281
+ }
282
+ } else {
283
+ // Truncate the left side of the text.
284
+ for (var x = 2; x < txt.length; x++) {
285
+ if (t.getSubStringLength(x - 2, txt.length) <= w) {
286
+ t.textContent = ".." + txt.substring(x, txt.length);
287
+ return;
288
+ }
289
+ }
290
+ }
291
+ t.textContent = "";
292
+ }
293
+ // zoom
294
+ function zoom_reset(e) {
295
+ if (e.tagName == "rect") {
296
+ e.attributes.x.value = format_percent(100 * parseInt(e.attributes["fg:x"].value) / total_samples);
297
+ e.attributes.width.value = format_percent(100 * parseInt(e.attributes["fg:w"].value) / total_samples);
298
+ }
299
+ if (e.childNodes == undefined) return;
300
+ for(var i = 0, c = e.childNodes; i < c.length; i++) {
301
+ zoom_reset(c[i]);
302
+ }
303
+ }
304
+ function zoom_child(e, x, zoomed_width_samples) {
305
+ if (e.tagName == "text") {
306
+ var parent_x = parseFloat(find_child(e.parentNode, "rect[x]").attributes.x.value);
307
+ e.attributes.x.value = format_percent(parent_x + (100 * 3 / frames.attributes.width.value));
308
+ } else if (e.tagName == "rect") {
309
+ e.attributes.x.value = format_percent(100 * (parseInt(e.attributes["fg:x"].value) - x) / zoomed_width_samples);
310
+ e.attributes.width.value = format_percent(100 * parseInt(e.attributes["fg:w"].value) / zoomed_width_samples);
311
+ }
312
+ if (e.childNodes == undefined) return;
313
+ for(var i = 0, c = e.childNodes; i < c.length; i++) {
314
+ zoom_child(c[i], x, zoomed_width_samples);
315
+ }
316
+ }
317
+ function zoom_parent(e) {
318
+ if (e.attributes) {
319
+ if (e.attributes.x != undefined) {
320
+ e.attributes.x.value = "0.0%";
321
+ }
322
+ if (e.attributes.width != undefined) {
323
+ e.attributes.width.value = "100.0%";
324
+ }
325
+ }
326
+ if (e.childNodes == undefined) return;
327
+ for(var i = 0, c = e.childNodes; i < c.length; i++) {
328
+ zoom_parent(c[i]);
329
+ }
330
+ }
331
+ function zoom(node) {
332
+ var attr = find_child(node, "rect").attributes;
333
+ var width = parseInt(attr["fg:w"].value);
334
+ var xmin = parseInt(attr["fg:x"].value);
335
+ var xmax = xmin + width;
336
+ var ymin = parseFloat(attr.y.value);
337
+ unzoombtn.classList.remove("hide");
338
+ var el = frames.children;
339
+ var to_update_text = [];
340
+ for (var i = 0; i < el.length; i++) {
341
+ var e = el[i];
342
+ var a = find_child(e, "rect").attributes;
343
+ var ex = parseInt(a["fg:x"].value);
344
+ var ew = parseInt(a["fg:w"].value);
345
+ // Is it an ancestor
346
+ if (!inverted) {
347
+ var upstack = parseFloat(a.y.value) > ymin;
348
+ } else {
349
+ var upstack = parseFloat(a.y.value) < ymin;
350
+ }
351
+ if (upstack) {
352
+ // Direct ancestor
353
+ if (ex <= xmin && (ex+ew) >= xmax) {
354
+ e.classList.add("parent");
355
+ zoom_parent(e);
356
+ to_update_text.push(e);
357
+ }
358
+ // not in current path
359
+ else
360
+ e.classList.add("hide");
361
+ }
362
+ // Children maybe
363
+ else {
364
+ // no common path
365
+ if (ex < xmin || ex >= xmax) {
366
+ e.classList.add("hide");
367
+ }
368
+ else {
369
+ zoom_child(e, xmin, width);
370
+ to_update_text.push(e);
371
+ }
372
+ }
373
+ }
374
+ update_text_for_elements(to_update_text);
375
+ }
376
+ function unzoom() {
377
+ unzoombtn.classList.add("hide");
378
+ var el = frames.children;
379
+ for(var i = 0; i < el.length; i++) {
380
+ el[i].classList.remove("parent");
381
+ el[i].classList.remove("hide");
382
+ zoom_reset(el[i]);
383
+ }
384
+ update_text_for_elements(el);
385
+ }
386
+ // search
387
+ function reset_search() {
388
+ var el = document.querySelectorAll("#frames rect");
389
+ for (var i = 0; i < el.length; i++) {
390
+ orig_load(el[i], "fill")
391
+ }
392
+ var params = get_params();
393
+ delete params.s;
394
+ history.replaceState(null, null, parse_params(params));
395
+ }
396
+ function search_prompt() {
397
+ if (!searching) {
398
+ var term = prompt("Enter a search term (regexp " +
399
+ "allowed, eg: ^ext4_)", "");
400
+ if (term != null) {
401
+ search(term)
402
+ }
403
+ } else {
404
+ reset_search();
405
+ searching = 0;
406
+ searchbtn.classList.remove("show");
407
+ searchbtn.firstChild.nodeValue = "Search"
408
+ matchedtxt.classList.add("hide");
409
+ matchedtxt.firstChild.nodeValue = ""
410
+ }
411
+ }
412
+ function search(term) {
413
+ var re = new RegExp(term);
414
+ var el = frames.children;
415
+ var matches = new Object();
416
+ var maxwidth = 0;
417
+ for (var i = 0; i < el.length; i++) {
418
+ var e = el[i];
419
+ // Skip over frames which are either not visible, or below the zoomed-to frame
420
+ if (e.classList.contains("hide") || e.classList.contains("parent")) {
421
+ continue;
422
+ }
423
+ var func = g_to_func(e);
424
+ var rect = find_child(e, "rect");
425
+ if (func == null || rect == null)
426
+ continue;
427
+ // Save max width. Only works as we have a root frame
428
+ var w = parseInt(rect.attributes["fg:w"].value);
429
+ if (w > maxwidth)
430
+ maxwidth = w;
431
+ if (func.match(re)) {
432
+ // highlight
433
+ var x = parseInt(rect.attributes["fg:x"].value);
434
+ orig_save(rect, "fill");
435
+ rect.attributes.fill.value = searchcolor;
436
+ // remember matches
437
+ if (matches[x] == undefined) {
438
+ matches[x] = w;
439
+ } else {
440
+ if (w > matches[x]) {
441
+ // overwrite with parent
442
+ matches[x] = w;
443
+ }
444
+ }
445
+ searching = 1;
446
+ }
447
+ }
448
+ if (!searching)
449
+ return;
450
+ var params = get_params();
451
+ params.s = term;
452
+ history.replaceState(null, null, parse_params(params));
453
+
454
+ searchbtn.classList.add("show");
455
+ searchbtn.firstChild.nodeValue = "Reset Search";
456
+ // calculate percent matched, excluding vertical overlap
457
+ var count = 0;
458
+ var lastx = -1;
459
+ var lastw = 0;
460
+ var keys = Array();
461
+ for (k in matches) {
462
+ if (matches.hasOwnProperty(k))
463
+ keys.push(k);
464
+ }
465
+ // sort the matched frames by their x location
466
+ // ascending, then width descending
467
+ keys.sort(function(a, b){
468
+ return a - b;
469
+ });
470
+ // Step through frames saving only the biggest bottom-up frames
471
+ // thanks to the sort order. This relies on the tree property
472
+ // where children are always smaller than their parents.
473
+ for (var k in keys) {
474
+ var x = parseInt(keys[k]);
475
+ var w = matches[keys[k]];
476
+ if (x >= lastx + lastw) {
477
+ count += w;
478
+ lastx = x;
479
+ lastw = w;
480
+ }
481
+ }
482
+ // display matched percent
483
+ matchedtxt.classList.remove("hide");
484
+ var pct = 100 * count / maxwidth;
485
+ if (pct != 100) pct = pct.toFixed(1);
486
+ matchedtxt.firstChild.nodeValue = "Matched: " + pct + "%";
487
+ }
488
+ function format_percent(n) {
489
+ return n.toFixed(4) + "%";
490
+ }
491
+ ]]></script><rect x="0" y="0" width="100%" height="390" fill="url(#background)"/><text id="title" fill="rgb(0,0,0)" x="50.0000%" y="24.00">Flame Graph</text><text id="details" fill="rgb(0,0,0)" x="10" y="373.00"> </text><text id="unzoom" class="hide" fill="rgb(0,0,0)" x="10" y="24.00">Reset Zoom</text><text id="search" fill="rgb(0,0,0)" x="1190" y="24.00">Search</text><text id="matched" fill="rgb(0,0,0)" x="1190" y="373.00"> </text><svg id="frames" x="10" width="1180" total_samples="1283"><g><title>libruby.3.4.dylib`rb_nogvl (1 samples, 0.08%)</title><rect x="0.0000%" y="181" width="0.0779%" height="15" fill="rgb(227,0,7)" fg:x="0" fg:w="1"/><text x="0.2500%" y="191.50"></text></g><g><title>libsystem_malloc.dylib`_free (2 samples, 0.16%)</title><rect x="0.0779%" y="181" width="0.1559%" height="15" fill="rgb(217,0,24)" fg:x="1" fg:w="2"/><text x="0.3279%" y="191.50"></text></g><g><title>libsystem_malloc.dylib`default_zone_free_definite_size (5 samples, 0.39%)</title><rect x="0.2338%" y="181" width="0.3897%" height="15" fill="rgb(221,193,54)" fg:x="3" fg:w="5"/><text x="0.4838%" y="191.50"></text></g><g><title>libsystem_malloc.dylib`nanov2_forked_free (1 samples, 0.08%)</title><rect x="0.6235%" y="181" width="0.0779%" height="15" fill="rgb(248,212,6)" fg:x="8" fg:w="1"/><text x="0.8735%" y="191.50"></text></g><g><title>libruby.3.4.dylib`blocking_region_begin (1 samples, 0.08%)</title><rect x="0.7794%" y="165" width="0.0779%" height="15" fill="rgb(208,68,35)" fg:x="10" fg:w="1"/><text x="1.0294%" y="175.50"></text></g><g><title>libruby.3.4.dylib`rb_current_ec (1 samples, 0.08%)</title><rect x="0.8574%" y="165" width="0.0779%" height="15" fill="rgb(232,128,0)" fg:x="11" fg:w="1"/><text x="1.1074%" y="175.50"></text></g><g><title>libruby.3.4.dylib`rb_errno (2 samples, 0.16%)</title><rect x="0.9353%" y="165" width="0.1559%" height="15" fill="rgb(207,160,47)" fg:x="12" fg:w="2"/><text x="1.1853%" y="175.50"></text></g><g><title>libdyld.dylib`tlv_get_addr (1 samples, 0.08%)</title><rect x="1.4030%" y="149" width="0.0779%" height="15" fill="rgb(228,23,34)" fg:x="18" fg:w="1"/><text x="1.6530%" y="159.50"></text></g><g><title>libruby.3.4.dylib`DYLD-STUB$$__error (2 samples, 0.16%)</title><rect x="1.4809%" y="149" width="0.1559%" height="15" fill="rgb(218,30,26)" fg:x="19" fg:w="2"/><text x="1.7309%" y="159.50"></text></g><g><title>libruby.3.4.dylib`blocking_region_begin (1 samples, 0.08%)</title><rect x="1.6368%" y="149" width="0.0779%" height="15" fill="rgb(220,122,19)" fg:x="21" fg:w="1"/><text x="1.8868%" y="159.50"></text></g><g><title>libsystem_pthread.dylib`pthread_mutex_lock (1 samples, 0.08%)</title><rect x="1.6368%" y="133" width="0.0779%" height="15" fill="rgb(250,228,42)" fg:x="21" fg:w="1"/><text x="1.8868%" y="143.50"></text></g><g><title>libruby.3.4.dylib`thread_sched_setup_running_threads (1 samples, 0.08%)</title><rect x="1.7147%" y="117" width="0.0779%" height="15" fill="rgb(240,193,28)" fg:x="22" fg:w="1"/><text x="1.9647%" y="127.50"></text></g><g><title>libsystem_pthread.dylib`pthread_mutex_lock (1 samples, 0.08%)</title><rect x="1.7147%" y="101" width="0.0779%" height="15" fill="rgb(216,20,37)" fg:x="22" fg:w="1"/><text x="1.9647%" y="111.50"></text></g><g><title>libruby.3.4.dylib`thread_sched_to_running (2 samples, 0.16%)</title><rect x="1.7147%" y="133" width="0.1559%" height="15" fill="rgb(206,188,39)" fg:x="22" fg:w="2"/><text x="1.9647%" y="143.50"></text></g><g><title>libsystem_pthread.dylib`pthread_mutex_lock (1 samples, 0.08%)</title><rect x="1.7927%" y="117" width="0.0779%" height="15" fill="rgb(217,207,13)" fg:x="23" fg:w="1"/><text x="2.0427%" y="127.50"></text></g><g><title>libruby.3.4.dylib`thread_sched_wait_running_turn (4 samples, 0.31%)</title><rect x="1.8706%" y="133" width="0.3118%" height="15" fill="rgb(231,73,38)" fg:x="24" fg:w="4"/><text x="2.1206%" y="143.50"></text></g><g><title>libruby.3.4.dylib`blocking_region_end (7 samples, 0.55%)</title><rect x="1.7147%" y="149" width="0.5456%" height="15" fill="rgb(225,20,46)" fg:x="22" fg:w="7"/><text x="1.9647%" y="159.50"></text></g><g><title>libsystem_pthread.dylib`pthread_mutex_lock (1 samples, 0.08%)</title><rect x="2.1824%" y="133" width="0.0779%" height="15" fill="rgb(210,31,41)" fg:x="28" fg:w="1"/><text x="2.4324%" y="143.50"></text></g><g><title>libruby.3.4.dylib`rb_ractor_blocking_threads_dec (3 samples, 0.23%)</title><rect x="2.2603%" y="149" width="0.2338%" height="15" fill="rgb(221,200,47)" fg:x="29" fg:w="3"/><text x="2.5103%" y="159.50"></text></g><g><title>libruby.3.4.dylib`thread_sched_setup_running_threads (1 samples, 0.08%)</title><rect x="2.4942%" y="149" width="0.0779%" height="15" fill="rgb(226,26,5)" fg:x="32" fg:w="1"/><text x="2.7442%" y="159.50"></text></g><g><title>libsystem_kernel.dylib`__error (2 samples, 0.16%)</title><rect x="2.5721%" y="149" width="0.1559%" height="15" fill="rgb(249,33,26)" fg:x="33" fg:w="2"/><text x="2.8221%" y="159.50"></text></g><g><title>libsystem_malloc.dylib`malloc (1 samples, 0.08%)</title><rect x="2.7280%" y="149" width="0.0779%" height="15" fill="rgb(235,183,28)" fg:x="35" fg:w="1"/><text x="2.9780%" y="159.50"></text></g><g><title>libsystem_malloc.dylib`nanov2_forked_malloc (7 samples, 0.55%)</title><rect x="2.8059%" y="149" width="0.5456%" height="15" fill="rgb(221,5,38)" fg:x="36" fg:w="7"/><text x="3.0559%" y="159.50"></text></g><g><title>libsystem_malloc.dylib`szone_malloc (1 samples, 0.08%)</title><rect x="3.3515%" y="149" width="0.0779%" height="15" fill="rgb(247,18,42)" fg:x="43" fg:w="1"/><text x="3.6015%" y="159.50"></text></g><g><title>libsystem_malloc.dylib`szone_malloc_should_clear (3 samples, 0.23%)</title><rect x="3.4295%" y="149" width="0.2338%" height="15" fill="rgb(241,131,45)" fg:x="44" fg:w="3"/><text x="3.6795%" y="159.50"></text></g><g><title>osprey.bundle`__rust_alloc (2 samples, 0.16%)</title><rect x="3.6633%" y="149" width="0.1559%" height="15" fill="rgb(249,31,29)" fg:x="47" fg:w="2"/><text x="3.9133%" y="159.50"></text></g><g><title>libsystem_malloc.dylib`small_malloc_should_clear (1 samples, 0.08%)</title><rect x="4.0530%" y="133" width="0.0779%" height="15" fill="rgb(225,111,53)" fg:x="52" fg:w="1"/><text x="4.3030%" y="143.50"></text></g><g><title>libsystem_malloc.dylib`rack_get_thread_index (1 samples, 0.08%)</title><rect x="4.1309%" y="117" width="0.0779%" height="15" fill="rgb(238,160,17)" fg:x="53" fg:w="1"/><text x="4.3809%" y="127.50"></text></g><g><title>libsystem_malloc.dylib`szone_malloc_should_clear (2 samples, 0.16%)</title><rect x="4.1309%" y="133" width="0.1559%" height="15" fill="rgb(214,148,48)" fg:x="53" fg:w="2"/><text x="4.3809%" y="143.50"></text></g><g><title>libsystem_malloc.dylib`small_malloc_should_clear (1 samples, 0.08%)</title><rect x="4.2089%" y="117" width="0.0779%" height="15" fill="rgb(232,36,49)" fg:x="54" fg:w="1"/><text x="4.4589%" y="127.50"></text></g><g><title>libsystem_pthread.dylib`cthread_yield (2 samples, 0.16%)</title><rect x="4.3648%" y="117" width="0.1559%" height="15" fill="rgb(209,103,24)" fg:x="56" fg:w="2"/><text x="4.6148%" y="127.50"></text></g><g><title>osprey.bundle`DYLD-STUB$$sched_yield (1 samples, 0.08%)</title><rect x="4.5207%" y="117" width="0.0779%" height="15" fill="rgb(229,88,8)" fg:x="58" fg:w="1"/><text x="4.7707%" y="127.50"></text></g><g><title>libsystem_c.dylib`clock_gettime (1 samples, 0.08%)</title><rect x="21.9797%" y="101" width="0.0779%" height="15" fill="rgb(213,181,19)" fg:x="282" fg:w="1"/><text x="22.2297%" y="111.50"></text></g><g><title>libsystem_kernel.dylib`swtch_pri (672 samples, 52.38%)</title><rect x="22.0577%" y="101" width="52.3772%" height="15" fill="rgb(254,191,54)" fg:x="283" fg:w="672"/><text x="22.3077%" y="111.50">libsystem_kernel.dylib`swtch_pri</text></g><g><title>libsystem_pthread.dylib`cthread_yield (2 samples, 0.16%)</title><rect x="74.4349%" y="101" width="0.1559%" height="15" fill="rgb(241,83,37)" fg:x="955" fg:w="2"/><text x="74.6849%" y="111.50"></text></g><g><title>osprey.bundle`DYLD-STUB$$clock_gettime (1 samples, 0.08%)</title><rect x="74.5908%" y="101" width="0.0779%" height="15" fill="rgb(233,36,39)" fg:x="957" fg:w="1"/><text x="74.8408%" y="111.50"></text></g><g><title>libsystem_c.dylib`clock_gettime (1 samples, 0.08%)</title><rect x="74.9026%" y="85" width="0.0779%" height="15" fill="rgb(226,3,54)" fg:x="961" fg:w="1"/><text x="75.1526%" y="95.50"></text></g><g><title>libsystem_pthread.dylib`pthread_mutex_unlock (1 samples, 0.08%)</title><rect x="74.9805%" y="85" width="0.0779%" height="15" fill="rgb(245,192,40)" fg:x="962" fg:w="1"/><text x="75.2305%" y="95.50"></text></g><g><title>libsystem_c.dylib`DYLD-STUB$$mach_timebase_info (1 samples, 0.08%)</title><rect x="75.1364%" y="53" width="0.0779%" height="15" fill="rgb(238,167,29)" fg:x="964" fg:w="1"/><text x="75.3864%" y="63.50"></text></g><g><title>libsystem_c.dylib`clock_gettime_nsec_np (1 samples, 0.08%)</title><rect x="75.2143%" y="53" width="0.0779%" height="15" fill="rgb(232,182,51)" fg:x="965" fg:w="1"/><text x="75.4643%" y="63.50"></text></g><g><title>libsystem_kernel.dylib`mach_timebase_info (1 samples, 0.08%)</title><rect x="75.2143%" y="37" width="0.0779%" height="15" fill="rgb(231,60,39)" fg:x="965" fg:w="1"/><text x="75.4643%" y="47.50"></text></g><g><title>libsystem_kernel.dylib`mach_absolute_time (13 samples, 1.01%)</title><rect x="75.2923%" y="53" width="1.0133%" height="15" fill="rgb(208,69,12)" fg:x="966" fg:w="13"/><text x="75.5423%" y="63.50"></text></g><g><title>osprey.bundle`std::sys::pal::unix::time::Timespec::now (19 samples, 1.48%)</title><rect x="75.0585%" y="85" width="1.4809%" height="15" fill="rgb(235,93,37)" fg:x="963" fg:w="19"/><text x="75.3085%" y="95.50"></text></g><g><title>libsystem_c.dylib`clock_gettime (19 samples, 1.48%)</title><rect x="75.0585%" y="69" width="1.4809%" height="15" fill="rgb(213,116,39)" fg:x="963" fg:w="19"/><text x="75.3085%" y="79.50"></text></g><g><title>libsystem_kernel.dylib`mach_timebase_info (3 samples, 0.23%)</title><rect x="76.3055%" y="53" width="0.2338%" height="15" fill="rgb(222,207,29)" fg:x="979" fg:w="3"/><text x="76.5555%" y="63.50"></text></g><g><title>libdispatch.dylib`_dispatch_sema4_timedwait (3 samples, 0.23%)</title><rect x="76.9291%" y="53" width="0.2338%" height="15" fill="rgb(206,96,30)" fg:x="987" fg:w="3"/><text x="77.1791%" y="63.50"></text></g><g><title>libsystem_kernel.dylib`mach_absolute_time (1 samples, 0.08%)</title><rect x="77.0850%" y="37" width="0.0779%" height="15" fill="rgb(218,138,4)" fg:x="989" fg:w="1"/><text x="77.3350%" y="47.50"></text></g><g><title>libdispatch.dylib`_dispatch_timeout (1 samples, 0.08%)</title><rect x="77.1629%" y="53" width="0.0779%" height="15" fill="rgb(250,191,14)" fg:x="990" fg:w="1"/><text x="77.4129%" y="63.50"></text></g><g><title>libdispatch.dylib`_dispatch_semaphore_wait_slow (229 samples, 17.85%)</title><rect x="76.6952%" y="69" width="17.8488%" height="15" fill="rgb(239,60,40)" fg:x="984" fg:w="229"/><text x="76.9452%" y="79.50">libdispatch.dylib`_dispatch_..</text></g><g><title>libsystem_kernel.dylib`semaphore_timedwait_trap (222 samples, 17.30%)</title><rect x="77.2408%" y="53" width="17.3032%" height="15" fill="rgb(206,27,48)" fg:x="991" fg:w="222"/><text x="77.4908%" y="63.50">libsystem_kernel.dylib`sema..</text></g><g><title>osprey.bundle`crossbeam_channel::flavors::list::Channel&lt;T&gt;::recv::_{{closure}} (258 samples, 20.11%)</title><rect x="74.6687%" y="101" width="20.1091%" height="15" fill="rgb(225,35,8)" fg:x="958" fg:w="258"/><text x="74.9187%" y="111.50">osprey.bundle`crossbeam_channel:..</text></g><g><title>osprey.bundle`std::thread::park_timeout (234 samples, 18.24%)</title><rect x="76.5394%" y="85" width="18.2385%" height="15" fill="rgb(250,213,24)" fg:x="982" fg:w="234"/><text x="76.7894%" y="95.50">osprey.bundle`std::thread::p..</text></g><g><title>libsystem_kernel.dylib`mach_absolute_time (3 samples, 0.23%)</title><rect x="94.5440%" y="69" width="0.2338%" height="15" fill="rgb(247,123,22)" fg:x="1213" fg:w="3"/><text x="94.7940%" y="79.50"></text></g><g><title>osprey.bundle`crossbeam_channel::flavors::list::Channel&lt;T&gt;::start_recv (4 samples, 0.31%)</title><rect x="94.7779%" y="101" width="0.3118%" height="15" fill="rgb(231,138,38)" fg:x="1216" fg:w="4"/><text x="95.0279%" y="111.50"></text></g><g><title>libsystem_c.dylib`clock_gettime_nsec_np (1 samples, 0.08%)</title><rect x="95.1676%" y="69" width="0.0779%" height="15" fill="rgb(231,145,46)" fg:x="1221" fg:w="1"/><text x="95.4176%" y="79.50"></text></g><g><title>osprey.bundle`std::sys::pal::unix::time::Timespec::now (4 samples, 0.31%)</title><rect x="95.0896%" y="101" width="0.3118%" height="15" fill="rgb(251,118,11)" fg:x="1220" fg:w="4"/><text x="95.3396%" y="111.50"></text></g><g><title>libsystem_c.dylib`clock_gettime (3 samples, 0.23%)</title><rect x="95.1676%" y="85" width="0.2338%" height="15" fill="rgb(217,147,25)" fg:x="1221" fg:w="3"/><text x="95.4176%" y="95.50"></text></g><g><title>libsystem_kernel.dylib`mach_absolute_time (2 samples, 0.16%)</title><rect x="95.2455%" y="69" width="0.1559%" height="15" fill="rgb(247,81,37)" fg:x="1222" fg:w="2"/><text x="95.4955%" y="79.50"></text></g><g><title>osprey.bundle`crossbeam_channel::flavors::list::Channel&lt;T&gt;::recv (1,166 samples, 90.88%)</title><rect x="4.5986%" y="117" width="90.8807%" height="15" fill="rgb(209,12,38)" fg:x="59" fg:w="1166"/><text x="4.8486%" y="127.50">osprey.bundle`crossbeam_channel::flavors::list::Channel&lt;T&gt;::recv</text></g><g><title>osprey.bundle`std::time::Instant::now (1 samples, 0.08%)</title><rect x="95.4014%" y="101" width="0.0779%" height="15" fill="rgb(227,1,9)" fg:x="1224" fg:w="1"/><text x="95.6514%" y="111.50"></text></g><g><title>osprey.bundle`crossbeam_channel::flavors::list::Channel&lt;T&gt;::start_recv (2 samples, 0.16%)</title><rect x="95.4793%" y="117" width="0.1559%" height="15" fill="rgb(248,47,43)" fg:x="1225" fg:w="2"/><text x="95.7293%" y="127.50"></text></g><g><title>libsystem_c.dylib`clock_gettime_nsec_np (1 samples, 0.08%)</title><rect x="95.6352%" y="85" width="0.0779%" height="15" fill="rgb(221,10,30)" fg:x="1227" fg:w="1"/><text x="95.8852%" y="95.50"></text></g><g><title>osprey.bundle`crossbeam_channel::channel::Receiver&lt;T&gt;::recv_timeout (1,182 samples, 92.13%)</title><rect x="4.2868%" y="133" width="92.1278%" height="15" fill="rgb(210,229,1)" fg:x="55" fg:w="1182"/><text x="4.5368%" y="143.50">osprey.bundle`crossbeam_channel::channel::Receiver&lt;T&gt;::recv_timeout</text></g><g><title>osprey.bundle`std::sys::pal::unix::time::Timespec::now (10 samples, 0.78%)</title><rect x="95.6352%" y="117" width="0.7794%" height="15" fill="rgb(222,148,37)" fg:x="1227" fg:w="10"/><text x="95.8852%" y="127.50"></text></g><g><title>libsystem_c.dylib`clock_gettime (10 samples, 0.78%)</title><rect x="95.6352%" y="101" width="0.7794%" height="15" fill="rgb(234,67,33)" fg:x="1227" fg:w="10"/><text x="95.8852%" y="111.50"></text></g><g><title>libsystem_kernel.dylib`mach_absolute_time (9 samples, 0.70%)</title><rect x="95.7132%" y="85" width="0.7015%" height="15" fill="rgb(247,98,35)" fg:x="1228" fg:w="9"/><text x="95.9632%" y="95.50"></text></g><g><title>libruby.3.4.dylib`rb_nogvl (1,224 samples, 95.40%)</title><rect x="1.0912%" y="165" width="95.4014%" height="15" fill="rgb(247,138,52)" fg:x="14" fg:w="1224"/><text x="1.3412%" y="175.50">libruby.3.4.dylib`rb_nogvl</text></g><g><title>osprey.bundle`osprey::gather_requests_no_gvl (1,189 samples, 92.67%)</title><rect x="3.8192%" y="149" width="92.6734%" height="15" fill="rgb(213,79,30)" fg:x="49" fg:w="1189"/><text x="4.0692%" y="159.50">osprey.bundle`osprey::gather_requests_no_gvl</text></g><g><title>osprey.bundle`crossbeam_channel::channel::Receiver&lt;T&gt;::try_recv (1 samples, 0.08%)</title><rect x="96.4147%" y="133" width="0.0779%" height="15" fill="rgb(246,177,23)" fg:x="1237" fg:w="1"/><text x="96.6647%" y="143.50"></text></g><g><title>libsystem_kernel.dylib`sigprocmask (22 samples, 1.71%)</title><rect x="96.4926%" y="165" width="1.7147%" height="15" fill="rgb(230,62,27)" fg:x="1238" fg:w="22"/><text x="96.7426%" y="175.50"></text></g><g><title>libsystem_malloc.dylib`DYLD-STUB$$_platform_memset (3 samples, 0.23%)</title><rect x="98.2073%" y="165" width="0.2338%" height="15" fill="rgb(216,154,8)" fg:x="1260" fg:w="3"/><text x="98.4573%" y="175.50"></text></g><g><title>libsystem_malloc.dylib`small_size (2 samples, 0.16%)</title><rect x="98.4412%" y="149" width="0.1559%" height="15" fill="rgb(244,35,45)" fg:x="1263" fg:w="2"/><text x="98.6912%" y="159.50"></text></g><g><title>libsystem_malloc.dylib`find_zone_and_free (5 samples, 0.39%)</title><rect x="98.4412%" y="165" width="0.3897%" height="15" fill="rgb(251,115,12)" fg:x="1263" fg:w="5"/><text x="98.6912%" y="175.50"></text></g><g><title>libsystem_malloc.dylib`szone_size (3 samples, 0.23%)</title><rect x="98.5970%" y="149" width="0.2338%" height="15" fill="rgb(240,54,50)" fg:x="1265" fg:w="3"/><text x="98.8470%" y="159.50"></text></g><g><title>libsystem_malloc.dylib`tiny_size (3 samples, 0.23%)</title><rect x="98.5970%" y="133" width="0.2338%" height="15" fill="rgb(233,84,52)" fg:x="1265" fg:w="3"/><text x="98.8470%" y="143.50"></text></g><g><title>libsystem_malloc.dylib`free_small (1 samples, 0.08%)</title><rect x="98.8309%" y="165" width="0.0779%" height="15" fill="rgb(207,117,47)" fg:x="1268" fg:w="1"/><text x="99.0809%" y="175.50"></text></g><g><title>libsystem_malloc.dylib`free_tiny (3 samples, 0.23%)</title><rect x="98.9088%" y="165" width="0.2338%" height="15" fill="rgb(249,43,39)" fg:x="1269" fg:w="3"/><text x="99.1588%" y="175.50"></text></g><g><title>libsystem_malloc.dylib`nanov2_size (4 samples, 0.31%)</title><rect x="99.1426%" y="165" width="0.3118%" height="15" fill="rgb(209,38,44)" fg:x="1272" fg:w="4"/><text x="99.3926%" y="175.50"></text></g><g><title>libsystem_malloc.dylib`szone_size (1 samples, 0.08%)</title><rect x="99.4544%" y="165" width="0.0779%" height="15" fill="rgb(236,212,23)" fg:x="1276" fg:w="1"/><text x="99.7044%" y="175.50"></text></g><g><title>libsystem_platform.dylib`DYLD-STUB$$sigprocmask (1 samples, 0.08%)</title><rect x="99.5323%" y="165" width="0.0779%" height="15" fill="rgb(242,79,21)" fg:x="1277" fg:w="1"/><text x="99.7823%" y="175.50"></text></g><g><title>all (1,283 samples, 100%)</title><rect x="0.0000%" y="341" width="100.0000%" height="15" fill="rgb(211,96,35)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="351.50"></text></g><g><title>libruby.3.4.dylib`fiber_entry (1,283 samples, 100.00%)</title><rect x="0.0000%" y="325" width="100.0000%" height="15" fill="rgb(253,215,40)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="335.50">libruby.3.4.dylib`fiber_entry</text></g><g><title>libruby.3.4.dylib`fiber_pool_expand (1,283 samples, 100.00%)</title><rect x="0.0000%" y="309" width="100.0000%" height="15" fill="rgb(211,81,21)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="319.50">libruby.3.4.dylib`fiber_pool_expand</text></g><g><title>libruby.3.4.dylib`rb_fiber_start (1,283 samples, 100.00%)</title><rect x="0.0000%" y="293" width="100.0000%" height="15" fill="rgb(208,190,38)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="303.50">libruby.3.4.dylib`rb_fiber_start</text></g><g><title>libruby.3.4.dylib`vm_invoke_proc (1,283 samples, 100.00%)</title><rect x="0.0000%" y="277" width="100.0000%" height="15" fill="rgb(235,213,38)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="287.50">libruby.3.4.dylib`vm_invoke_proc</text></g><g><title>libruby.3.4.dylib`rb_vm_exec (1,283 samples, 100.00%)</title><rect x="0.0000%" y="261" width="100.0000%" height="15" fill="rgb(237,122,38)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="271.50">libruby.3.4.dylib`rb_vm_exec</text></g><g><title>libruby.3.4.dylib`vm_exec_core (1,283 samples, 100.00%)</title><rect x="0.0000%" y="245" width="100.0000%" height="15" fill="rgb(244,218,35)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="255.50">libruby.3.4.dylib`vm_exec_core</text></g><g><title>libruby.3.4.dylib`vm_invoke_ifunc_block (1,283 samples, 100.00%)</title><rect x="0.0000%" y="229" width="100.0000%" height="15" fill="rgb(240,68,47)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="239.50">libruby.3.4.dylib`vm_invoke_ifunc_block</text></g><g><title>libruby.3.4.dylib`vm_yield_with_cfunc (1,283 samples, 100.00%)</title><rect x="0.0000%" y="213" width="100.0000%" height="15" fill="rgb(210,16,53)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="223.50">libruby.3.4.dylib`vm_yield_with_cfunc</text></g><g><title>osprey.bundle`magnus::block::_&lt;impl magnus::api::Ruby&gt;::proc_from_fn::call (1,283 samples, 100.00%)</title><rect x="0.0000%" y="197" width="100.0000%" height="15" fill="rgb(235,124,12)" fg:x="0" fg:w="1283"/><text x="0.2500%" y="207.50">osprey.bundle`magnus::block::_&lt;impl magnus::api::Ruby&gt;::proc_from_fn::call</text></g><g><title>osprey.bundle`core::ops::function::impls::_&lt;impl core::ops::function::FnOnce&lt;A&gt; for &amp;mut F&gt;::call_once (1,274 samples, 99.30%)</title><rect x="0.7015%" y="181" width="99.2985%" height="15" fill="rgb(224,169,11)" fg:x="9" fg:w="1274"/><text x="0.9515%" y="191.50">osprey.bundle`core::ops::function::impls::_&lt;impl core::ops::function::FnOnce&lt;A&gt; for &amp;mut F&gt;::call_once</text></g><g><title>libsystem_platform.dylib`_platform_memset (5 samples, 0.39%)</title><rect x="99.6103%" y="165" width="0.3897%" height="15" fill="rgb(250,166,2)" fg:x="1278" fg:w="5"/><text x="99.8603%" y="175.50"></text></g></svg></svg>
Binary file
@@ -0,0 +1,8 @@
1
+ apply_osx_fork_safety_patch = [
2
+ ENV["OBJC_DISABLE_INITIALIZE_FORK_SAFETY"].nil?,
3
+ RUBY_PLATFORM =~ /darwin/ ,
4
+ !ENV.key?('OSPREY_DISABLE_AUTO_DISABLE_OBJ_FORK_SAFETY'),
5
+ $PROGRAM_NAME =~ %r{osprey$}
6
+ ].all?
7
+
8
+ exec(ENV.to_h.merge("OBJC_DISABLE_INITIALIZE_FORK_SAFETY" => "YES"), *[$PROGRAM_NAME] + ARGV) if apply_osx_fork_safety_patch
@@ -0,0 +1,22 @@
1
+ return unless defined?(::Rackup::Handler)
2
+
3
+ module Rack
4
+ module Handler
5
+ module Osprey
6
+ def self.run(app, options = {})
7
+ ::Osprey.start(
8
+ host: options.fetch(:host, "127.0.0.1"),
9
+ port: options.fetch(:port, 3001),
10
+ workers: options.fetch(:workers, 1),
11
+ threads: options.fetch(:threads, 1),
12
+ http_port: options.fetch(:http_port, 3000),
13
+ cert_path: "/Users/pico/Development/osprey/server.cert",
14
+ key_path: "/Users/pico/Development/osprey/server.key",
15
+ app: app
16
+ )
17
+ end
18
+ end
19
+ end
20
+ end
21
+ ::Rackup::Handler.register("osprey", Rack::Handler::Osprey)
22
+ ::Rackup::Handler.register("Osprey", Rack::Handler::Osprey)
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Osprey
4
+ VERSION = "0.1.0"
5
+ end
data/lib/osprey.rb ADDED
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "async"
4
+ require_relative "osprey/version"
5
+ require_relative "osprey/osprey"
6
+ require_relative "osprey/patches"
7
+ require_relative "osprey/rack/handler/osprey"
8
+ require "debug"
9
+
10
+ module Osprey
11
+ class Error < StandardError; end
12
+
13
+ MAX_CONCURRENT_FIBERS = 1000
14
+
15
+ def self.call(...)
16
+ @handler.call(to_env(...))
17
+ end
18
+
19
+ def self.to_env(
20
+ (query_string, remote_addr, path_info), script_name, method, host, scheme, version,
21
+ protocol, port, fd, headers, hijack_proc
22
+ )
23
+ env = {
24
+ "SERVER_SOFTWARE" => "Osprey",
25
+ "SCRIPT_NAME" => script_name,
26
+ "REQUEST_METHOD" => method,
27
+ "PATH_INFO" => path_info,
28
+ "QUERY_STRING" => query_string,
29
+ "REMOTE_ADDR" => remote_addr,
30
+ "SERVER_NAME" => host,
31
+ "SERVER_PORT" => port,
32
+ "SERVER_PROTOCOL" => protocol,
33
+ "HTTP_HOST" => host,
34
+ "HTTP_VERSION" => version,
35
+ "rack.url_scheme" => scheme,
36
+ "rack.hijack_enabled?" => true,
37
+ "rack.hijack" => hijack_proc,
38
+ "rack.protocol" => protocol,
39
+ "rack.input" => fd.positive? ? IO.new(fd, "rb") : StringIO.new,
40
+ "rack.errors" => $stderr,
41
+ "rack.multipart.buffer_size" => 16_384,
42
+ }.merge(
43
+ headers.transform_keys do |k|
44
+ case k
45
+ when "content-length" then "CONTENT_LENGTH"
46
+ when "content-type" then "CONTENT_TYPE"
47
+ when "authorization" then "AUTH_TYPE"
48
+ else "HTTP_#{k.upcase.tr("-", "_")}"
49
+ end
50
+ end
51
+ )
52
+ end
53
+ end
data/server.cert ADDED
Binary file
data/server.key ADDED
Binary file
@@ -0,0 +1,4 @@
1
+ module Osprey
2
+ VERSION: String
3
+ # See the writing guide of rbs: https://github.com/ruby/rbs#guides
4
+ end