Skip to content

Instantly share code, notes, and snippets.

@DevBrent
Last active December 14, 2024 21:28
Show Gist options
  • Save DevBrent/0ee8d6bbd0517223ac1f95d952bb33e2 to your computer and use it in GitHub Desktop.
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
// 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