3v324v23 commited on
Commit
e628e42
·
1 Parent(s): 2324f78

refactor: Split demo into 4 separate features with individual buttons

Browse files
Files changed (1) hide show
  1. index.js +81 -50
index.js CHANGED
@@ -23,56 +23,59 @@ const LARGE_JSON_PATH = path.join(DATA_DIR, 'large_data.json');
23
  // Global lock to prevent concurrent demos
24
  global.isDemoRunning = false;
25
 
26
- async function runDemo() {
27
- console.log('=== Node.js 性能优化与大文件处理演示 ===\n');
28
-
29
  try {
30
- // 1. Large File Processing Demo
31
- console.log('--- 1. 大文件流式处理 ---');
32
  const largeFileHandler = new LargeFileHandler(LARGE_FILE_PATH);
33
-
34
- // Generate 100k lines
35
- const lineCount = 100000;
36
  console.log(`正在生成测试数据 (${lineCount} 行)...`);
37
- await largeFileHandler.generateTestFile(lineCount);
38
-
39
- // Stream processing
40
  console.log('开始流式处理...');
41
  await largeFileHandler.processFileStream();
42
-
43
- console.log('\n--- 2. XML 处理 ---');
44
- // Generate XML
45
- const xmlContent = xmlJsonHandler.generateXml(1000);
 
 
 
 
 
 
 
46
  fs.writeFileSync(XML_FILE_PATH, xmlContent);
47
  console.log(`XML 文件已保存: ${XML_FILE_PATH}`);
48
-
49
- // Parse XML
50
  const parsedXml = xmlJsonHandler.parseXml(xmlContent);
51
  console.log('XML 解析完成');
52
-
53
- console.log('\n--- 3. JSON 大文件流式处理 ---');
54
- // Generate large JSON
 
 
 
 
 
 
 
55
  console.log('正在生成 JSON 数据...');
56
  await xmlJsonHandler.generateLargeJson(LARGE_JSON_PATH, 10000);
57
-
58
- // Stream parse JSON
59
  console.log('开始流式解析 JSON...');
60
  await xmlJsonHandler.processLargeJsonStream(LARGE_JSON_PATH);
61
-
62
- console.log('\n=== 演示结束 ===');
63
-
64
- // Capture memory usage
65
- const used = process.memoryUsage();
66
- console.log('Memory Usage:');
67
- for (let key in used) {
68
- console.log(`${key}: ${Math.round(used[key] / 1024 / 1024 * 100) / 100} MB`);
69
- }
70
-
71
  } catch (err) {
72
  console.error('发生错误:', err);
73
  }
74
  }
75
 
 
 
 
 
 
 
 
 
76
  // Serve the main page
77
  app.get('/', (req, res) => {
78
  res.send(`
@@ -85,10 +88,14 @@ app.get('/', (req, res) => {
85
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background: #f0f2f5; padding: 40px; color: #333; }
86
  .container { max-width: 900px; margin: 0 auto; background: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
87
  h1 { color: #2c3e50; margin-bottom: 20px; border-bottom: 2px solid #eee; padding-bottom: 10px; }
88
- .controls { margin-bottom: 20px; display: flex; gap: 10px; }
89
- button { padding: 10px 20px; font-size: 16px; cursor: pointer; background: #007bff; color: white; border: none; border-radius: 5px; transition: background 0.3s; }
90
  button:hover { background: #0056b3; }
91
  button:disabled { background: #ccc; cursor: not-allowed; }
 
 
 
 
92
  #output { background: #1e1e1e; color: #d4d4d4; padding: 20px; border-radius: 5px; font-family: "Menlo", "Monaco", "Courier New", monospace; height: 500px; overflow-y: auto; white-space: pre-wrap; font-size: 14px; line-height: 1.5; border: 1px solid #333; }
93
  .status { margin-top: 10px; font-style: italic; color: #666; }
94
  </style>
@@ -97,21 +104,23 @@ app.get('/', (req, res) => {
97
  <div class="container">
98
  <h1>Node.js Performance Demo</h1>
99
  <div class="controls">
100
- <button id="runBtn" onclick="runDemo()"> 运行性能演示</button>
101
- <button onclick="getSystemInfo()" style="background: #28a745;">🖥 获取系统信息</button>
102
- <button onclick="clearOutput()" style="background: #6c757d;">🗑 清空输出</button>
 
 
103
  </div>
104
- <div id="output">等待操作...</div>
105
  <div id="status" class="status"></div>
106
  </div>
107
 
108
  <script>
109
  const outputDiv = document.getElementById('output');
110
  const statusDiv = document.getElementById('status');
111
- const runBtn = document.getElementById('runBtn');
112
 
113
  function log(msg, isError = false) {
114
- if (outputDiv.innerHTML === '等待操作...') {
115
  outputDiv.innerHTML = '';
116
  }
117
  const span = document.createElement('div');
@@ -122,18 +131,18 @@ app.get('/', (req, res) => {
122
  }
123
 
124
  function clearOutput() {
125
- outputDiv.innerHTML = '等待操作...';
126
  statusDiv.textContent = '';
127
  }
128
 
129
- function runDemo() {
130
- if (runBtn.disabled) return;
131
 
132
- runBtn.disabled = true;
 
133
  statusDiv.textContent = '正在运行演示...';
134
- outputDiv.innerHTML = ''; // Clear previous output
135
 
136
- const eventSource = new EventSource('/api/run-demo');
137
 
138
  eventSource.onmessage = function(event) {
139
  try {
@@ -144,7 +153,8 @@ app.get('/', (req, res) => {
144
  log(data.message, true);
145
  } else if (data.type === 'end') {
146
  eventSource.close();
147
- runBtn.disabled = false;
 
148
  statusDiv.textContent = '演示完成';
149
  }
150
  } catch (e) {
@@ -155,18 +165,25 @@ app.get('/', (req, res) => {
155
  eventSource.onerror = function(err) {
156
  console.error('EventSource failed:', err);
157
  eventSource.close();
158
- runBtn.disabled = false;
 
159
  statusDiv.textContent = '连接中断';
160
  log('Error: Connection to server lost.', true);
161
  };
162
  }
163
 
 
 
 
 
 
164
  async function getSystemInfo() {
 
165
  statusDiv.textContent = '正在获取系统信息...';
166
  try {
167
  const res = await fetch('/api/system-info');
168
  const text = await res.text();
169
- log('\\n=== 系统信息 ===');
170
  log(text);
171
  statusDiv.textContent = '获取成功';
172
  } catch (e) {
@@ -181,6 +198,8 @@ app.get('/', (req, res) => {
181
 
182
  // SSE Endpoint for running the demo
183
  app.get('/api/run-demo', async (req, res) => {
 
 
184
  if (global.isDemoRunning) {
185
  res.writeHead(200, {
186
  'Content-Type': 'text/event-stream',
@@ -222,7 +241,19 @@ app.get('/api/run-demo', async (req, res) => {
222
  };
223
 
224
  try {
225
- await runDemo();
 
 
 
 
 
 
 
 
 
 
 
 
226
  } catch (e) {
227
  console.error('Unhandled error:', e);
228
  } finally {
 
23
  // Global lock to prevent concurrent demos
24
  global.isDemoRunning = false;
25
 
26
+ // Feature 1: Large File Stream
27
+ async function runLargeFileDemo() {
28
+ console.log('=== 1. 大文件流式处理演示 ===');
29
  try {
 
 
30
  const largeFileHandler = new LargeFileHandler(LARGE_FILE_PATH);
31
+ const lineCount = 100000;
 
 
32
  console.log(`正在生成测试数据 (${lineCount} 行)...`);
33
+ await largeFileHandler.generateTestFile(lineCount);
 
 
34
  console.log('开始流式处理...');
35
  await largeFileHandler.processFileStream();
36
+ logMemoryUsage();
37
+ } catch (err) {
38
+ console.error('发生错误:', err);
39
+ }
40
+ }
41
+
42
+ // Feature 2: XML Processing
43
+ async function runXmlDemo() {
44
+ console.log('=== 2. XML 处理演示 ===');
45
+ try {
46
+ const xmlContent = xmlJsonHandler.generateXml(1000);
47
  fs.writeFileSync(XML_FILE_PATH, xmlContent);
48
  console.log(`XML 文件已保存: ${XML_FILE_PATH}`);
 
 
49
  const parsedXml = xmlJsonHandler.parseXml(xmlContent);
50
  console.log('XML 解析完成');
51
+ logMemoryUsage();
52
+ } catch (err) {
53
+ console.error('发生错误:', err);
54
+ }
55
+ }
56
+
57
+ // Feature 3: JSON Stream
58
+ async function runJsonDemo() {
59
+ console.log('=== 3. JSON 大文件流式处理演示 ===');
60
+ try {
61
  console.log('正在生成 JSON 数据...');
62
  await xmlJsonHandler.generateLargeJson(LARGE_JSON_PATH, 10000);
 
 
63
  console.log('开始流式解析 JSON...');
64
  await xmlJsonHandler.processLargeJsonStream(LARGE_JSON_PATH);
65
+ logMemoryUsage();
 
 
 
 
 
 
 
 
 
66
  } catch (err) {
67
  console.error('发生错误:', err);
68
  }
69
  }
70
 
71
+ function logMemoryUsage() {
72
+ const used = process.memoryUsage();
73
+ console.log('Memory Usage:');
74
+ for (let key in used) {
75
+ console.log(`${key}: ${Math.round(used[key] / 1024 / 1024 * 100) / 100} MB`);
76
+ }
77
+ }
78
+
79
  // Serve the main page
80
  app.get('/', (req, res) => {
81
  res.send(`
 
88
  body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif; background: #f0f2f5; padding: 40px; color: #333; }
89
  .container { max-width: 900px; margin: 0 auto; background: #fff; padding: 30px; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
90
  h1 { color: #2c3e50; margin-bottom: 20px; border-bottom: 2px solid #eee; padding-bottom: 10px; }
91
+ .controls { margin-bottom: 20px; display: grid; grid-template-columns: repeat(2, 1fr); gap: 15px; }
92
+ button { padding: 15px; font-size: 16px; cursor: pointer; background: #007bff; color: white; border: none; border-radius: 5px; transition: background 0.3s; font-weight: bold; }
93
  button:hover { background: #0056b3; }
94
  button:disabled { background: #ccc; cursor: not-allowed; }
95
+ .btn-system { background: #28a745; }
96
+ .btn-system:hover { background: #218838; }
97
+ .btn-clear { background: #6c757d; grid-column: span 2; }
98
+ .btn-clear:hover { background: #5a6268; }
99
  #output { background: #1e1e1e; color: #d4d4d4; padding: 20px; border-radius: 5px; font-family: "Menlo", "Monaco", "Courier New", monospace; height: 500px; overflow-y: auto; white-space: pre-wrap; font-size: 14px; line-height: 1.5; border: 1px solid #333; }
100
  .status { margin-top: 10px; font-style: italic; color: #666; }
101
  </style>
 
104
  <div class="container">
105
  <h1>Node.js Performance Demo</h1>
106
  <div class="controls">
107
+ <button onclick="runDemo('large-file')">📄 1. 大文件流式处理</button>
108
+ <button onclick="runDemo('xml')">🏷️ 2. XML 解析处理</button>
109
+ <button onclick="runDemo('json')">📦 3. JSON 流式解析</button>
110
+ <button onclick="getSystemInfo()" class="btn-system">🖥️ 4. 系统信息 (child_process)</button>
111
+ <button onclick="clearOutput()" class="btn-clear">🗑 清空输出</button>
112
  </div>
113
+ <div id="output">点击上方按钮开始测试...</div>
114
  <div id="status" class="status"></div>
115
  </div>
116
 
117
  <script>
118
  const outputDiv = document.getElementById('output');
119
  const statusDiv = document.getElementById('status');
120
+ let isRunning = false;
121
 
122
  function log(msg, isError = false) {
123
+ if (outputDiv.innerHTML === '点击上方按钮开始测试...') {
124
  outputDiv.innerHTML = '';
125
  }
126
  const span = document.createElement('div');
 
131
  }
132
 
133
  function clearOutput() {
134
+ outputDiv.innerHTML = '点击上方按钮开始测试...';
135
  statusDiv.textContent = '';
136
  }
137
 
138
+ function runDemo(type) {
139
+ if (isRunning) return;
140
 
141
+ isRunning = true;
142
+ updateButtons(true);
143
  statusDiv.textContent = '正在运行演示...';
 
144
 
145
+ const eventSource = new EventSource('/api/run-demo?type=' + type);
146
 
147
  eventSource.onmessage = function(event) {
148
  try {
 
153
  log(data.message, true);
154
  } else if (data.type === 'end') {
155
  eventSource.close();
156
+ isRunning = false;
157
+ updateButtons(false);
158
  statusDiv.textContent = '演示完成';
159
  }
160
  } catch (e) {
 
165
  eventSource.onerror = function(err) {
166
  console.error('EventSource failed:', err);
167
  eventSource.close();
168
+ isRunning = false;
169
+ updateButtons(false);
170
  statusDiv.textContent = '连接中断';
171
  log('Error: Connection to server lost.', true);
172
  };
173
  }
174
 
175
+ function updateButtons(disabled) {
176
+ const btns = document.querySelectorAll('button:not(.btn-clear)');
177
+ btns.forEach(btn => btn.disabled = disabled);
178
+ }
179
+
180
  async function getSystemInfo() {
181
+ if (isRunning) return;
182
  statusDiv.textContent = '正在获取系统信息...';
183
  try {
184
  const res = await fetch('/api/system-info');
185
  const text = await res.text();
186
+ log('\\n=== 4. 系统信息 ===');
187
  log(text);
188
  statusDiv.textContent = '获取成功';
189
  } catch (e) {
 
198
 
199
  // SSE Endpoint for running the demo
200
  app.get('/api/run-demo', async (req, res) => {
201
+ const type = req.query.type;
202
+
203
  if (global.isDemoRunning) {
204
  res.writeHead(200, {
205
  'Content-Type': 'text/event-stream',
 
241
  };
242
 
243
  try {
244
+ switch (type) {
245
+ case 'large-file':
246
+ await runLargeFileDemo();
247
+ break;
248
+ case 'xml':
249
+ await runXmlDemo();
250
+ break;
251
+ case 'json':
252
+ await runJsonDemo();
253
+ break;
254
+ default:
255
+ console.log('未知的任务类型');
256
+ }
257
  } catch (e) {
258
  console.error('Unhandled error:', e);
259
  } finally {