Last active
December 14, 2024 21:28
-
-
Save DevBrent/0ee8d6bbd0517223ac1f95d952bb33e2 to your computer and use it in GitHub Desktop.
LFI with fewer logical leaps and minimal performance overhead per my personal experience with arrays smaller than 1.5 million
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Warning: This is primarily generated as a proof of concept for the sake of argument and has not been tested. | |
/* This program is free software. It comes without any warranty, to | |
* the extent permitted by applicable law. You can redistribute it | |
* and/or modify it under the terms of the WTFPL, Version 2, | |
* as published by Sam Hocevar. See http://www.wtfpl.net/ */ | |
/** | |
* Processes an array through multiple stages with concurrency limits. | |
* @param array - The input array to process. | |
* @param limit - Maximum number of concurrent tasks. | |
* @param stages - Array of functions, each representing a processing stage. | |
* @returns A promise resolving to the final processed array. | |
*/ | |
export async function processArrayWithStages<T>( | |
array: T[], | |
limit: number, | |
stages: Array<(item: T) => Promise<T>> | |
): Promise<T[]> { | |
// Use processItemThroughStages for concurrent stage processing | |
return processItemsConcurrently(array, limit, async (item) => { | |
let currentItem = item; | |
for (const stage of stages) { | |
currentItem = await stage(currentItem); | |
} | |
return currentItem; | |
}); | |
} | |
/** | |
* Processes items concurrently with a given limit and processing function. | |
* @param array - The input array to process. | |
* @param limit - Maximum number of concurrent tasks. | |
* @param processFn - Function to process each item. | |
* @returns A promise resolving to the processed array. | |
*/ | |
async function processItemsConcurrently<T>( | |
array: T[], | |
limit: number, | |
processFn: (item: T) => Promise<T> | |
): Promise<T[]> { | |
const results: T[] = []; | |
let currentIndex = 0; | |
const workers = Array.from({ length: limit }, async () => { | |
while (currentIndex < array.length) { | |
const index = currentIndex++; // Get the next item to process | |
results[index] = await processFn(array[index]); // Process the item and store result | |
} | |
}); | |
await Promise.all(workers); | |
return results; | |
} | |
// Example 1 From LFI | |
import { processArrayWithStages } from './your-module'; // Adjust the import as necessary | |
// Hypothetical delays for processing | |
const mapDelays = [5, 1, 1]; | |
const filterDelays = [1, 1, 5]; | |
// Helper function to simulate a delay | |
const delay = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms)); | |
// Mapping function with delay | |
const mapFn = async (i: number): Promise<number> => { | |
await delay(mapDelays[i] * 1000); | |
console.log(`Mapped: ${i}`); | |
return i * 2; // Example transformation | |
}; | |
// Filtering function with delay | |
const filterFn = async (i: number): Promise<number> => { | |
await delay(filterDelays[i] * 1000); | |
const keep = i % 2 === 0; // Example filter condition | |
console.log(`Filtered: ${i} (keep: ${keep})`); | |
if (keep) return i; | |
throw new Error('Filtered out'); | |
}; | |
// Wrapping the logic for filtering | |
const safeFilterFn = async (i: number): Promise<number> => { | |
try { | |
return await filterFn(i); | |
} catch { | |
// If filtered out, we can return undefined or skip | |
return undefined as unknown as number; // Ensure typing works | |
} | |
}; | |
// Example usage | |
(async () => { | |
const inputArray = [0, 1, 2]; | |
const limit = 2; // Max 2 concurrent tasks | |
console.time('processArrayWithStages'); | |
const result = await processArrayWithStages( | |
inputArray, | |
limit, | |
[ | |
mapFn, // Stage 1: Map | |
safeFilterFn, // Stage 2: Filter | |
] | |
); | |
console.timeEnd('processArrayWithStages'); | |
console.log('Final Result:', result.filter(Boolean)); // Remove undefined values | |
})(); | |
// Example 3: | |
async function exampleUsage() { | |
const animals = [ | |
{ species: 'sloth', name: 'strawberry', age: 7 }, | |
{ species: 'sloth', name: 'bitsy', age: 7 }, | |
{ species: 'sloth', name: 'max', age: 19 }, | |
{ species: 'sloth', name: 'tommy', age: 24 }, | |
{ species: 'elephant', name: 'dumbo', age: 10 }, | |
]; | |
// Define processing stages | |
const stages = [ | |
(animal: any) => Promise.resolve(animal.species === 'sloth' ? animal : null), // Filter sloths | |
(animal: any) => | |
Promise.resolve( | |
animal ? { age: animal.age, name: animal.name } : null | |
), // Map to age-name pair | |
]; | |
// Use processArrayWithStages to process animals | |
const processed = await processArrayWithStages(animals, 2, stages); | |
// Group results by age | |
const result = processed | |
.filter(Boolean) // Remove nulls | |
.reduce((map, item) => { | |
if (!map.has(item.age)) { | |
map.set(item.age, new Set()); | |
} | |
map.get(item.age).add(item.name); | |
return map; | |
}, new Map()); | |
console.log(result); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment