-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDemo.java
More file actions
144 lines (120 loc) · 7.34 KB
/
Demo.java
File metadata and controls
144 lines (120 loc) · 7.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
package fastspider;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.atomic.AtomicInteger;
/**
* Hero Demo — live terminal crawler using real Wikipedia pages.
* Showcases native WinHTTP fetching, Virtual Thread concurrency,
* and AVX2 link extraction with animated ANSI output.
*/
public class Demo {
private Demo() {}
// ── ANSI helpers ────────────────────────────────────────────────────────
private static final String R = "\033[0m";
private static final String B = "\033[1m";
private static final String CY = "\033[36m";
private static final String GR = "\033[32m";
private static final String YL = "\033[33m";
private static final String MG = "\033[35m";
private static final String RD = "\033[31m";
private static final String DM = "\033[90m"; // dim grey
private static final String ER = "\033[K"; // erase to end of line
private static final String[] SPIN = {"⠋","⠙","⠹","⠸","⠼","⠴","⠦","⠧","⠇","⠏"};
// ── Target URLs ─────────────────────────────────────────────────────────
private static final List<String> URLS = List.of(
"https://en.wikipedia.org/wiki/Java_(programming_language)",
"https://en.wikipedia.org/wiki/C%2B%2B",
"https://en.wikipedia.org/wiki/SIMD",
"https://en.wikipedia.org/wiki/Web_crawler",
"https://en.wikipedia.org/wiki/Just-in-time_compilation"
);
public static void main(String[] args) throws Exception {
banner();
FastSpider spider = FastSpider.open();
// ── Phase 1: live sequential ticker ─────────────────────────────────
header("Phase 1", "Sequential crawl — " + URLS.size() + " Wikipedia pages");
System.out.println();
List<FastSpider.SpiderResponse> sequential = new ArrayList<>();
long seqTotal = 0;
for (int i = 0; i < URLS.size(); i++) {
String url = URLS.get(i);
String label = shortLabel(url);
// pending line
System.out.printf("\r " + YL + "[%d/%d]" + R + " Fetching %-34s ..." + ER,
i + 1, URLS.size(), label);
System.out.flush();
long t0 = System.nanoTime();
FastSpider.SpiderResponse resp = spider.fetchAsync(url).join();
long ms = (System.nanoTime() - t0) / 1_000_000;
seqTotal += ms;
sequential.add(resp);
String tick = resp.isSuccess() ? GR + "✔" + R : RD + "✘" + R;
System.out.printf(
"\r " + YL + "[%d/%d]" + R + " %s %-34s " + GR + "%3d" + R + " " + CY + "%,5d ms" + R + " " + DM + "%,6d B" + R + ER + "\n",
i + 1, URLS.size(), tick, label, resp.statusCode(), ms, resp.rawBody().length);
}
System.out.println();
// ── Phase 2: concurrent batch with spinner ───────────────────────────
header("Phase 2", "Concurrent batch — same pages via Virtual Threads");
System.out.println();
AtomicInteger doneCount = new AtomicInteger(0);
long batchStart = System.currentTimeMillis();
List<CompletableFuture<FastSpider.SpiderResponse>> futures = new ArrayList<>();
for (String url : URLS) {
futures.add(spider.fetchAsync(url).whenComplete((r, t) -> doneCount.incrementAndGet()));
}
int s = 0;
while (doneCount.get() < URLS.size()) {
double elapsed = (System.currentTimeMillis() - batchStart) / 1000.0;
System.out.printf("\r " + CY + SPIN[s % SPIN.length] + R
+ " Crawling... " + GR + "%d" + R + "/" + URLS.size() + " pages done " + DM + "%.1fs" + R + ER,
doneCount.get(), elapsed);
System.out.flush();
Thread.sleep(80);
s++;
}
long batchMs = System.currentTimeMillis() - batchStart;
double speedup = (double) seqTotal / Math.max(1, batchMs);
System.out.printf("\r " + GR + "✔ Batch complete!" + R
+ " All %d pages in " + B + GR + "%d ms" + R
+ " " + DM + "(%.1fx faster than sequential)" + R + ER + "\n",
URLS.size(), batchMs, speedup);
System.out.println();
// ── Phase 3: link extraction ─────────────────────────────────────────
header("Phase 3", "AVX2 link extraction — \"Java (programming language)\"");
System.out.println();
FastSpider.SpiderResponse javaPage = sequential.get(0);
List<String> hrefs = spider.extractHrefs(javaPage.rawBody());
int shown = Math.min(hrefs.size(), 10);
for (int i = 0; i < shown; i++) {
System.out.println(" " + CY + "→" + R + " " + hrefs.get(i));
}
if (hrefs.size() > shown) {
System.out.println(" " + DM + " ... and " + (hrefs.size() - shown) + " more links" + R);
}
System.out.println();
// ── Footer ───────────────────────────────────────────────────────────
footer("FastSpider crawled " + URLS.size() + " real Wikipedia pages via native WinHTTP + Virtual Threads.");
}
// ── Helpers ─────────────────────────────────────────────────────────────
private static String shortLabel(String url) {
return url.substring(url.lastIndexOf('/') + 1)
.replace("%2B", "+")
.replace("_", " ");
}
private static void banner() {
System.out.println(MG + "═══════════════════════════════════════════════════════════════");
System.out.println(B + CY + " ⚡ FastSpider — Native WinHTTP + Virtual Thread Crawler" + R);
System.out.println(MG + "═══════════════════════════════════════════════════════════════" + R);
System.out.println();
}
private static void header(String phase, String msg) {
System.out.println(YL + B + "[" + phase + "]" + R + " " + msg);
}
private static void footer(String msg) {
System.out.println(MG + "═══════════════════════════════════════════════════════════════");
System.out.println(B + GR + " ✔ " + msg + R);
System.out.println(MG + "═══════════════════════════════════════════════════════════════" + R);
}
}