mirror of
https://github.com/lighttransport/tinyusdz.git
synced 2026-01-18 01:11:17 +01:00
Add memory management and load-only options for JS/WASM
- Add reset() and getMemoryStats() to TinyUSDZLoaderNative (binding.cc) - reset() clears render scene, layers, assets, and all cached data - getMemoryStats() returns memory usage statistics for debugging - Update clearScene() in materialx.js to properly free memory on reload - Dispose Three.js geometries, materials, and textures - Call nativeLoader.reset() to free WASM memory - Reset GUI state for normal display mode - Add command line argument support to load-test-node.js - Add new options to test-stream-load.js: - --load-only: Load USD as Layer only (no scene conversion) - --compare-modes: Compare load-only vs full load performance - Fix --compare to clear memory between tests with reset() and GC - Add memory usage reporting to all examples 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2864,6 +2864,69 @@ class TinyUSDZLoaderNative {
|
||||
em_resolver_.clear();
|
||||
}
|
||||
|
||||
/// Reset all state - clears render scene, assets, and all cached data
|
||||
/// Call this before loading a new USD file to free memory
|
||||
void reset() {
|
||||
// Clear loaded flag
|
||||
loaded_ = false;
|
||||
loaded_as_layer_ = false;
|
||||
composited_ = false;
|
||||
|
||||
// Clear strings
|
||||
filename_.clear();
|
||||
warn_.clear();
|
||||
error_.clear();
|
||||
|
||||
// Clear render scene (meshes, materials, textures, buffers, etc.)
|
||||
render_scene_ = tinyusdz::tydra::RenderScene();
|
||||
|
||||
// Clear layers
|
||||
layer_ = tinyusdz::Layer();
|
||||
composed_layer_ = tinyusdz::Layer();
|
||||
|
||||
// Clear USDZ asset
|
||||
usdz_asset_ = tinyusdz::USDZAsset();
|
||||
|
||||
// Clear asset resolver cache
|
||||
em_resolver_.clear();
|
||||
|
||||
// Clear reordered mesh cache
|
||||
reordered_mesh_cache_.clear();
|
||||
|
||||
// Reset parsing progress
|
||||
parsing_progress_.reset();
|
||||
}
|
||||
|
||||
/// Get memory usage statistics
|
||||
emscripten::val getMemoryStats() const {
|
||||
emscripten::val stats = emscripten::val::object();
|
||||
|
||||
// Count meshes
|
||||
stats.set("numMeshes", static_cast<int>(render_scene_.meshes.size()));
|
||||
stats.set("numMaterials", static_cast<int>(render_scene_.materials.size()));
|
||||
stats.set("numTextures", static_cast<int>(render_scene_.textures.size()));
|
||||
stats.set("numImages", static_cast<int>(render_scene_.images.size()));
|
||||
stats.set("numBuffers", static_cast<int>(render_scene_.buffers.size()));
|
||||
stats.set("numNodes", static_cast<int>(render_scene_.nodes.size()));
|
||||
stats.set("numLights", static_cast<int>(render_scene_.lights.size()));
|
||||
|
||||
// Estimate buffer memory
|
||||
size_t bufferMemory = 0;
|
||||
for (const auto &buf : render_scene_.buffers) {
|
||||
bufferMemory += buf.data.size();
|
||||
}
|
||||
stats.set("bufferMemoryBytes", static_cast<double>(bufferMemory));
|
||||
stats.set("bufferMemoryMB", static_cast<double>(bufferMemory) / (1024.0 * 1024.0));
|
||||
|
||||
// Asset cache count
|
||||
stats.set("assetCacheCount", static_cast<int>(em_resolver_.cache.size()));
|
||||
|
||||
// Reordered mesh cache count
|
||||
stats.set("reorderedMeshCacheCount", static_cast<int>(reordered_mesh_cache_.size()));
|
||||
|
||||
return stats;
|
||||
}
|
||||
|
||||
void setAsset(const std::string &name, const std::string &binary) {
|
||||
em_resolver_.add(name, binary);
|
||||
}
|
||||
@@ -3844,6 +3907,10 @@ EMSCRIPTEN_BINDINGS(tinyusdz_module) {
|
||||
&TinyUSDZLoaderNative::assetExists)
|
||||
.function("clearAssets",
|
||||
&TinyUSDZLoaderNative::clearAssets)
|
||||
.function("reset",
|
||||
&TinyUSDZLoaderNative::reset)
|
||||
.function("getMemoryStats",
|
||||
&TinyUSDZLoaderNative::getMemoryStats)
|
||||
|
||||
.function("layerToString",
|
||||
&TinyUSDZLoaderNative::layerToString)
|
||||
|
||||
@@ -123,7 +123,24 @@ function checkMemory64Support() {
|
||||
|
||||
console.log("memory64:", checkMemory64Support());
|
||||
|
||||
const usd_filename = "../../models/suzanne-subd-lv4.usdc";
|
||||
// Parse command line arguments
|
||||
const args = process.argv.slice(2);
|
||||
if (args.length === 0) {
|
||||
console.log('Usage: node load-test-node.js <path-to-usd-file>');
|
||||
console.log('');
|
||||
console.log('Examples:');
|
||||
console.log(' node load-test-node.js model.usdz');
|
||||
console.log(' node load-test-node.js ../../models/suzanne-subd-lv4.usdc');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const usd_filename = args[0];
|
||||
|
||||
// Check if file exists
|
||||
if (!fs.existsSync(usd_filename)) {
|
||||
console.error(`Error: File not found: ${usd_filename}`);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
async function initScene() {
|
||||
|
||||
@@ -134,11 +151,17 @@ async function initScene() {
|
||||
|
||||
// Option 1: Use traditional file loading (existing method)
|
||||
console.log("\n=== Traditional file loading ===");
|
||||
console.log(`File: ${usd_filename}`);
|
||||
const f = loadFile(usd_filename);
|
||||
if (!f) {
|
||||
console.error('Failed to load file');
|
||||
process.exit(1);
|
||||
}
|
||||
const url = URL.createObjectURL(f);
|
||||
//const usd = await loader.loadTestAsync(url);
|
||||
const usd = await loader.loadAsync(url);
|
||||
//console.log("Traditional loading completed");
|
||||
console.log("Load completed");
|
||||
reportMemUsage();
|
||||
|
||||
/*
|
||||
@@ -183,4 +206,7 @@ Object [WebAssembly] {
|
||||
*/
|
||||
|
||||
|
||||
initScene();
|
||||
initScene().catch(err => {
|
||||
console.error('Error:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
|
||||
@@ -602,24 +602,96 @@ async function reloadMaterials() {
|
||||
}
|
||||
|
||||
function clearScene() {
|
||||
// If showing normals, the mesh materials are MeshNormalMaterial instances
|
||||
// and the original materials are stored in originalMaterialsMap
|
||||
// Dispose the normal materials first before clearing sceneRoot
|
||||
if (showingNormals && sceneRoot) {
|
||||
sceneRoot.traverse(obj => {
|
||||
if (obj.isMesh && obj.material) {
|
||||
// This is a MeshNormalMaterial - dispose it
|
||||
if (obj.material.dispose) {
|
||||
obj.material.dispose();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
originalMaterialsMap.clear();
|
||||
showingNormals = false;
|
||||
// Reset GUI checkbox state to match
|
||||
if (settings.showNormals) {
|
||||
settings.showNormals = false;
|
||||
// Update GUI if it exists
|
||||
if (gui) {
|
||||
gui.controllersRecursive().forEach(controller => {
|
||||
if (controller.property === 'showNormals') {
|
||||
controller.updateDisplay();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Clear Three.js scene objects
|
||||
if (sceneRoot) {
|
||||
sceneRoot.traverse(obj => {
|
||||
if (obj.isMesh) {
|
||||
obj.geometry?.dispose();
|
||||
// Dispose material if not already disposed (when not in normal mode)
|
||||
if (obj.material && obj.material.dispose) {
|
||||
if (Array.isArray(obj.material)) {
|
||||
obj.material.forEach(m => m.dispose());
|
||||
} else {
|
||||
obj.material.dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
scene.remove(sceneRoot);
|
||||
sceneRoot = null;
|
||||
}
|
||||
|
||||
currentMaterials.forEach(mat => mat.dispose());
|
||||
// Clear material references (already disposed above)
|
||||
currentMaterials = [];
|
||||
materialData = [];
|
||||
|
||||
// Dispose textures in cache
|
||||
textureCache.forEach((texture) => {
|
||||
if (texture && texture.dispose) {
|
||||
texture.dispose();
|
||||
}
|
||||
});
|
||||
textureCache.clear();
|
||||
|
||||
// Reset upAxis to default
|
||||
currentFileUpAxis = 'Y';
|
||||
currentSceneMetadata = null;
|
||||
|
||||
// Clear WASM memory - reset the native loader to free render scene, assets, etc.
|
||||
if (nativeLoader) {
|
||||
// Log memory stats before clearing (for debugging)
|
||||
try {
|
||||
const stats = nativeLoader.getMemoryStats();
|
||||
console.log('Memory before reset:', stats);
|
||||
} catch (e) {
|
||||
// getMemoryStats may not exist in older builds
|
||||
}
|
||||
|
||||
// Reset WASM state to free memory
|
||||
try {
|
||||
nativeLoader.reset();
|
||||
console.log('WASM memory reset complete');
|
||||
} catch (e) {
|
||||
// reset() may not exist in older builds, try clearAssets as fallback
|
||||
try {
|
||||
nativeLoader.clearAssets();
|
||||
console.log('WASM assets cleared (fallback)');
|
||||
} catch (e2) {
|
||||
console.warn('Could not clear WASM memory:', e2);
|
||||
}
|
||||
}
|
||||
|
||||
// Set to null to allow GC - a new instance will be created on next load
|
||||
nativeLoader = null;
|
||||
}
|
||||
}
|
||||
|
||||
function fitCameraToScene() {
|
||||
|
||||
@@ -9,6 +9,16 @@
|
||||
|
||||
import { TinyUSDZLoader } from './src/tinyusdz/TinyUSDZLoader.js';
|
||||
|
||||
// ============================================================
|
||||
// Memory Usage Reporting (Node.js only)
|
||||
// ============================================================
|
||||
function reportMemUsage() {
|
||||
const used = process.memoryUsage();
|
||||
for (let key in used) {
|
||||
console.log(`${key}: ${Math.round(used[key] / 1024 / 1024 * 100) / 100} MB`);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Example 1: Stream fetch from URL (Browser/Node.js with fetch)
|
||||
// ============================================================
|
||||
@@ -43,6 +53,7 @@ async function exampleStreamFetch(url) {
|
||||
if (loadOk) {
|
||||
console.log('USD loaded successfully from cached asset!');
|
||||
console.log(`Total time: ${(performance.now() - startTime).toFixed(2)} ms`);
|
||||
reportMemUsage();
|
||||
} else {
|
||||
console.error('Failed to load USD:', usd.error());
|
||||
}
|
||||
@@ -89,6 +100,7 @@ async function exampleStreamFile(filePath) {
|
||||
if (loadOk) {
|
||||
console.log('USD loaded successfully from cached asset!');
|
||||
console.log(`Total time: ${(performance.now() - startTime).toFixed(2)} ms`);
|
||||
reportMemUsage();
|
||||
} else {
|
||||
console.error('Failed to load USD:', usd.error());
|
||||
}
|
||||
@@ -123,6 +135,7 @@ async function exampleLoadWithStreaming(url) {
|
||||
console.log('\n');
|
||||
console.log(`Total time: ${(performance.now() - startTime).toFixed(2)} ms`);
|
||||
console.log('USD object loaded:', usd ? 'success' : 'failed');
|
||||
reportMemUsage();
|
||||
|
||||
return usd;
|
||||
} catch (error) {
|
||||
@@ -164,6 +177,7 @@ async function exampleStreamMultiple(assets) {
|
||||
}
|
||||
|
||||
console.log(`Total time: ${(performance.now() - startTime).toFixed(2)} ms`);
|
||||
reportMemUsage();
|
||||
|
||||
return results;
|
||||
} catch (error) {
|
||||
@@ -173,7 +187,137 @@ async function exampleStreamMultiple(assets) {
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Example 5: Compare streaming vs traditional loading
|
||||
// Example 5: USD Load Only (no scene conversion for Three.js)
|
||||
// ============================================================
|
||||
// This mode loads USD as a Layer only, without converting to RenderScene.
|
||||
// Useful for measuring pure USD parsing memory usage.
|
||||
async function exampleLoadOnly(filePath) {
|
||||
console.log('=== USD Load Only (No Scene Conversion) ===');
|
||||
console.log(`File: ${filePath}`);
|
||||
console.log('Mode: Layer-only parsing (no RenderScene conversion)');
|
||||
|
||||
const loader = new TinyUSDZLoader();
|
||||
await loader.init({ useMemory64: true });
|
||||
|
||||
const fs = await import('fs');
|
||||
const fileData = fs.readFileSync(filePath);
|
||||
const fileSizeMB = (fileData.length / (1024 * 1024)).toFixed(2);
|
||||
console.log(`File size: ${fileSizeMB} MB`);
|
||||
|
||||
const startTime = performance.now();
|
||||
|
||||
try {
|
||||
const usd = new loader.native_.TinyUSDZLoaderNative();
|
||||
|
||||
// Load as Layer only - no RenderScene conversion
|
||||
const loadOk = usd.loadAsLayerFromBinary(fileData, filePath);
|
||||
const loadTime = performance.now() - startTime;
|
||||
|
||||
if (loadOk) {
|
||||
console.log(`\nUSD Layer loaded successfully!`);
|
||||
console.log(`Load time: ${loadTime.toFixed(2)} ms`);
|
||||
|
||||
// Try to get memory stats if available
|
||||
try {
|
||||
const stats = usd.getMemoryStats();
|
||||
console.log('\nWASM Memory Stats:');
|
||||
console.log(` Meshes: ${stats.numMeshes} (should be 0 for layer-only)`);
|
||||
console.log(` Materials: ${stats.numMaterials}`);
|
||||
console.log(` Buffer Memory: ${stats.bufferMemoryMB?.toFixed(2) || 0} MB`);
|
||||
} catch (e) {
|
||||
// getMemoryStats may not exist
|
||||
}
|
||||
} else {
|
||||
console.error('Failed to load USD:', usd.error());
|
||||
}
|
||||
|
||||
console.log('\nNode.js Memory Usage:');
|
||||
reportMemUsage();
|
||||
|
||||
return { success: loadOk, loadTime };
|
||||
} catch (error) {
|
||||
console.error('Load only failed:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Example 6: Compare full load vs load-only
|
||||
// ============================================================
|
||||
async function exampleCompareLoadModes(filePath) {
|
||||
console.log('=== Compare Load Modes ===');
|
||||
console.log(`File: ${filePath}`);
|
||||
|
||||
const loader = new TinyUSDZLoader();
|
||||
await loader.init({ useMemory64: true });
|
||||
|
||||
const fs = await import('fs');
|
||||
const fileData = fs.readFileSync(filePath);
|
||||
const fileSizeMB = (fileData.length / (1024 * 1024)).toFixed(2);
|
||||
console.log(`File size: ${fileSizeMB} MB`);
|
||||
|
||||
// Mode 1: Load Only (Layer parsing, no scene conversion)
|
||||
console.log('\n--- Mode 1: Load Only (Layer) ---');
|
||||
const loadOnlyStart = performance.now();
|
||||
|
||||
const usd1 = new loader.native_.TinyUSDZLoaderNative();
|
||||
const ok1 = usd1.loadAsLayerFromBinary(fileData, filePath);
|
||||
const loadOnlyTime = performance.now() - loadOnlyStart;
|
||||
|
||||
console.log(` Load time: ${loadOnlyTime.toFixed(2)} ms`);
|
||||
console.log(` Load result: ${ok1 ? 'success' : 'failed'}`);
|
||||
console.log(' Memory (Layer only):');
|
||||
reportMemUsage();
|
||||
|
||||
// Reset for fair comparison
|
||||
usd1.reset();
|
||||
|
||||
// Force GC if available
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
console.log(' (GC triggered)');
|
||||
}
|
||||
|
||||
// Mode 2: Full Load (with RenderScene conversion)
|
||||
console.log('\n--- Mode 2: Full Load (with Scene Conversion) ---');
|
||||
const fullLoadStart = performance.now();
|
||||
|
||||
const usd2 = new loader.native_.TinyUSDZLoaderNative();
|
||||
const ok2 = usd2.loadFromBinary(fileData, filePath);
|
||||
const fullLoadTime = performance.now() - fullLoadStart;
|
||||
|
||||
console.log(` Load time: ${fullLoadTime.toFixed(2)} ms`);
|
||||
console.log(` Load result: ${ok2 ? 'success' : 'failed'}`);
|
||||
|
||||
// Get render scene stats
|
||||
try {
|
||||
const stats = usd2.getMemoryStats();
|
||||
console.log(' RenderScene Stats:');
|
||||
console.log(` Meshes: ${stats.numMeshes}`);
|
||||
console.log(` Materials: ${stats.numMaterials}`);
|
||||
console.log(` Textures: ${stats.numTextures}`);
|
||||
console.log(` Images: ${stats.numImages}`);
|
||||
console.log(` Buffers: ${stats.numBuffers}`);
|
||||
console.log(` Buffer Memory: ${stats.bufferMemoryMB?.toFixed(2) || 0} MB`);
|
||||
} catch (e) {
|
||||
// getMemoryStats may not exist
|
||||
}
|
||||
|
||||
console.log(' Memory (Full load):');
|
||||
reportMemUsage();
|
||||
|
||||
// Summary
|
||||
console.log('\n--- Summary ---');
|
||||
console.log(` Load Only (Layer): ${loadOnlyTime.toFixed(2)} ms`);
|
||||
console.log(` Full Load (RenderScene): ${fullLoadTime.toFixed(2)} ms`);
|
||||
console.log(` Scene conversion overhead: ${(fullLoadTime - loadOnlyTime).toFixed(2)} ms`);
|
||||
if (fullLoadTime > 0) {
|
||||
console.log(` Overhead ratio: ${((fullLoadTime / loadOnlyTime - 1) * 100).toFixed(1)}% slower`);
|
||||
}
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// Example 7: Compare streaming vs traditional loading
|
||||
// ============================================================
|
||||
async function exampleComparePerformance(filePath) {
|
||||
console.log('=== Performance Comparison ===');
|
||||
@@ -182,12 +326,15 @@ async function exampleComparePerformance(filePath) {
|
||||
const loader = new TinyUSDZLoader();
|
||||
await loader.init({ useMemory64: true });
|
||||
|
||||
const fs = await import('fs');
|
||||
|
||||
// Traditional loading (read entire file into JS, then copy to WASM)
|
||||
console.log('\n--- Traditional Loading ---');
|
||||
const traditionalStart = performance.now();
|
||||
|
||||
const fs = await import('fs');
|
||||
const fileData = fs.readFileSync(filePath);
|
||||
let fileData = fs.readFileSync(filePath);
|
||||
const fileSizeMB = (fileData.length / (1024 * 1024)).toFixed(2);
|
||||
console.log(` File size: ${fileSizeMB} MB`);
|
||||
const traditionalReadTime = performance.now() - traditionalStart;
|
||||
|
||||
const usd1 = new loader.native_.TinyUSDZLoaderNative();
|
||||
@@ -197,6 +344,43 @@ async function exampleComparePerformance(filePath) {
|
||||
console.log(` Read time: ${traditionalReadTime.toFixed(2)} ms`);
|
||||
console.log(` Total time: ${traditionalTotalTime.toFixed(2)} ms`);
|
||||
console.log(` Load result: ${ok1 ? 'success' : 'failed'}`);
|
||||
console.log(' Memory after traditional load:');
|
||||
reportMemUsage();
|
||||
|
||||
// Clear memory before streaming test for fair comparison
|
||||
console.log('\n--- Clearing Memory ---');
|
||||
|
||||
// Reset WASM memory (clear render scene, assets, caches)
|
||||
try {
|
||||
usd1.reset();
|
||||
console.log(' WASM memory reset');
|
||||
} catch (e) {
|
||||
// reset() may not exist in older builds
|
||||
try {
|
||||
usd1.clearAssets();
|
||||
console.log(' WASM assets cleared (fallback)');
|
||||
} catch (e2) {
|
||||
console.log(' Could not clear WASM memory');
|
||||
}
|
||||
}
|
||||
|
||||
// Clear JS file data reference
|
||||
fileData = null;
|
||||
|
||||
// Try to trigger garbage collection if available
|
||||
// Run with: node --expose-gc test-stream-load.js file.usd --compare
|
||||
if (global.gc) {
|
||||
global.gc();
|
||||
console.log(' GC triggered');
|
||||
} else {
|
||||
console.log(' GC not available (run with --expose-gc for manual GC)');
|
||||
}
|
||||
|
||||
// Small delay to allow GC to run
|
||||
await new Promise(resolve => setTimeout(resolve, 100));
|
||||
|
||||
console.log(' Memory after cleanup:');
|
||||
reportMemUsage();
|
||||
|
||||
// Streaming loading (chunks transferred directly to WASM)
|
||||
console.log('\n--- Streaming Loading ---');
|
||||
@@ -215,12 +399,15 @@ async function exampleComparePerformance(filePath) {
|
||||
console.log(` Transfer time: ${streamingTransferTime.toFixed(2)} ms`);
|
||||
console.log(` Total time: ${streamingTotalTime.toFixed(2)} ms`);
|
||||
console.log(` Load result: ${ok2 ? 'success' : 'failed'}`);
|
||||
console.log(' Memory after streaming load:');
|
||||
reportMemUsage();
|
||||
|
||||
// Summary
|
||||
console.log('\n--- Summary ---');
|
||||
console.log(` Traditional: ${traditionalTotalTime.toFixed(2)} ms`);
|
||||
console.log(` Streaming: ${streamingTotalTime.toFixed(2)} ms`);
|
||||
console.log(` Memory benefit: Streaming frees JS memory chunk-by-chunk`);
|
||||
console.log(' Note: Run with "node --expose-gc" for accurate memory comparison');
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
@@ -230,10 +417,18 @@ async function main() {
|
||||
const args = process.argv.slice(2);
|
||||
|
||||
if (args.length === 0) {
|
||||
console.log('Usage: node test-stream-load.js <path-to-usd-file> [--compare]');
|
||||
console.log('Usage: node test-stream-load.js <path-to-usd-file> [options]');
|
||||
console.log('');
|
||||
console.log('Options:');
|
||||
console.log(' --load-only Load USD only (no scene conversion) - measure pure parsing');
|
||||
console.log(' --compare-modes Compare load-only vs full load with scene conversion');
|
||||
console.log(' --compare Compare streaming vs traditional loading');
|
||||
console.log(' --url Treat input as URL (auto-detected for http/https)');
|
||||
console.log('');
|
||||
console.log('Examples:');
|
||||
console.log(' node test-stream-load.js model.usdz');
|
||||
console.log(' node test-stream-load.js model.usdz --load-only');
|
||||
console.log(' node test-stream-load.js model.usdz --compare-modes');
|
||||
console.log(' node test-stream-load.js model.usdz --compare');
|
||||
console.log(' node test-stream-load.js https://example.com/model.usdz --url');
|
||||
process.exit(1);
|
||||
@@ -242,6 +437,8 @@ async function main() {
|
||||
const input = args[0];
|
||||
const isUrl = args.includes('--url') || input.startsWith('http://') || input.startsWith('https://');
|
||||
const doCompare = args.includes('--compare');
|
||||
const doLoadOnly = args.includes('--load-only');
|
||||
const doCompareModes = args.includes('--compare-modes');
|
||||
|
||||
try {
|
||||
if (isUrl) {
|
||||
@@ -251,7 +448,11 @@ async function main() {
|
||||
await exampleLoadWithStreaming(input);
|
||||
} else {
|
||||
// File-based examples
|
||||
if (doCompare) {
|
||||
if (doLoadOnly) {
|
||||
await exampleLoadOnly(input);
|
||||
} else if (doCompareModes) {
|
||||
await exampleCompareLoadModes(input);
|
||||
} else if (doCompare) {
|
||||
await exampleComparePerformance(input);
|
||||
} else {
|
||||
await exampleStreamFile(input);
|
||||
@@ -277,5 +478,7 @@ export {
|
||||
exampleStreamFile,
|
||||
exampleLoadWithStreaming,
|
||||
exampleStreamMultiple,
|
||||
exampleLoadOnly,
|
||||
exampleCompareLoadModes,
|
||||
exampleComparePerformance
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user