<commit_before>package net.ssehub.kernel_haven.fe_analysis.fes;

import static net.ssehub.kernel_haven.util.null_checks.NullHelpers.notNull;

import net.ssehub.kernel_haven.SetUpException;
import net.ssehub.kernel_haven.analysis.AnalysisComponent;
import net.ssehub.kernel_haven.config.Configuration;
import net.ssehub.kernel_haven.fe_analysis.pcs.PcFinder.VariableWithPcs;
import net.ssehub.kernel_haven.util.OrderPreservingParallelizer;
import net.ssehub.kernel_haven.util.ProgressLogger;
import net.ssehub.kernel_haven.util.null_checks.NonNull;

/**
 * A {@link FeatureEffectFinder} that utilizes multiple threads. This helps with performance if simplification takes
 * long.
 * 
 * @author Adam
 */
public class ThreadedFeatureEffectFinder extends FeatureEffectFinder {

    private static final int NUM_THREADS = 6;
    
    /**
     * Creates a new {@link ThreadedFeatureEffectFinder} for the given PC finder.
     * 
     * @param config The global configuration.
     * @param pcFinder The component to get the PCs from.
     * 
     * @throws SetUpException If creating this component fails.
     */
    public ThreadedFeatureEffectFinder(@NonNull Configuration config,
            @NonNull AnalysisComponent<VariableWithPcs> pcFinder) throws SetUpException {
        super(config, pcFinder);
    }
    
    @Override
    protected void execute() {
        ProgressLogger progress = new ProgressLogger(notNull(getClass().getSimpleName()));
        
        OrderPreservingParallelizer<VariableWithPcs, VariableWithFeatureEffect> parallelizer
            = new OrderPreservingParallelizer<>(this::processSingle, (result) -> {
                if (result != null) {
                    addResult(result);
                }
                
                progress.processedOne();
                
            }, NUM_THREADS);
        
        VariableWithPcs pcs;
        while ((pcs = pcFinder.getNextResult()) != null) {
            parallelizer.add(pcs);
        }
        
        parallelizer.end();
        parallelizer.join();
        
        progress.close();
    }

}<commit_msg>Make number of threads in ThreadedFeatureEffectFinder configurable<commit_after>package net.ssehub.kernel_haven.fe_analysis.fes;

import static net.ssehub.kernel_haven.util.null_checks.NullHelpers.notNull;

import net.ssehub.kernel_haven.SetUpException;
import net.ssehub.kernel_haven.analysis.AnalysisComponent;
import net.ssehub.kernel_haven.config.Configuration;
import net.ssehub.kernel_haven.config.Setting;
import net.ssehub.kernel_haven.config.Setting.Type;
import net.ssehub.kernel_haven.fe_analysis.pcs.PcFinder.VariableWithPcs;
import net.ssehub.kernel_haven.util.OrderPreservingParallelizer;
import net.ssehub.kernel_haven.util.ProgressLogger;
import net.ssehub.kernel_haven.util.null_checks.NonNull;

/**
 * A {@link FeatureEffectFinder} that utilizes multiple threads. This helps with performance if simplification takes
 * long.
 * 
 * @author Adam
 */
public class ThreadedFeatureEffectFinder extends FeatureEffectFinder {

    public static final @NonNull Setting<@NonNull Integer> THREAD_SETTING = new Setting<>(
            "analysis.fe_finder.threads", Type.INTEGER, true, "4", "Defines the number of threads the "
            + ThreadedFeatureEffectFinder.class.getSimpleName() + " should use.");
    
    private int numThreads;
    
    /**
     * Creates a new {@link ThreadedFeatureEffectFinder} for the given PC finder.
     * 
     * @param config The global configuration.
     * @param pcFinder The component to get the PCs from.
     * 
     * @throws SetUpException If creating this component fails.
     */
    public ThreadedFeatureEffectFinder(@NonNull Configuration config,
            @NonNull AnalysisComponent<VariableWithPcs> pcFinder) throws SetUpException {
        super(config, pcFinder);
        
        config.registerSetting(THREAD_SETTING);
        numThreads = config.getValue(THREAD_SETTING);
        
        if (numThreads < 1) {
            throw new SetUpException("Number of threads can't be " + numThreads);
        }
    }
    
    @Override
    protected void execute() {
        ProgressLogger progress = new ProgressLogger(notNull(getClass().getSimpleName()));
        
        OrderPreservingParallelizer<VariableWithPcs, VariableWithFeatureEffect> parallelizer
            = new OrderPreservingParallelizer<>(this::processSingle, (result) -> {
                if (result != null) {
                    addResult(result);
                }
                
                progress.processedOne();
                
            }, numThreads);
        
        VariableWithPcs pcs;
        while ((pcs = pcFinder.getNextResult()) != null) {
            parallelizer.add(pcs);
        }
        
        parallelizer.end();
        parallelizer.join();
        
        progress.close();
    }

}
{'fraction_non_alphanumeric': 0.08804123711340206, 'fraction_numerical': 0.0006185567010309278, 'mean_word_length': 2.813679245283019, 'pattern_counts': {'":': 0, '<': 12, '<?xml version=': 0, '>': 13, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2407382', 'n_tokens_mistral': 1345, 'n_tokens_neox': 1326, 'n_words': 281}