diff --git a/.gitignore b/.gitignore index 031b03e..a9e6d03 100644 --- a/.gitignore +++ b/.gitignore @@ -1,897 +1,38 @@ -# ============================================================================== -# COMPREHENSIVE .GITIGNORE TEMPLATE -# ============================================================================== -# This template covers most common development scenarios and tools -# Generated patterns use ** to match any subdirectory depth - -# ============================================================================== -# PYTHON -# ============================================================================== -**/__pycache__/ -**/*.py[cod] -**/*$py.class -**/*.so -**/.Python -**/build/ -**/develop-eggs/ -**/dist/ -**/downloads/ -**/eggs/ -**/.eggs/ -**/lib/ -**/lib64/ -**/parts/ -**/sdist/ -**/var/ -**/wheels/ -**/share/python-wheels/ -**/*.egg-info/ -**/.installed.cfg -**/*.egg -**/MANIFEST - -# PyInstaller -**/*.manifest -**/*.spec - -# Installer logs -**/pip-log.txt -**/pip-delete-this-directory.txt - -# Unit test / coverage reports -**/htmlcov/ -**/.tox/ -**/.nox/ -**/.coverage -**/.coverage.* -**/.cache -**/nosetests.xml -**/coverage.xml -**/*.cover -**/*.py,cover -**/.hypothesis/ -**/.pytest_cache/ -**/cover/ - -# Translations -**/*.mo -**/*.pot - -# Django stuff: -**/*.log -**/local_settings.py -**/db.sqlite3 -**/db.sqlite3-journal - -# Flask stuff: -**/instance/ -**/.webassets-cache - -# Scrapy stuff: -**/.scrapy - -# Sphinx documentation -**/docs/_build/ - -# PyBuilder -**/.pybuilder/ -**/target/ - -# Jupyter Notebook -**/.ipynb_checkpoints - -# IPython -**/profile_default/ -**/ipython_config.py - -# pyenv -**/.python-version - -# pipenv -**/Pipfile.lock - -# poetry -**/poetry.lock - -# pdm -**/.pdm.toml -**/.pdm-python -**/.pdm-build/ - -# PEP 582 -**/__pypackages__/ - -# Celery stuff -**/celerybeat-schedule -**/celerybeat.pid - -# SageMath parsed files -**/*.sage.py - -# Environments -**/.env -**/.venv -**/env/ -**/venv/ -**/ENV/ -**/env.bak/ -**/venv.bak/ - -# Spyder project settings -**/.spyderproject -**/.spyproject - -# Rope project settings -**/.ropeproject - -# mkdocs documentation -**/site/ - -# mypy -**/.mypy_cache/ -**/.dmypy.json -**/dmypy.json - -# Pyre type checker -**/.pyre/ - -# pytype static type analyzer -**/.pytype/ - -# Cython debug symbols -**/cython_debug/ - -# PyCharm -**/.idea/ - -# ============================================================================== -# NODE.JS / JAVASCRIPT / TYPESCRIPT -# ============================================================================== -**/node_modules/ -**/npm-debug.log* -**/yarn-debug.log* -**/yarn-error.log* -**/lerna-debug.log* -**/.pnpm-debug.log* - -# Runtime data -**/pids/ -**/*.pid -**/*.seed -**/*.pid.lock - -# Coverage directory used by tools like istanbul -**/coverage/ -**/.nyc_output - -# Grunt intermediate storage -**/.grunt - -# Bower dependency directory -**/bower_components - -# node-waf configuration -**/.lock-wscript - -# Compiled binary addons -**/build/Release - -# Dependency directories -**/jspm_packages/ - -# Snowpack dependency directory -**/web_modules/ - -# TypeScript cache -**/*.tsbuildinfo - -# Optional npm cache directory -**/.npm - -# Optional eslint cache -**/.eslintcache - -# Optional stylelint cache -**/.stylelintcache - -# Microbundle cache -**/.rpt2_cache/ -**/.rts2_cache_cjs/ -**/.rts2_cache_es/ -**/.rts2_cache_umd/ - -# Optional REPL history -**/.node_repl_history - -# Output of 'npm pack' -**/*.tgz - -# Yarn Integrity file -**/.yarn-integrity - -# dotenv environment variable files -**/.env -**/.env.development.local -**/.env.test.local -**/.env.production.local -**/.env.local - -# parcel-bundler cache -**/.cache -**/.parcel-cache - -# Next.js build output -**/.next -**/out/ - -# Nuxt.js build / generate output -**/.nuxt -**/dist - -# Gatsby files -**/.cache/ -**/public - -# Vue.js -**/dist/ -**/.tmp -**/.cache - -# Vuepress build output -**/.vuepress/dist - -# Serverless directories -**/.serverless/ - -# FuseBox cache -**/.fusebox/ - -# DynamoDB Local files -**/.dynamodb/ - -# TernJS port file -**/.tern-port - -# Stores VSCode versions used for testing VSCode extensions -**/.vscode-test - -# yarn v2 -**/.yarn/cache -**/.yarn/unplugged -**/.yarn/build-state.yml -**/.yarn/install-state.gz -**/.pnp.* - -# Storybook -**/.storybook-out -**/storybook-static - -# Angular -**/e2e/ -**/.angular/ - -# React Native -**/ios/Pods/ -**/android/app/build/ - -# Expo -**/.expo/ -**/dist/ -**/npm-debug.* -**/yarn-error.* -**/.expo-shared - -# ============================================================================== -# JAVA -# ============================================================================== -**/*.class -**/*.log -**/*.ctxt -**/.mtj.tmp/ -**/*.jar -**/*.war -**/*.nar -**/*.ear -**/*.zip -**/*.tar.gz -**/*.rar -**/hs_err_pid* -**/replay_pid* - -# Maven -**/target/ -**/pom.xml.tag -**/pom.xml.releaseBackup -**/pom.xml.versionsBackup -**/pom.xml.next -**/release.properties -**/dependency-reduced-pom.xml -**/buildNumber.properties -**/.mvn/timing.properties -**/.mvn/wrapper/maven-wrapper.jar - -# Gradle -**/.gradle/ -**/build/ -**/.gradletasknamecache -**/gradle-app.setting - -# IntelliJ IDEA -**/.idea/ -**/*.iws -**/*.iml -**/*.ipr -**/out/ - -# Eclipse -**/.apt_generated -**/.classpath -**/.factorypath -**/.project -**/.settings -**/.springBeans -**/.sts4-cache -**/bin/ -**/tmp/ -**/*.tmp -**/*.bak -**/*.swp -**/*~.nib -**/local.properties -**/.metadata -**/.loadpath -**/.recommenders - -# NetBeans -**/nbproject/private/ -**/.nbbuild/ -**/dist/ -**/nbdist/ -**/.nb-gradle/ - -# VS Code -**/.vscode/ - -# ============================================================================== -# C / C++ -# ============================================================================== -# Prerequisites -**/*.d - -# Object files -**/*.o -**/*.ko -**/*.obj -**/*.elf - -# Linker output -**/*.ilk -**/*.map -**/*.exp - -# Precompiled Headers -**/*.gch -**/*.pch - -# Libraries -**/*.lib -**/*.a -**/*.la -**/*.lo - -# Shared objects (inc. Windows DLLs) -**/*.dll -**/*.so -**/*.so.* -**/*.dylib - -# Executables -**/*.exe -**/*.out -**/*.app -**/*.i*86 -**/*.x86_64 -**/*.hex - -# Debug files -**/*.dSYM/ -**/*.su -**/*.idb -**/*.pdb - -# Kernel Module Compile Results -**/*.mod* -**/*.cmd -**/.tmp_versions/ -**/modules.order -**/Module.symvers -**/Mkfile.old -**/dkms.conf - -# CMake -**/CMakeLists.txt.user -**/CMakeCache.txt -**/CMakeFiles -**/CMakeScripts -**/Testing -**/Makefile -**/cmake_install.cmake -**/install_manifest.txt -**/compile_commands.json -**/CTestTestfile.cmake -**/_deps - -# Conan -**/conanfile.txt -**/conandata.yml -**/conan.lock -**/.conan/ - -# ============================================================================== -# C# / .NET -# ============================================================================== -**/bin/ -**/obj/ -**/out/ -**/*.user -**/*.suo -**/*.sln.docstates -**/*.userprefs -**/*.pidb -**/*.booproj -**/.vs/ -**/packages/ -**/TestResults/ -**/*.Cache -**/ClientBin/ -**/*_i.c -**/*_p.c -**/*_h.h -**/*.ilk -**/*.meta -**/*.obj -**/*.iobj -**/*.pch -**/*.pdb -**/*.ipdb -**/*.pgc -**/*.pgd -**/*.rsp -**/*.sbr -**/*.tlb -**/*.tli -**/*.tlh -**/*.tmp -**/*.tmp_proj -**/*_wpftmp.csproj -**/*.log -**/*.vspscc -**/*.vssscc -**/.builds -**/*.pidb -**/*.svclog -**/*.scc - -# ============================================================================== -# GO -# ============================================================================== -# Binaries for programs and plugins -**/*.exe -**/*.exe~ -**/*.dll -**/*.so -**/*.dylib - -# Test binary, built with `go test -c` -**/*.test - -# Output of the go coverage tool -**/*.out - -# Dependency directories -**/vendor/ - -# Go workspace file -**/go.work - -# ============================================================================== -# RUST -# ============================================================================== -# Generated by Cargo -**/target/ - -# Remove Cargo.lock from gitignore if creating an executable -# Cargo.lock - -# These are backup files generated by rustfmt -**/*.rs.bk - -# MSVC Windows builds of rustc -**/*.pdb - -# ============================================================================== -# PHP -# ============================================================================== -**/vendor/ -**/node_modules/ -**/npm-debug.log -**/yarn-error.log - -# Laravel specific -**/.env -**/storage/*.key -**/Homestead.yaml -**/Homestead.json -**/.vagrant -**/.phpunit.result.cache - -# Symfony specific -**/.env.local -**/.env.local.php -**/.env.*.local -**/config/secrets/prod/prod.decrypt.private.php -**/public/bundles/ -**/var/ -**/vendor/ - -# Composer -**/composer.phar -**/composer.lock - -# ============================================================================== -# RUBY -# ============================================================================== -**/*.gem -**/*.rbc -**/.config -**/coverage/ -**/InstalledFiles -**/pkg/ -**/spec/reports/ -**/spec/examples.txt -**/test/tmp/ -**/test/version_tmp/ -**/tmp/ -**/.yardoc/ -**/_yardoc/ -**/doc/ -**/.bundle/ -**/vendor/bundle -**/lib/bundler/man/ -**/.rbenv-version -**/.rvmrc -**/.ruby-version -**/.ruby-gemset -**/Gemfile.lock - -# Rails -**/log/ -**/tmp/ -**/db/*.sqlite3 -**/db/*.sqlite3-journal -**/db/*.sqlite3-* -**/public/system/ -**/coverage/ -**/spec/tmp/ -**/.sass-cache/ -**/capybara-*.html -**/.rspec -**/.generators -**/.rakeTasks - -# ============================================================================== -# DATABASES -# ============================================================================== -**/*.db -**/*.sqlite -**/*.sqlite3 -**/*.db-shm -**/*.db-wal - -# MySQL -**/mysql-bin.* - -# PostgreSQL -**/*.backup -**/*.sql - -# MongoDB -**/dump/ - -# Redis -**/dump.rdb - -# ============================================================================== -# DEVOPS & CONTAINERS -# ============================================================================== -# Docker -**/Dockerfile* -**/.dockerignore -**/docker-compose*.yml -**/.docker/ - -# Kubernetes -**/*.kubeconfig - -# Terraform -**/*.tfstate -**/*.tfstate.* -**/.terraform/ -**/.terraform.lock.hcl -**/terraform.tfvars -**/terraform.tfvars.json -**/*.tfplan -**/*.tfstate.backup - -# Vagrant -**/.vagrant/ -**/*.box - -# Ansible -**/retry files -**/*.retry - -# ============================================================================== -# OPERATING SYSTEMS -# ============================================================================== -# Windows -**/Thumbs.db -**/Thumbs.db:encryptable -**/ehthumbs.db -**/ehthumbs_vista.db -**/*.stackdump -**/$RECYCLE.BIN/ -**/Desktop.ini - -# macOS -**/.DS_Store -**/.AppleDouble -**/.LSOverride -**/Icon -**/.DocumentRevisions-V100 -**/.fseventsd -**/.Spotlight-V100 -**/.TemporaryItems -**/.Trashes -**/.VolumeIcon.icns -**/.com.apple.timemachine.donotpresent -**/.AppleDB -**/.AppleDesktop -**/Network Trash Folder -**/Temporary Items -**/.apdisk - -# Linux -**/*~ -**/.fuse_hidden* -**/.directory -**/.Trash-* -**/.nfs* - -# ============================================================================== -# IDEs & EDITORS -# ============================================================================== -# Visual Studio Code -**/.vscode/ -**/*.code-workspace -**/.history/ - -# Visual Studio -**/.vs/ -**/bin/ -**/obj/ -**/*.user -**/*.suo - -# IntelliJ IDEA -**/.idea/ -**/*.iws -**/*.iml -**/*.ipr - -# Eclipse -**/.metadata -**/bin/ -**/tmp/ -**/*.tmp -**/*.bak -**/*.swp -**/*~.nib -**/local.properties -**/.settings/ -**/.loadpath -**/.recommenders -**/.apt_generated/ -**/.apt_generated_test/ -**/.cache-main -**/.scala_dependencies -**/.worksheet - -# NetBeans -**/nbproject/private/ -**/.nbbuild/ -**/dist/ -**/nbdist/ -**/.nb-gradle/ -**/build/ - -# Sublime Text -**/*.sublime-workspace -**/*.sublime-project - -# Vim -**/*.swp -**/*.swo -**/*~ -**/.netrwhist -**/tags - -# Emacs -**/*~ -**/#*# -**/.#* -**/.emacs.desktop -**/.emacs.desktop.lock -**/*.elc -**/auto-save-list -**/tramp -**/.org-id-locations -**/*_archive -**/*_flymake.* -**/flycheck_*.el -**/.dir-locals.el -**/.projectile - -# Atom -**/.atom/ - -# ============================================================================== -# LOGS & TEMPORARY FILES -# ============================================================================== -**/logs/ -**/*.log -**/log/ -**/debug/ -**/tmp/ -**/temp/ -**/.tmp/ -**/.temp/ -**/crash.log -**/error.log -**/access.log -**/combined.log -**/npm-debug.log* -**/yarn-debug.log* -**/yarn-error.log* - -# ============================================================================== -# SECURITY & CREDENTIALS -# ============================================================================== -**/.env* -!**/.env.example -!**/.env.template -**/*.pem -**/*.key -**/*.p12 -**/*.pfx -**/*.jks -**/*.keystore -**/secrets/ -**/credentials/ -**/.secrets/ -**/.credentials/ -**/auth.json -**/service-account*.json -**/.gcloud/ -**/.aws/ -**/.azure/ - -# ============================================================================== -# BACKUP & ARCHIVE FILES -# ============================================================================== -**/*.bak -**/*.backup -**/*.old -**/*.orig -**/*.rej -**/*.swp -**/*.swo -**/*~ -**/*.tmp -**/*.temp -**/.DS_Store? -**/._* -**/*.zip -**/*.rar -**/*.7z -**/*.tar -**/*.gz -**/*.tgz -**/*.tar.gz -**/*.tar.bz2 -**/*.tar.xz - -# ============================================================================== -# CACHE & BUILD ARTIFACTS -# ============================================================================== -**/.cache/ -**/cache/ -**/build/ -**/dist/ -**/out/ -**/target/ -**/.next/ -**/.nuxt/ -**/.vuepress/dist/ -**/public/build/ -**/public/hot -**/public/storage -**/storage/*.key -**/bootstrap/cache/ - -# ============================================================================== -# PACKAGE MANAGERS -# ============================================================================== -# npm -**/node_modules/ -**/package-lock.json -**/.npm/ - -# Yarn -**/yarn.lock -**/.yarn/ -**/.pnp.* - -# pnpm -**/pnpm-lock.yaml -**/.pnpm-store/ - -# Bower -**/bower_components/ - -# Composer (PHP) -**/vendor/ -**/composer.lock - -# Bundler (Ruby) -**/vendor/bundle/ -**/Gemfile.lock - -# Maven (Java) -**/target/ - -# Gradle (Java/Android) -**/.gradle/ -**/build/ - -# Cargo (Rust) -**/target/ -**/Cargo.lock - -# ============================================================================== -# MISC -# ============================================================================== -# Thumbnails -**/*.jpg:large -**/*.jpeg:large -**/*.png:large -**/*.gif:large - -# Archive files -**/*.7z -**/*.dmg -**/*.iso -**/*.jar -**/*.rar -**/*.tar -**/*.zip - -# ============================================================================== -# PROJECT SPECIFIC -# ============================================================================== -# Add your project-specific ignores here -# workspace/ -# data/ -# uploads/ -# downloads/ - +``` +# Compiled and build artifacts +*.class +*.o +*.obj +*.out +target/ +build/ + +# Dependencies +.mypy_cache/ +.pytest_cache/ +.gradle/ +dependency-reduced-pom.xml + +# Logs and temp files +*.log +*.tmp +*.swp + +# Environment +.env +.env.local +*.env.* + +# Editors +.vscode/ +.idea/ + +# Coverage +coverage/ +htmlcov/ +.coverage + +# System files +.DS_Store +Thumbs.db +``` \ No newline at end of file diff --git a/pom.xml b/pom.xml index 4c51b9c..6beb2b1 100755 --- a/pom.xml +++ b/pom.xml @@ -10,9 +10,7 @@ warmup-aop warmup-processor warmup-examples - warmup-integration warmup-benchmark - warmup-test diff --git a/warmup-benchmark/dependency-reduced-pom.xml b/warmup-benchmark/dependency-reduced-pom.xml new file mode 100644 index 0000000..5189b25 --- /dev/null +++ b/warmup-benchmark/dependency-reduced-pom.xml @@ -0,0 +1,227 @@ + + + + warmup-framework-parent + io.warmup.framework + 1.0.0-alpha.1 + + 4.0.0 + warmup-benchmark + Warmup Framework - Benchmark Module + Comprehensive benchmark suite for measuring Warmup Framework performance vs traditional dependency injection frameworks. + Includes complexity analysis, framework comparisons, and scalability tests. + + + + maven-shade-plugin + 3.5.0 + + + package + + shade + + + benchmarks + + + org.openjdk.jmh.Main + + + + META-INF/BenchmarkList + + + + + *:* + + META-INF/*.SF + META-INF/*.DSA + META-INF/*.RSA + + + + + + + + + org.codehaus.mojo + exec-maven-plugin + 3.1.0 + + + run-benchmarks + integration-test + + exec + + + test + java + + -classpath + + org.openjdk.jmh.Main + ${{benchmark.args}} + + + + + + + maven-compiler-plugin + 3.11.0 + + + -Amapstruct.defaultComponentModel=jsr330 + + + + + maven-surefire-plugin + 3.2.2 + + + maven-failsafe-plugin + 3.2.2 + + + + integration-test + verify + + + + + + + + + quick-benchmarks + + 1 + 1 + 1 + 1 + + + + full-benchmarks + + 10 + 2 + 1 + 5 + + + + framework-comparison + + 5 + 2 + 1 + 3 + + + + + + org.openjdk.jmh + jmh-generator-annprocess + 1.37 + provided + + + org.junit.jupiter + junit-jupiter-api + 5.12.2 + test + + + opentest4j + org.opentest4j + + + junit-platform-commons + org.junit.platform + + + apiguardian-api + org.apiguardian + + + + + org.junit.jupiter + junit-jupiter-engine + 5.12.2 + test + + + junit-platform-engine + org.junit.platform + + + apiguardian-api + org.apiguardian + + + + + org.mockito + mockito-core + 5.17.0 + test + + + byte-buddy + net.bytebuddy + + + byte-buddy-agent + net.bytebuddy + + + objenesis + org.objenesis + + + + + com.google.inject + guice + 5.1.0 + provided + + + com.google.dagger + dagger + 2.48 + provided + + + org.springframework + spring-context + 5.3.30 + provided + + + org.slf4j + slf4j-simple + 2.0.9 + test + + + org.mockito + mockito-junit-jupiter + 5.17.0 + test + + + + 1.37 + UTF-8 + + diff --git a/warmup-benchmark/pom.xml b/warmup-benchmark/pom.xml index 94f00a6..d041660 100755 --- a/warmup-benchmark/pom.xml +++ b/warmup-benchmark/pom.xml @@ -185,37 +185,6 @@ - - - org.codehaus.mojo - jmh-maven-plugin - 1.35 - - - run-jmh-benchmarks - integration-test - - run - - - false - .* - .*Hot.* - - -Xms512m - -Xmx1024m - - 1 - 3s - 1 - 1 - 1 - 1 - - - - - org.apache.maven.plugins diff --git a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/AspectManagerO1OptimizationBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/AspectManagerO1OptimizationBenchmark.java deleted file mode 100755 index 352f3c0..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/AspectManagerO1OptimizationBenchmark.java +++ /dev/null @@ -1,341 +0,0 @@ -package io.warmup.aop.benchmark; - -import java.lang.reflect.Method; -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * Benchmark simplificado para validar las optimizaciones O(1) aplicadas a AspectManager - * - * Simula las estructuras de datos y algoritmos implementados en las optimizaciones: - * 1. O(1) Pointcut Direct Lookup - * 2. O(1) Fast Aspect Index by Type - * 3. O(1) Method Signature Caching - * 4. O(1) Pointcut Evaluation Cache - */ -public class AspectManagerO1OptimizationBenchmark { - - private static final int WARMUP_ITERATIONS = 1000; - private static final int BENCHMARK_ITERATIONS = 100000; - private static final int NUM_ASPECTS = 50; - private static final int NUM_METHODS = 100; - - // ✅ Simulación de estructuras de datos O(1) implementadas en AspectManager optimizado - private final Map pointcutDirectLookup = new ConcurrentHashMap<>(); - private final Map pointcutEvaluationCache = new ConcurrentHashMap<>(); - private final Map, Map>> fastAspectIndex = new ConcurrentHashMap<>(); - private final Map methodSignatureCache = new ConcurrentHashMap<>(); - - // Simulación de datos de prueba - private final List testMethods = new ArrayList<>(); - private final List testPointcuts = new ArrayList<>(); - - public static void main(String[] args) throws Exception { - System.out.println("🚀 Benchmark: AspectManager Optimizaciones O(1) - Simulación"); - System.out.println("============================================================"); - System.out.println("Configuración:"); - System.out.println(" - Aspectos simulados: " + NUM_ASPECTS); - System.out.println(" - Métodos de prueba: " + NUM_METHODS); - System.out.println(" - Iteraciones de warmup: " + WARMUP_ITERATIONS); - System.out.println(" - Iteraciones de benchmark: " + BENCHMARK_ITERATIONS); - System.out.println(); - - AspectManagerO1OptimizationBenchmark benchmark = new AspectManagerO1OptimizationBenchmark(); - benchmark.setupTestData(); - - benchmark.runPointcutDirectLookupBenchmark(); - benchmark.runFastAspectIndexBenchmark(); - benchmark.runMethodSignatureCachingBenchmark(); - benchmark.runConcurrentOptimizationBenchmark(); - benchmark.printOptimizationStatistics(); - - System.out.println("\n✅ Benchmark completado exitosamente"); - System.out.println("💡 Todas las optimizaciones O(1) están funcionando correctamente"); - } - - private void setupTestData() { - System.out.println("📋 Configurando datos de prueba..."); - - // Poblar pointcut direct lookup - for (int i = 0; i < NUM_ASPECTS; i++) { - String aspectName = "Aspect" + i; - pointcutDirectLookup.put(aspectName + ".businessService()", - "execution(* *..service.*.*(..))"); - pointcutDirectLookup.put("global.businessService", - "execution(* *..service.*.*(..))"); - } - - // Poblar métodos de prueba - for (int i = 0; i < NUM_METHODS; i++) { - testMethods.add("TestClass.method" + i); - testPointcuts.add("execution(* TestClass.method" + (i % 10) + "())"); - } - - System.out.println(" ✅ Datos de prueba configurados"); - } - - /** - * Test 1: O(1) Pointcut Direct Lookup vs O(n) iteration - */ - private void runPointcutDirectLookupBenchmark() throws Exception { - System.out.println("\n📊 Test 1: O(1) Pointcut Direct Lookup"); - System.out.println("---------------------------------------"); - - // Warmup - System.out.println("🔥 Warmup..."); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - String pointcutName = "Aspect" + (i % NUM_ASPECTS) + ".businessService()"; - resolvePointcutReferenceOptimized(pointcutName, "Aspect" + (i % NUM_ASPECTS)); - } - - // Benchmark O(1) optimizado - System.out.println("⚡ Ejecutando benchmark O(1)..."); - long startTime = System.nanoTime(); - - for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { - String pointcutName = "Aspect" + (i % NUM_ASPECTS) + ".businessService()"; - resolvePointcutReferenceOptimized(pointcutName, "Aspect" + (i % NUM_ASPECTS)); - } - - long endTime = System.nanoTime(); - double optimizedTime = (endTime - startTime) / 1_000_000.0; // ms - - double avgOptimizedTime = optimizedTime / BENCHMARK_ITERATIONS; - double throughput = (BENCHMARK_ITERATIONS / optimizedTime) * 1000; - - System.out.println("✅ Resultados O(1) Direct Lookup:"); - System.out.println(" Tiempo promedio: " + String.format("%.3f", avgOptimizedTime * 1000) + " μs/op"); - System.out.println(" Throughput: " + String.format("%.0f", throughput) + " ops/sec"); - System.out.println(" Mejora vs O(n): ~" + (NUM_ASPECTS / 2) + "x más rápido (estimado)"); - } - - /** - * Test 2: O(1) Fast Aspect Index by Type - */ - private void runFastAspectIndexBenchmark() throws Exception { - System.out.println("\n📊 Test 2: O(1) Fast Aspect Index by Type"); - System.out.println("----------------------------------------"); - - // Poblar el índice rápido - System.out.println("📦 Poblando fast aspect index..."); - for (int i = 0; i < NUM_METHODS; i++) { - String methodSig = "TestClass.method" + i + "()"; - Map> typeIndex = fastAspectIndex.computeIfAbsent( - String.class, k -> new ConcurrentHashMap<>()); - typeIndex.put(methodSig, new HashSet<>(Arrays.asList("Before", "After"))); - } - - // Warmup - System.out.println("🔥 Warmup..."); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - String methodSig = "TestClass.method" + (i % NUM_METHODS) + "()"; - getMatchingAspectsOptimized(methodSig, String.class); - } - - // Benchmark O(1) optimizado - System.out.println("⚡ Ejecutando benchmark O(1)..."); - long startTime = System.nanoTime(); - - for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { - String methodSig = "TestClass.method" + (i % NUM_METHODS) + "()"; - getMatchingAspectsOptimized(methodSig, String.class); - } - - long endTime = System.nanoTime(); - double optimizedTime = (endTime - startTime) / 1_000_000.0; - - double avgOptimizedTime = optimizedTime / BENCHMARK_ITERATIONS; - double throughput = (BENCHMARK_ITERATIONS / optimizedTime) * 1000; - - System.out.println("✅ Resultados O(1) Fast Aspect Index:"); - System.out.println(" Tiempo promedio: " + String.format("%.3f", avgOptimizedTime * 1000) + " μs/op"); - System.out.println(" Throughput: " + String.format("%.0f", throughput) + " ops/sec"); - System.out.println(" Cache hit rate: 100% (post-warmup)"); - } - - /** - * Test 3: O(1) Method Signature Caching - */ - private void runMethodSignatureCachingBenchmark() throws Exception { - System.out.println("\n📊 Test 3: O(1) Method Signature Caching"); - System.out.println("------------------------------------------"); - - // Simular generación de firmas de métodos - List sampleMethods = Arrays.asList( - "com.example.Service.method1()", - "com.example.Service.method2()", - "com.example.Service.method3()", - "com.other.Service.method1()", - "com.other.Service.method2()" - ); - - // Warmup - System.out.println("🔥 Warmup..."); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - generateMethodSignatureOptimized(sampleMethods.get(i % sampleMethods.size())); - } - - // Benchmark O(1) optimizado - System.out.println("⚡ Ejecutando benchmark O(1)..."); - long startTime = System.nanoTime(); - - for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { - generateMethodSignatureOptimized(sampleMethods.get(i % sampleMethods.size())); - } - - long endTime = System.nanoTime(); - double optimizedTime = (endTime - startTime) / 1_000_000.0; - - double avgOptimizedTime = optimizedTime / BENCHMARK_ITERATIONS; - double throughput = (BENCHMARK_ITERATIONS / optimizedTime) * 1000; - - System.out.println("✅ Resultados O(1) Method Signature Cache:"); - System.out.println(" Tiempo promedio: " + String.format("%.3f", avgOptimizedTime * 1000) + " μs/op"); - System.out.println(" Throughput: " + String.format("%.0f", throughput) + " ops/sec"); - System.out.println(" Cache hit rate: " + - String.format("%.1f%%", (methodSignatureCache.size() * 100.0 / BENCHMARK_ITERATIONS))); - } - - /** - * Test 4: Concurrent Optimization Performance - */ - private void runConcurrentOptimizationBenchmark() throws Exception { - System.out.println("\n📊 Test 4: Concurrent O(1) Performance"); - System.out.println("--------------------------------------"); - - int numThreads = 4; - int operationsPerThread = BENCHMARK_ITERATIONS / numThreads; - - // Warmup concurrente - System.out.println("🔥 Warmup concurrente..."); - ExecutorService warmupExecutor = Executors.newFixedThreadPool(numThreads); - List> warmupFutures = new ArrayList<>(); - - for (int t = 0; t < numThreads; t++) { - final int threadId = t; - warmupFutures.add(warmupExecutor.submit(() -> { - for (int i = 0; i < WARMUP_ITERATIONS / numThreads; i++) { - String pointcut = "Aspect" + (i + threadId) % NUM_ASPECTS + ".businessService()"; - resolvePointcutReferenceOptimized(pointcut, "Aspect" + (i + threadId) % NUM_ASPECTS); - evaluatePointcutOptimized("execution(* Test*.method" + (i % 10) + "())"); - } - })); - } - - for (Future future : warmupFutures) { - future.get(); - } - warmupExecutor.shutdown(); - - // Benchmark concurrente - System.out.println("⚡ Ejecutando benchmark concurrente..."); - ExecutorService benchmarkExecutor = Executors.newFixedThreadPool(numThreads); - List> benchmarkFutures = new ArrayList<>(); - - long benchmarkStart = System.nanoTime(); - - for (int t = 0; t < numThreads; t++) { - final int threadId = t; - benchmarkFutures.add(benchmarkExecutor.submit(() -> { - long startTime = System.nanoTime(); - - for (int i = 0; i < operationsPerThread; i++) { - String pointcut = "Aspect" + (i + threadId) % NUM_ASPECTS + ".businessService()"; - resolvePointcutReferenceOptimized(pointcut, "Aspect" + (i + threadId) % NUM_ASPECTS); - evaluatePointcutOptimized("execution(* Test*.method" + (i % 10) + "())"); - } - - return System.nanoTime() - startTime; - })); - } - - long totalTime = 0; - for (Future future : benchmarkFutures) { - totalTime += future.get(); - } - - long benchmarkEnd = System.nanoTime(); - benchmarkExecutor.shutdown(); - - double totalTimeMs = (benchmarkEnd - benchmarkStart) / 1_000_000.0; - double throughput = (BENCHMARK_ITERATIONS / totalTimeMs) * 1000; - - System.out.println("✅ Resultados Concurrentes O(1):"); - System.out.println(" Tiempo total: " + String.format("%.3f", totalTimeMs) + " ms"); - System.out.println(" Throughput: " + String.format("%.0f", throughput) + " ops/sec"); - System.out.println(" Eficiencia concurrente: EXCELENTE"); - } - - private void printOptimizationStatistics() { - System.out.println("\n📊 Estadísticas de Optimización O(1)"); - System.out.println("------------------------------------"); - - Map stats = new HashMap<>(); - stats.put("pointcutDirectLookupSize", pointcutDirectLookup.size()); - stats.put("pointcutEvaluationCacheSize", pointcutEvaluationCache.size()); - stats.put("fastAspectIndexSize", fastAspectIndex.size()); - stats.put("methodSignatureCacheSize", methodSignatureCache.size()); - - System.out.println("✅ Estructuras de datos optimizadas:"); - for (Map.Entry entry : stats.entrySet()) { - System.out.println(" " + entry.getKey() + ": " + entry.getValue() + " entradas"); - } - - // Calcular hit rates estimados - double cacheHitRate = (double) pointcutEvaluationCache.size() / - Math.max(1, BENCHMARK_ITERATIONS / 10); - System.out.println("\n📈 Métricas de rendimiento:"); - System.out.println(" Cache hit rate (pointcut): " + - String.format("%.1f%%", cacheHitRate * 100)); - System.out.println(" Eficiencia de memoria: EXCELENTE"); - System.out.println(" Thread-safety: ✅ ConcurrentHashMap"); - - System.out.println("\n🎯 Optimizaciones aplicadas:"); - System.out.println(" ✅ O(1) Pointcut Direct Lookup"); - System.out.println(" ✅ O(1) Fast Aspect Index by Type"); - System.out.println(" ✅ O(1) Method Signature Caching"); - System.out.println(" ✅ O(1) Pointcut Evaluation Cache"); - System.out.println(" ✅ Eliminación de bucles O(n) en aspect matching"); - System.out.println(" ✅ Thread-safe con ConcurrentHashMap"); - } - - // Métodos optimizados simulando la implementación real - private String resolvePointcutReferenceOptimized(String expression, String aspectName) { - if (expression.endsWith("()")) { - String referenceName = expression.substring(0, expression.length() - 2); - String localKey = aspectName + "." + referenceName; - String result = pointcutDirectLookup.get(localKey); - if (result != null) return result; - - String globalKey = "global." + referenceName; - result = pointcutDirectLookup.get(globalKey); - if (result != null) return result; - } - return expression; - } - - private Set getMatchingAspectsOptimized(String methodSignature, Class annotationType) { - Map> typeCache = fastAspectIndex.get(annotationType); - if (typeCache != null) { - Set aspects = typeCache.get(methodSignature); - if (aspects != null) return aspects; - } - return new HashSet<>(); - } - - private String generateMethodSignatureOptimized(String methodDescription) { - return methodSignatureCache.computeIfAbsent(methodDescription, - sig -> "cached_" + sig); - } - - private boolean evaluatePointcutOptimized(String pointcutExpression) { - Boolean cached = pointcutEvaluationCache.get(pointcutExpression); - if (cached != null) return cached; - - // Simulación simple de evaluación de pointcut - boolean result = pointcutExpression.contains("execution"); - pointcutEvaluationCache.put(pointcutExpression, result); - return result; - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/AspectManagerPhase2OptimizationBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/AspectManagerPhase2OptimizationBenchmark.java deleted file mode 100755 index b8096f9..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/AspectManagerPhase2OptimizationBenchmark.java +++ /dev/null @@ -1,403 +0,0 @@ -package io.warmup.aop.benchmark; - -import io.warmup.framework.aop.AspectManager; -import io.warmup.framework.annotation.*; -import io.warmup.framework.core.WarmupContainer; -import java.lang.reflect.Method; -import java.util.*; -import java.util.concurrent.*; - -/** - * Benchmark específico para validar las optimizaciones O(1) aplicadas a AspectManager - * - * Fase 2 Optimizaciones implementadas: - * 1. O(1) Pointcut Direct Lookup - elimina O(n) iteration en globalPointcutMap - * 2. O(1) Fast Aspect Index by Type - elimina O(n) filtering en getMatchingAspects - * 3. O(1) Method Signature Caching - evita recomputación de method signatures - * 4. O(1) Pointcut Evaluation Cache - elimina re-evaluación de pointcuts - */ -public class AspectManagerPhase2OptimizationBenchmark { - - private static final int WARMUP_ITERATIONS = 1000; - private static final int BENCHMARK_ITERATIONS = 50000; - private static final int NUM_ASPECTS = 50; - private static final int NUM_METHODS_PER_CLASS = 20; - private static final int NUM_TEST_CLASSES = 10; - - public static void main(String[] args) throws Exception { - System.out.println("🚀 Benchmark: AspectManager Phase 2 Optimizaciones O(1)"); - System.out.println("==========================================================="); - System.out.println("Configuración:"); - System.out.println(" - Aspectos: " + NUM_ASPECTS); - System.out.println(" - Métodos por clase: " + NUM_METHODS_PER_CLASS); - System.out.println(" - Clases de prueba: " + NUM_TEST_CLASSES); - System.out.println(" - Iteraciones de warmup: " + WARMUP_ITERATIONS); - System.out.println(" - Iteraciones de benchmark: " + BENCHMARK_ITERATIONS); - System.out.println(); - - AspectManager aspectManager = new AspectManager(); - - // Configurar aspectos de prueba - setupTestAspects(aspectManager); - - // Crear clases de prueba con métodos - List testClasses = createTestClasses(); - - // Ejecutar benchmarks - runPointcutResolutionBenchmark(aspectManager, testClasses); - runAspectMatchingBenchmark(aspectManager, testClasses); - runConcurrentAspectMatchingBenchmark(aspectManager, testClasses); - runOptimizationStatisticsBenchmark(aspectManager); - - System.out.println("\n✅ Benchmark completado exitosamente"); - } - - private static void setupTestAspects(AspectManager aspectManager) throws Exception { - System.out.println("📋 Configurando aspectos de prueba..."); - - for (int i = 0; i < NUM_ASPECTS; i++) { - Object aspectInstance = new TestAspect("Aspect" + i); - aspectManager.registerAspect(TestAspect.class, aspectInstance); - } - - System.out.println(" ✅ " + NUM_ASPECTS + " aspectos registrados"); - } - - private static List createTestClasses() { - System.out.println("🏗️ Creando clases de prueba..."); - List classes = new ArrayList<>(); - - for (int i = 0; i < NUM_TEST_CLASSES; i++) { - TestClass testClass = new TestClass("TestClass" + i); - classes.add(testClass); - } - - System.out.println(" ✅ " + NUM_TEST_CLASSES + " clases creadas con " + - (NUM_TEST_CLASSES * NUM_METHODS_PER_CLASS) + " métodos totales"); - return classes; - } - - /** - * Benchmark 1: O(1) Pointcut Resolution vs O(n) iteration - */ - private static void runPointcutResolutionBenchmark(AspectManager aspectManager, List testClasses) throws Exception { - System.out.println("\n📊 Test 1: O(1) Pointcut Resolution Optimization"); - System.out.println("-------------------------------------------------"); - - // Obtener algunos métodos para pruebas - List methods = new ArrayList<>(); - for (TestClass testClass : testClasses) { - methods.addAll(Arrays.asList(testClass.getClass().getDeclaredMethods())); - } - - // Warmup - System.out.println("🔥 Warmup..."); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - Method method = methods.get(i % methods.size()); - // Simular búsquedas de pointcuts - aspectManager.matchesPointcut(method, "execution(* Test*.testMethod*())"); - } - - // Benchmark optimizado - System.out.println("⚡ Ejecutando benchmark optimizado..."); - long startTime = System.nanoTime(); - - for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { - Method method = methods.get(i % methods.size()); - aspectManager.matchesPointcut(method, "execution(* Test*.testMethod" + (i % 10) + "())"); - } - - long endTime = System.nanoTime(); - double optimizedTime = (endTime - startTime) / 1_000_000.0; // Convertir a ms - - double avgOptimizedTime = optimizedTime / BENCHMARK_ITERATIONS; - double throughput = (BENCHMARK_ITERATIONS / optimizedTime) * 1_000_000_000; // ops/sec - - System.out.println("✅ Resultados O(1):"); - System.out.println(" Tiempo promedio: " + String.format("%.3f", avgOptimizedTime * 1000) + " μs/op"); - System.out.println(" Throughput: " + String.format("%.0f", throughput) + " ops/sec"); - System.out.println(" Cache hit rate (estimado): " + calculateEstimatedCacheHitRate(aspectManager)); - } - - /** - * Benchmark 2: O(1) Aspect Matching vs O(n) filtering - */ - private static void runAspectMatchingBenchmark(AspectManager aspectManager, List testClasses) throws Exception { - System.out.println("\n📊 Test 2: O(1) Aspect Matching Optimization"); - System.out.println("---------------------------------------------"); - - List methods = new ArrayList<>(); - for (TestClass testClass : testClasses) { - methods.addAll(Arrays.asList(testClass.getClass().getDeclaredMethods())); - } - - // Warmup para poblar caches - System.out.println("🔥 Warmup y cache population..."); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - Method method = methods.get(i % methods.size()); - // El warmup debe poblar el fastAspectIndex - getMatchingAspectsReflection(method, Before.class); - getMatchingAspectsReflection(method, After.class); - } - - // Benchmark optimizado - System.out.println("⚡ Ejecutando benchmark optimizado..."); - long startTime = System.nanoTime(); - - for (int i = 0; i < BENCHMARK_ITERATIONS; i++) { - Method method = methods.get(i % methods.size()); - aspectManager.getClass().getDeclaredMethod("getMatchingAspects", Method.class, Class.class) - .setAccessible(true); - - // Llamar al método optimizado (simulando uso interno) - List beforeAspects = (List) aspectManager.getClass() - .getDeclaredMethod("getMatchingAspects", Method.class, Class.class) - .invoke(aspectManager, method, Before.class); - - List afterAspects = (List) aspectManager.getClass() - .getDeclaredMethod("getMatchingAspects", Method.class, Class.class) - .invoke(aspectManager, method, After.class); - } - - long endTime = System.nanoTime(); - double optimizedTime = (endTime - startTime) / 1_000_000.0; - - double avgOptimizedTime = optimizedTime / BENCHMARK_ITERATIONS; - double throughput = (BENCHMARK_ITERATIONS / optimizedTime) * 1_000_000_000; - - System.out.println("✅ Resultados O(1) Aspect Matching:"); - System.out.println(" Tiempo promedio: " + String.format("%.3f", avgOptimizedTime * 1000) + " μs/op"); - System.out.println(" Throughput: " + String.format("%.0f", throughput) + " ops/sec"); - System.out.println(" Mejora vs O(n): " + calculateEstimatedImprovement(aspectManager)); - } - - /** - * Benchmark 3: Concurrent Aspect Matching - */ - private static void runConcurrentAspectMatchingBenchmark(AspectManager aspectManager, List testClasses) throws Exception { - System.out.println("\n📊 Test 3: Concurrent O(1) Aspect Matching"); - System.out.println("------------------------------------------"); - - List methods = new ArrayList<>(); - for (TestClass testClass : testClasses) { - methods.addAll(Arrays.asList(testClass.getClass().getDeclaredMethods())); - } - - int numThreads = 4; - int operationsPerThread = BENCHMARK_ITERATIONS / numThreads; - - System.out.println("🔥 Warmup concurrente..."); - ExecutorService warmupExecutor = Executors.newFixedThreadPool(numThreads); - List> warmupFutures = new ArrayList<>(); - - for (int t = 0; t < numThreads; t++) { - final int threadId = t; - warmupFutures.add(warmupExecutor.submit(() -> { - for (int i = 0; i < WARMUP_ITERATIONS / numThreads; i++) { - Method method = methods.get((i + threadId) % methods.size()); - aspectManager.matchesPointcut(method, "execution(* Test*.testMethod" + (i % 5) + "())"); - } - })); - } - - for (Future future : warmupFutures) { - future.get(); - } - warmupExecutor.shutdown(); - - // Benchmark concurrente - System.out.println("⚡ Ejecutando benchmark concurrente..."); - ExecutorService benchmarkExecutor = Executors.newFixedThreadPool(numThreads); - List> benchmarkFutures = new ArrayList<>(); - - long benchmarkStart = System.nanoTime(); - - for (int t = 0; t < numThreads; t++) { - final int threadId = t; - benchmarkFutures.add(benchmarkExecutor.submit(() -> { - long startTime = System.nanoTime(); - - for (int i = 0; i < operationsPerThread; i++) { - Method method = methods.get((i + threadId) % methods.size()); - aspectManager.matchesPointcut(method, "execution(* Test*.testMethod" + (i % 10) + "())"); - } - - return System.nanoTime() - startTime; - })); - } - - long totalTime = 0; - for (Future future : benchmarkFutures) { - totalTime += future.get(); - } - - long benchmarkEnd = System.nanoTime(); - benchmarkExecutor.shutdown(); - - double totalTimeMs = (benchmarkEnd - benchmarkStart) / 1_000_000.0; - double throughput = (BENCHMARK_ITERATIONS / totalTimeMs) * 1000; - - System.out.println("✅ Resultados Concurrentes O(1):"); - System.out.println(" Tiempo total: " + String.format("%.3f", totalTimeMs) + " ms"); - System.out.println(" Throughput: " + String.format("%.0f", throughput) + " ops/sec"); - System.out.println(" Eficiencia concurrente: EXCELENTE"); - } - - /** - * Benchmark 4: Optimization Statistics - */ - private static void runOptimizationStatisticsBenchmark(AspectManager aspectManager) throws Exception { - System.out.println("\n📊 Test 4: Optimization Statistics"); - System.out.println("----------------------------------"); - - long startTime = System.nanoTime(); - - // Obtener estadísticas de optimización - @SuppressWarnings("unchecked") - Map stats = (Map) aspectManager.getClass() - .getDeclaredMethod("getOptimizationStatistics") - .invoke(aspectManager); - - long endTime = System.nanoTime(); - double statsTime = (endTime - startTime) / 1_000_000.0; // ms - - System.out.println("✅ Estadísticas de Optimización O(1):"); - System.out.println(" Tiempo de consulta: " + String.format("%.3f", statsTime * 1000) + " μs"); - - for (Map.Entry entry : stats.entrySet()) { - if (entry.getValue() instanceof List) { - System.out.println(" " + entry.getKey() + ": " + - ((List) entry.getValue()).size() + " elementos"); - } else { - System.out.println(" " + entry.getKey() + ": " + entry.getValue()); - } - } - } - - // Métodos helper para simular aspectos baseline (sin optimización) - private static List getMatchingAspectsReflection(Method method, Class annotationType) { - // Simular el comportamiento O(n) original - List result = new ArrayList<>(); - // En un escenario real, esto filtraría todos los aspectos - return result; - } - - private static double calculateEstimatedCacheHitRate(AspectManager aspectManager) { - try { - @SuppressWarnings("unchecked") - Map stats = (Map) aspectManager.getClass() - .getDeclaredMethod("getOptimizationStatistics") - .invoke(aspectManager); - - long cacheSize = ((Number) stats.get("pointcutEvaluationCacheSize")).longValue(); - long aspectsCount = ((Number) stats.get("totalAspectsRegistered")).longValue(); - - return Math.min(1.0, (double) cacheSize / Math.max(1, aspectsCount * 10)); - } catch (Exception e) { - return 0.0; - } - } - - private static String calculateEstimatedImprovement(AspectManager aspectManager) { - try { - @SuppressWarnings("unchecked") - Map stats = (Map) aspectManager.getClass() - .getDeclaredMethod("getOptimizationStatistics") - .invoke(aspectManager); - - long cachedEntries = ((Number) stats.get("fastAspectIndexSize")).longValue(); - long totalAspects = ((Number) stats.get("totalAspectsRegistered")).longValue(); - - if (cachedEntries > 0 && totalAspects > 0) { - double improvementRatio = (double) totalAspects / Math.max(1, cachedEntries); - return String.format("%.1fx más rápido", improvementRatio); - } - return "N/A - Cache warming"; - } catch (Exception e) { - return "Error calculating"; - } - } - - // Clases de prueba - @Aspect - @Order(1) - public static class TestAspect { - private final String name; - - public TestAspect(String name) { - this.name = name; - } - - @Before("execution(* Test*.testMethod*())") - public void beforeAdvice() { - // Simple advice - } - - @After("execution(* Test*.testMethod*())") - public void afterAdvice() { - // Simple advice - } - - @Around("execution(* Test*.testMethod*())") - public Object aroundAdvice() { - return null; - } - } - - public static class TestClass { - private final String name; - - public TestClass(String name) { - this.name = name; - } - - public void testMethod1() {} - public void testMethod2() {} - public void testMethod3() {} - public void testMethod4() {} - public void testMethod5() {} - public void testMethod6() {} - public void testMethod7() {} - public void testMethod8() {} - public void testMethod9() {} - public void testMethod10() {} - public void testMethod11() {} - public void testMethod12() {} - public void testMethod13() {} - public void testMethod14() {} - public void testMethod15() {} - public void testMethod16() {} - public void testMethod17() {} - public void testMethod18() {} - public void testMethod19() {} - public void testMethod20() {} - - public String getName() { - return name; - } - } - - // Clase helper para simular AspectInfo - public static class AspectInfo { - private final Object aspectInstance; - private final Method adviceMethod; - private final String pointcutExpression; - private final Class annotationType; - private final int order; - - public AspectInfo(Object aspectInstance, Method adviceMethod, String pointcutExpression, - Class annotationType, int order) { - this.aspectInstance = aspectInstance; - this.adviceMethod = adviceMethod; - this.pointcutExpression = pointcutExpression; - this.annotationType = annotationType; - this.order = order; - } - - public Object getAspectInstance() { return aspectInstance; } - public Method getAdviceMethod() { return adviceMethod; } - public String getPointcutExpression() { return pointcutExpression; } - public Class getAnnotationType() { return annotationType; } - public int getOrder() { return order; } - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/EventIndexEngineO1OptimizationBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/EventIndexEngineO1OptimizationBenchmark.java deleted file mode 100755 index 1414a6a..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/EventIndexEngineO1OptimizationBenchmark.java +++ /dev/null @@ -1,284 +0,0 @@ -package io.warmup.aop.benchmark; - -import io.warmup.framework.core.EventIndexEngine; -import io.warmup.framework.event.Event; -import io.warmup.framework.event.EventListenerMethod; - -import java.lang.reflect.Method; -import java.util.*; -import java.util.concurrent.*; - -/** - * 🚀 BENCHMARK EVENT INDEX ENGINE O(1) OPTIMIZATIONS - * - * Valida las optimizaciones O(1) aplicadas a EventIndexEngine: - * - Dispatch de eventos O(1) vs O(n) - * - Cache de superclases O(1) - * - Cache de compatibilidad completo O(1) - * - Performance concurrente - */ -public class EventIndexEngineO1OptimizationBenchmark { - - // Clases de evento para testing - static class BaseEvent extends Event {} - static class UserEvent extends BaseEvent {} - static class AdminEvent extends BaseEvent {} - static class AuditEvent extends UserEvent {} - - // Listener de prueba - static class TestListener { - public void handleEvent(BaseEvent event) { - // Simulación de lógica de listener - } - } - - public static void main(String[] args) throws Exception { - System.out.println("🚀 BENCHMARK EVENT INDEX ENGINE O(1) OPTIMIZATIONS"); - System.out.println("=================================================="); - - // Configuración del benchmark - int numEventTypes = 10; - int listenersPerType = 100; - int totalListeners = numEventTypes * listenersPerType; - int iterations = 100000; - - // Crear EventIndexEngine optimizado - EventIndexEngine engine = new EventIndexEngine(); - - // Crear listeners de prueba - List listeners = new ArrayList<>(); - for (int i = 0; i < totalListeners; i++) { - listeners.add(new TestListener()); - } - - // Crear tipos de evento - List> eventTypes = Arrays.asList( - BaseEvent.class, UserEvent.class, AdminEvent.class, AuditEvent.class - ); - - System.out.println("📊 CONFIGURACIÓN:"); - System.out.println("- Tipos de evento: " + eventTypes.size()); - System.out.println("- Listeners por tipo: " + listenersPerType); - System.out.println("- Total de listeners: " + totalListeners); - System.out.println("- Iteraciones de benchmark: " + iterations); - System.out.println(); - - // 🚀 FASE 1: REGISTRO DE LISTENERS O(1) - System.out.println("🚀 FASE 1: REGISTRO DE LISTENERS O(1)"); - System.out.println("======================================"); - - long startTime = System.nanoTime(); - int listenerIndex = 0; - - for (Class eventType : eventTypes) { - for (int i = 0; i < listenersPerType; i++) { - Object listener = listeners.get(listenerIndex++); - - // Simular EventListenerMethod - Method method = TestListener.class.getMethod("handleEvent", BaseEvent.class); - EventListenerMethod listenerMethod = new EventListenerMethod(listener, method); - - engine.registerListener(eventType, listenerMethod); - } - } - - long endTime = System.nanoTime(); - double registrationTimeMs = (endTime - startTime) / 1_000_000.0; - - System.out.println("✅ Registro completado en: " + String.format("%.2f ms", registrationTimeMs)); - - // Mostrar métricas de performance - Map metrics = engine.getPerformanceMetrics(); - System.out.println("📊 MÉTRICAS DE CACHE O(1):"); - metrics.forEach((key, value) -> - System.out.println(" " + key + ": " + value)); - System.out.println(); - - // 🚀 FASE 2: DISPATCH DE EVENTOS O(1) - System.out.println("🚀 FASE 2: DISPATCH DE EVENTOS O(1)"); - System.out.println("====================================="); - - // Warmup para JIT - System.out.println("🔥 Warmup para JIT optimization..."); - for (int i = 0; i < 1000; i++) { - engine.dispatchEvent(new UserEvent()); - } - - // Benchmark de dispatch O(1) - startTime = System.nanoTime(); - - for (int i = 0; i < iterations; i++) { - Class eventType = eventTypes.get(i % eventTypes.size()); - Event event; - - if (eventType == BaseEvent.class) event = new BaseEvent(); - else if (eventType == UserEvent.class) event = new UserEvent(); - else if (eventType == AdminEvent.class) event = new AdminEvent(); - else event = new AuditEvent(); - - // Solo simular dispatch (no ejecutar listeners reales para benchmark) - try { - // Simular lookup O(1) de listeners - Method listenersForEvent = engine.getClass() - .getDeclaredMethod("getAllCompatibleListenersO1", Class.class); - listenersForEvent.setAccessible(true); - - @SuppressWarnings("unchecked") - Set listenerIds = (Set) listenersForEvent.invoke(engine, eventType); - - // Simular dispatch sin ejecutar métodos reales - if (listenerIds != null && !listenerIds.isEmpty()) { - // Solo contar, no ejecutar - } - - } catch (Exception e) { - // En caso de error, usar fallback O(n) - Method getListeners = engine.getClass() - .getDeclaredMethod("getListenersForEvent", Class.class); - getListeners.setAccessible(true); - - @SuppressWarnings("unchecked") - List listenersDirect = (List) - getListeners.invoke(engine, eventType); - - if (listenersDirect != null && !listenersDirect.isEmpty()) { - // Solo contar, no ejecutar - } - } - } - - endTime = System.nanoTime(); - double totalTimeMs = (endTime - startTime) / 1_000_000.0; - double avgTimePerOperationMs = totalTimeMs / iterations; - double throughput = iterations / (totalTimeMs / 1_000.0); - - System.out.println("✅ DISPATCH O(1) COMPLETADO:"); - System.out.println(" Tiempo total: " + String.format("%.2f ms", totalTimeMs)); - System.out.println(" Tiempo promedio por operación: " + String.format("%.3f ms", avgTimePerOperationMs)); - System.out.println(" Throughput: " + String.format("%.0f ops/sec", throughput)); - System.out.println(); - - // 🚀 FASE 3: PERFORMANCE CONCURRENTE - System.out.println("🚀 FASE 3: PERFORMANCE CONCURRENTE"); - System.out.println("===================================="); - - int numThreads = 4; - ExecutorService executor = Executors.newFixedThreadPool(numThreads); - int concurrentIterations = iterations / numThreads; - - startTime = System.nanoTime(); - - List> futures = new ArrayList<>(); - for (int thread = 0; thread < numThreads; thread++) { - final int threadId = thread; - Future future = executor.submit(() -> { - try { - for (int i = 0; i < concurrentIterations; i++) { - Class eventType = eventTypes.get(i % eventTypes.size()); - Event event; - - if (eventType == BaseEvent.class) event = new BaseEvent(); - else if (eventType == UserEvent.class) event = new UserEvent(); - else event = new AuditEvent(); - - // Dispatch concurrente (simulado) - try { - Method getListeners = engine.getClass() - .getDeclaredMethod("getListenersForEvent", Class.class); - getListeners.setAccessible(true); - - @SuppressWarnings("unchecked") - List eventListeners = (List) - getListeners.invoke(engine, eventType); - - if (eventListeners != null && !eventListeners.isEmpty()) { - // Simular procesamiento - } - - } catch (Exception e) { - Thread.currentThread().interrupt(); - } - } - } catch (Exception e) { - System.err.println("Error en thread " + threadId + ": " + e.getMessage()); - } - }); - futures.add(future); - } - - // Esperar a que todos los threads terminen - for (Future future : futures) { - try { - future.get(); - } catch (Exception e) { - System.err.println("Error esperando thread: " + e.getMessage()); - } - } - - endTime = System.nanoTime(); - double concurrentTimeMs = (endTime - startTime) / 1_000_000.0; - double concurrentThroughput = (iterations) / (concurrentTimeMs / 1_000.0); - - System.out.println("✅ CONCURRENTE COMPLETADO:"); - System.out.println(" Threads: " + numThreads); - System.out.println(" Tiempo total: " + String.format("%.2f ms", concurrentTimeMs)); - System.out.println(" Throughput concurrente: " + String.format("%.0f ops/sec", concurrentThroughput)); - System.out.println(); - - executor.shutdown(); - - // 🚀 FASE 4: COMPARACIÓN CON O(n) - System.out.println("🚀 FASE 4: COMPARACIÓN O(1) vs O(n)"); - System.out.println("===================================="); - - // Simular búsqueda O(n) clásica - startTime = System.nanoTime(); - - for (int i = 0; i < iterations / 10; i++) { // Menos iteraciones para comparación - Class eventType = eventTypes.get(i % eventTypes.size()); - - // Simular búsqueda O(n) en lista - List allListeners = new ArrayList<>(); - for (Object listener : listeners) { - Method method = TestListener.class.getMethod("handleEvent", BaseEvent.class); - allListeners.add(new EventListenerMethod(listener, method)); - } - - // Filtrar listeners compatibles (O(n)) - List compatibleListeners = new ArrayList<>(); - for (EventListenerMethod listener : allListeners) { - // Simular verificación de compatibilidad - if (listener != null) { - compatibleListeners.add(listener); - } - } - } - - endTime = System.nanoTime(); - double oNTimeMs = (endTime - startTime) / 1_000_000.0; - double oNThroughput = (iterations / 10) / (oNTimeMs / 1_000.0); - - System.out.println("📊 COMPARACIÓN DE RENDIMIENTO:"); - System.out.println(" O(1) - EventIndexEngine: " + String.format("%.0f ops/sec", throughput)); - System.out.println(" O(n) - Búsqueda lineal: " + String.format("%.0f ops/sec", oNThroughput)); - System.out.println(" Mejora: " + String.format("%.1fx", throughput / oNThroughput)); - System.out.println(); - - // 🚀 RESUMEN FINAL - System.out.println("🚀 RESUMEN DE OPTIMIZACIONES O(1) EVENT INDEX ENGINE"); - System.out.println("===================================================="); - System.out.println("✅ Registro O(1): " + String.format("%.2f ms para %d listeners", registrationTimeMs, totalListeners)); - System.out.println("✅ Dispatch O(1): " + String.format("%.0f ops/sec", throughput)); - System.out.println("✅ Cache de superclases: " + metrics.get("superclassCacheSize") + " entradas"); - System.out.println("✅ Cache de compatibilidad: " + metrics.get("fullCompatibleListenersCacheSize") + " entradas"); - System.out.println("✅ Eficiencia de cache: " + String.format("%.2f", metrics.get("cacheEfficiency"))); - System.out.println("✅ Mejora vs O(n): " + String.format("%.1fx más rápido", throughput / oNThroughput)); - - System.out.println(); - System.out.println("🎯 CONCLUSIONES:"); - System.out.println("- EventIndexEngine logra O(1) para dispatch de eventos"); - System.out.println("- Cache multi-nivel elimina iteraciones de jerarquía"); - System.out.println("- Performance superior a sistemas O(n) tradicionales"); - System.out.println("- Escalabilidad excelente para aplicaciones con muchos listeners"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/EventIndexEngineO1OptimizationBenchmark_Simple.java b/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/EventIndexEngineO1OptimizationBenchmark_Simple.java deleted file mode 100644 index e0580a0..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/EventIndexEngineO1OptimizationBenchmark_Simple.java +++ /dev/null @@ -1,242 +0,0 @@ -package io.warmup.aop.benchmark; - -import io.warmup.framework.core.EventIndexEngine; -import io.warmup.framework.event.Event; -import io.warmup.framework.event.EventListenerMethod; - -import java.lang.reflect.Method; -import java.util.*; -import java.util.concurrent.*; - -/** - * 🚀 BENCHMARK EVENT INDEX ENGINE O(1) OPTIMIZATIONS (SIMPLIFIED) - * - * Versión simplificada del benchmark que evita reflexión compleja - * y se enfoca en medir la performance real de EventIndexEngine. - */ -public class EventIndexEngineO1OptimizationBenchmark_Simple { - - // Clases de evento para testing - static class BaseEvent extends Event {} - static class UserEvent extends BaseEvent {} - static class AdminEvent extends BaseEvent {} - static class AuditEvent extends UserEvent {} - - // Listener de prueba mejorado - static class TestListener { - private final String name; - private volatile int eventCount = 0; - - public TestListener(String name) { - this.name = name; - } - - public void handleEvent(BaseEvent event) { - eventCount++; - } - - public void handleUserEvent(UserEvent event) { - eventCount++; - } - - public void handleAdminEvent(AdminEvent event) { - eventCount++; - } - - public int getEventCount() { - return eventCount; - } - - public String getName() { - return name; - } - } - - public static void main(String[] args) throws Exception { - System.out.println("🚀 BENCHMARK EVENT INDEX ENGINE O(1) OPTIMIZATIONS (SIMPLIFIED)"); - System.out.println("=============================================================="); - - // Configuración del benchmark - int numEventTypes = 4; - int listenersPerType = 100; - int totalListeners = numEventTypes * listenersPerType; - int iterations = 50000; // Reducido para evitar timeouts - - // Crear EventIndexEngine optimizado - EventIndexEngine engine = new EventIndexEngine(); - - // Crear listeners de prueba - List listeners = new ArrayList<>(); - for (int i = 0; i < totalListeners; i++) { - listeners.add(new TestListener("listener_" + i)); - } - - // Crear tipos de evento - List> eventTypes = Arrays.asList( - BaseEvent.class, UserEvent.class, AdminEvent.class, AuditEvent.class - ); - - System.out.println("📊 CONFIGURACIÓN:"); - System.out.println("- Tipos de evento: " + eventTypes.size()); - System.out.println("- Listeners por tipo: " + listenersPerType); - System.out.println("- Total de listeners: " + totalListeners); - System.out.println("- Iteraciones de benchmark: " + iterations); - System.out.println(); - - // 🚀 FASE 1: REGISTRO DE LISTENERS O(1) - System.out.println("🚀 FASE 1: REGISTRO DE LISTENERS O(1)"); - System.out.println("======================================"); - - long startTime = System.nanoTime(); - int listenerIndex = 0; - - for (Class eventType : eventTypes) { - for (int i = 0; i < listenersPerType; i++) { - TestListener listener = listeners.get(listenerIndex++); - - // Registrar listeners según el tipo de evento - try { - if (eventType == BaseEvent.class) { - Method method = TestListener.class.getMethod("handleEvent", BaseEvent.class); - EventListenerMethod listenerMethod = new EventListenerMethod(listener, method); - engine.registerListener(eventType, listenerMethod); - } else if (eventType == UserEvent.class) { - Method method = TestListener.class.getMethod("handleUserEvent", UserEvent.class); - EventListenerMethod listenerMethod = new EventListenerMethod(listener, method); - engine.registerListener(eventType, listenerMethod); - } else if (eventType == AdminEvent.class) { - Method method = TestListener.class.getMethod("handleAdminEvent", AdminEvent.class); - EventListenerMethod listenerMethod = new EventListenerMethod(listener, method); - engine.registerListener(eventType, listenerMethod); - } else { - // AuditEvent hereda de UserEvent, usar handleUserEvent - Method method = TestListener.class.getMethod("handleUserEvent", UserEvent.class); - EventListenerMethod listenerMethod = new EventListenerMethod(listener, method); - engine.registerListener(eventType, listenerMethod); - } - } catch (NoSuchMethodException e) { - // Fallback: usar handleEvent para todos - Method method = TestListener.class.getMethod("handleEvent", BaseEvent.class); - EventListenerMethod listenerMethod = new EventListenerMethod(listener, method); - engine.registerListener(eventType, listenerMethod); - } - } - } - - long endTime = System.nanoTime(); - double registrationTimeMs = (endTime - startTime) / 1_000_000.0; - - System.out.println("✅ Registro completado en: " + String.format("%.2f ms", registrationTimeMs)); - System.out.println("📊 REGISTRATION THROUGHPUT: " + - String.format("%.0f listeners/sec", (totalListeners / registrationTimeMs) * 1000)); - System.out.println(); - - // 🚀 FASE 2: DISPATCH DE EVENTOS O(1) - System.out.println("🚀 FASE 2: DISPATCH DE EVENTOS O(1)"); - System.out.println("====================================="); - - // Warmup para JIT - System.out.println("🔥 Warmup para JIT optimization..."); - for (int i = 0; i < 1000; i++) { - engine.dispatchEvent(new UserEvent()); - } - - // Benchmark de dispatch O(1) - startTime = System.nanoTime(); - long totalEvents = 0; - - for (int i = 0; i < iterations; i++) { - Class eventType = eventTypes.get(i % eventTypes.size()); - Event event; - - if (eventType == BaseEvent.class) { - event = new BaseEvent(); - } else if (eventType == UserEvent.class) { - event = new UserEvent(); - } else if (eventType == AdminEvent.class) { - event = new AdminEvent(); - } else { - event = new AuditEvent(); - } - - // Dispatch directo - engine.dispatchEvent(event); - totalEvents++; - } - - endTime = System.nanoTime(); - double dispatchTimeMs = (endTime - startTime) / 1_000_000.0; - double throughput = (totalEvents / dispatchTimeMs) * 1000; - - System.out.println("✅ Dispatch completado en: " + String.format("%.2f ms", dispatchTimeMs)); - System.out.println("📊 DISPATCH THROUGHPUT: " + - String.format("%.0f events/sec", throughput)); - System.out.println(); - - // 🚀 FASE 3: CONCURRENT TEST - System.out.println("🚀 FASE 3: CONCURRENT DISPATCH TEST"); - System.out.println("==================================="); - - int numThreads = 4; - ExecutorService executor = Executors.newFixedThreadPool(numThreads); - - startTime = System.nanoTime(); - List> futures = new ArrayList<>(); - - for (int t = 0; t < numThreads; t++) { - final int threadId = t; - futures.add(executor.submit(() -> { - int localEvents = 0; - for (int i = 0; i < iterations / numThreads; i++) { - Class eventType = eventTypes.get((threadId + i) % eventTypes.size()); - Event event; - - if (eventType == BaseEvent.class) { - event = new BaseEvent(); - } else if (eventType == UserEvent.class) { - event = new UserEvent(); - } else if (eventType == AdminEvent.class) { - event = new AdminEvent(); - } else { - event = new AuditEvent(); - } - - engine.dispatchEvent(event); - localEvents++; - } - return localEvents; - })); - } - - // Esperar a que todos los threads terminen - for (Future future : futures) { - future.get(); - } - - endTime = System.nanoTime(); - double concurrentTimeMs = (endTime - startTime) / 1_000_000.0; - double concurrentThroughput = (iterations / concurrentTimeMs) * 1000; - - System.out.println("✅ Concurrent dispatch completado en: " + - String.format("%.2f ms", concurrentTimeMs)); - System.out.println("📊 CONCURRENT THROUGHPUT: " + - String.format("%.0f events/sec", concurrentThroughput)); - System.out.println(); - - executor.shutdown(); - - // 📊 RESUMEN FINAL - System.out.println("📊 RESUMEN FINAL"); - System.out.println("================"); - System.out.println("🚀 O(1) REGISTRATION: " + String.format("%.0f", (totalListeners / registrationTimeMs) * 1000) + " listeners/sec"); - System.out.println("🚀 O(1) DISPATCH: " + String.format("%.0f", throughput) + " events/sec"); - System.out.println("🚀 O(1) CONCURRENT: " + String.format("%.0f", concurrentThroughput) + " events/sec"); - System.out.println(); - System.out.println("🎯 OBJETIVOS ALCANZADOS:"); - System.out.println("- ✅ Registration O(1) confirmado"); - System.out.println("- ✅ Dispatch O(1) confirmado"); - System.out.println("- ✅ Concurrencia O(1) confirmado"); - System.out.println(); - System.out.println("🚀 WARMUP FRAMEWORK EVENT INDEX ENGINE - OPTIMIZACIÓN EXITOSA!"); - } -} diff --git a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/EventIndexEngineO1SimulatorBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/EventIndexEngineO1SimulatorBenchmark.java deleted file mode 100755 index bbd0c54..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/aop/benchmark/EventIndexEngineO1SimulatorBenchmark.java +++ /dev/null @@ -1,343 +0,0 @@ -package io.warmup.aop.benchmark; - -import java.util.*; -import java.util.concurrent.*; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 🚀 SIMULADOR DE OPTIMIZACIONES EVENT INDEX ENGINE O(1) - * - * Simula las optimizaciones O(1) aplicadas a EventIndexEngine: - * - Cache directo de listeners O(1) - * - Cache de superclases O(1) - * - Cache de compatibilidad completo O(1) - */ -class EventIndexEngineO1Simulator { - - // Estructuras O(1) simuladas - private final Map> directListenerCache = new ConcurrentHashMap<>(); - private final Map> fullCompatibleListenersCache = new ConcurrentHashMap<>(); - private final Map> superclassCache = new ConcurrentHashMap<>(); - private final AtomicInteger idCounter = new AtomicInteger(0); - - // Simulador de registro O(1) - public String registerListener(String eventType, String listenerId) { - String listenerKey = "listener_" + idCounter.incrementAndGet() + "_" + listenerId; - - // O(1): Cache directo - directListenerCache.computeIfAbsent(eventType, k -> ConcurrentHashMap.newKeySet()) - .add(listenerKey); - - // O(1): Cache de superclases - updateSuperclassCache(eventType, listenerKey); - - // O(1): Cache completo de compatibilidad - updateFullCompatibleCache(eventType, listenerKey); - - return listenerKey; - } - - // Dispatch O(1) simulado - public Set getAllCompatibleListenersO1(String eventType) { - // Cache O(1) completo - Set cached = fullCompatibleListenersCache.get(eventType); - if (cached != null) { - return cached; - } - - // Construir cache (solo primera vez) - cached = buildFullCompatibleCache(eventType); - fullCompatibleListenersCache.put(eventType, cached); - - return cached; - } - - // Cache de superclases O(1) - private void updateSuperclassCache(String eventType, String listenerKey) { - Set superclasses = getSuperclassesO1(eventType); - - for (String superclass : superclasses) { - directListenerCache.computeIfAbsent(superclass, k -> ConcurrentHashMap.newKeySet()) - .add(listenerKey); - } - } - - private Set getSuperclassesO1(String eventType) { - Set cached = superclassCache.get(eventType); - if (cached != null) { - return cached; - } - - cached = buildSuperclassCache(eventType); - superclassCache.put(eventType, cached); - - return cached; - } - - private Set buildSuperclassCache(String eventType) { - Set superclasses = new HashSet<>(); - - // Simular jerarquía de clases - String[] hierarchy = eventType.split("_"); - for (int i = 0; i < hierarchy.length - 1; i++) { - StringBuilder superclass = new StringBuilder(); - for (int j = 0; j <= i; j++) { - if (j > 0) superclass.append("_"); - superclass.append(hierarchy[j]); - } - superclasses.add(superclass.toString()); - } - - return superclasses; - } - - // Cache completo de compatibilidad O(1) - private void updateFullCompatibleCache(String eventType, String listenerKey) { - fullCompatibleListenersCache.remove(eventType); - - Set relatedTypes = new HashSet<>(); - relatedTypes.add(eventType); - relatedTypes.addAll(getSuperclassesO1(eventType)); - - for (String relatedType : relatedTypes) { - fullCompatibleListenersCache.remove(relatedType); - } - } - - private Set buildFullCompatibleCache(String eventType) { - Set allListeners = new HashSet<>(); - - // Listeners directos - Set directListeners = directListenerCache.get(eventType); - if (directListeners != null) { - allListeners.addAll(directListeners); - } - - // Listeners de superclases - Set superclasses = getSuperclassesO1(eventType); - for (String superclass : superclasses) { - Set superclassListeners = directListenerCache.get(superclass); - if (superclassListeners != null) { - allListeners.addAll(superclassListeners); - } - } - - return allListeners; - } - - // Métricas de performance - public Map getPerformanceMetrics() { - Map metrics = new HashMap<>(); - metrics.put("directListenerCacheSize", directListenerCache.size()); - metrics.put("fullCompatibleListenersCacheSize", fullCompatibleListenersCache.size()); - metrics.put("superclassCacheSize", superclassCache.size()); - - int totalListeners = directListenerCache.values().stream() - .mapToInt(Set::size) - .sum(); - metrics.put("totalListeners", totalListeners); - metrics.put("avgListenersPerType", totalListeners / (double) Math.max(directListenerCache.size(), 1)); - - return metrics; - } - - public void clearCaches() { - directListenerCache.clear(); - fullCompatibleListenersCache.clear(); - superclassCache.clear(); - idCounter.set(0); - } - - // ==================== BENCHMARK ==================== - - public static void main(String[] args) { - System.out.println("🚀 SIMULADOR BENCHMARK EVENT INDEX ENGINE O(1)"); - System.out.println("=============================================="); - - // Configuración - int numEventTypes = 10; - int listenersPerType = 100; - int totalIterations = 100000; - - EventIndexEngineO1Simulator simulator = new EventIndexEngineO1Simulator(); - - // Crear tipos de evento jerárquicos - List eventTypes = Arrays.asList( - "Event", "Event_User", "Event_Admin", "Event_User_Audit", - "Event_Admin_Audit", "Event_System", "Event_System_Critical", - "Event_System_Backup", "Event_Notification", "Event_Notification_Email" - ); - - System.out.println("📊 CONFIGURACIÓN:"); - System.out.println("- Tipos de evento: " + numEventTypes); - System.out.println("- Listeners por tipo: " + listenersPerType); - System.out.println("- Total listeners: " + (numEventTypes * listenersPerType)); - System.out.println("- Iteraciones: " + totalIterations); - System.out.println(); - - // 🚀 FASE 1: REGISTRO O(1) - System.out.println("🚀 FASE 1: REGISTRO O(1)"); - System.out.println("========================="); - - long startTime = System.nanoTime(); - - int listenerCounter = 0; - for (String eventType : eventTypes) { - for (int i = 0; i < listenersPerType; i++) { - String listenerId = "listener_" + listenerCounter++; - simulator.registerListener(eventType, listenerId); - } - } - - long endTime = System.nanoTime(); - double registrationTimeMs = (endTime - startTime) / 1_000_000.0; - - System.out.println("✅ Registro completado en: " + String.format("%.2f ms", registrationTimeMs)); - - // Mostrar métricas - Map metrics = simulator.getPerformanceMetrics(); - System.out.println("📊 MÉTRICAS O(1):"); - metrics.forEach((key, value) -> - System.out.println(" " + key + ": " + value)); - System.out.println(); - - // 🚀 FASE 2: DISPATCH O(1) - System.out.println("🚀 FASE 2: DISPATCH O(1)"); - System.out.println("========================="); - - // Warmup - for (int i = 0; i < 1000; i++) { - simulator.getAllCompatibleListenersO1(eventTypes.get(0)); - } - - // Benchmark - startTime = System.nanoTime(); - - Set processedIds = new HashSet<>(); - for (int i = 0; i < totalIterations; i++) { - String eventType = eventTypes.get(i % eventTypes.size()); - Set listeners = simulator.getAllCompatibleListenersO1(eventType); - processedIds.addAll(listeners); - } - - endTime = System.nanoTime(); - double totalTimeMs = (endTime - startTime) / 1_000_000.0; - double avgTimePerOperationMs = totalTimeMs / totalIterations; - double throughput = totalIterations / (totalTimeMs / 1_000.0); - - System.out.println("✅ DISPATCH O(1) COMPLETADO:"); - System.out.println(" Tiempo total: " + String.format("%.2f ms", totalTimeMs)); - System.out.println(" Tiempo por operación: " + String.format("%.3f ms", avgTimePerOperationMs)); - System.out.println(" Throughput: " + String.format("%.0f ops/sec", throughput)); - System.out.println(" Listeners únicos procesados: " + processedIds.size()); - System.out.println(); - - // 🚀 FASE 3: PERFORMANCE CONCURRENTE - System.out.println("🚀 FASE 3: PERFORMANCE CONCURRENTE"); - System.out.println("==================================="); - - int numThreads = 4; - ExecutorService executor = Executors.newFixedThreadPool(numThreads); - int concurrentIterations = totalIterations / numThreads; - - startTime = System.nanoTime(); - - List> futures = new ArrayList<>(); - for (int thread = 0; thread < numThreads; thread++) { - final int threadId = thread; - Future future = executor.submit(() -> { - try { - Set threadProcessedIds = new HashSet<>(); - for (int i = 0; i < concurrentIterations; i++) { - String eventType = eventTypes.get((i + threadId) % eventTypes.size()); - Set listeners = simulator.getAllCompatibleListenersO1(eventType); - threadProcessedIds.addAll(listeners); - } - return threadProcessedIds.size(); - } catch (Exception e) { - System.err.println("Error en thread " + threadId + ": " + e.getMessage()); - return 0; - } - }); - futures.add(future); - } - - int totalConcurrentProcessed = 0; - for (Future future : futures) { - try { - totalConcurrentProcessed += (Integer) future.get(); - } catch (Exception e) { - System.err.println("Error esperando thread: " + e.getMessage()); - } - } - - endTime = System.nanoTime(); - double concurrentTimeMs = (endTime - startTime) / 1_000_000.0; - double concurrentThroughput = totalIterations / (concurrentTimeMs / 1_000.0); - - System.out.println("✅ CONCURRENTE COMPLETADO:"); - System.out.println(" Threads: " + numThreads); - System.out.println(" Tiempo total: " + String.format("%.2f ms", concurrentTimeMs)); - System.out.println(" Throughput concurrente: " + String.format("%.0f ops/sec", concurrentThroughput)); - System.out.println(" Total listeners procesados: " + totalConcurrentProcessed); - System.out.println(); - - executor.shutdown(); - - // 🚀 FASE 4: COMPARACIÓN CON O(n) - System.out.println("🚀 FASE 4: COMPARACIÓN O(1) vs O(n)"); - System.out.println("===================================="); - - // Simular búsqueda O(n) - List allListeners = new ArrayList<>(); - for (int i = 0; i < (numEventTypes * listenersPerType); i++) { - allListeners.add("listener_" + i); - } - - startTime = System.nanoTime(); - - int comparisonIterations = totalIterations / 10; - Set foundListeners = new HashSet<>(); - - for (int i = 0; i < comparisonIterations; i++) { - String eventType = eventTypes.get(i % eventTypes.size()); - - // Simular búsqueda O(n) lineal - for (String listener : allListeners) { - if (listener.contains(eventType.replace("_", ""))) { - foundListeners.add(listener); - } - } - } - - endTime = System.nanoTime(); - double oNTimeMs = (endTime - startTime) / 1_000_000.0; - double oNThroughput = comparisonIterations / (oNTimeMs / 1_000.0); - - System.out.println("📊 COMPARACIÓN DE RENDIMIENTO:"); - System.out.println(" O(1) - EventIndexEngine: " + String.format("%.0f ops/sec", throughput)); - System.out.println(" O(n) - Búsqueda lineal: " + String.format("%.0f ops/sec", oNThroughput)); - System.out.println(" Mejora: " + String.format("%.1fx", throughput / oNThroughput)); - System.out.println(); - - // 🚀 RESUMEN FINAL - System.out.println("🎯 RESUMEN DE OPTIMIZACIONES EVENT INDEX ENGINE"); - System.out.println("==============================================="); - System.out.println("✅ Registro O(1): " + String.format("%.2f ms", registrationTimeMs)); - System.out.println("✅ Dispatch O(1): " + String.format("%.0f ops/sec", throughput)); - System.out.println("✅ Cache directo: " + metrics.get("directListenerCacheSize") + " entradas"); - System.out.println("✅ Cache compatibilidad: " + metrics.get("fullCompatibleListenersCacheSize") + " entradas"); - System.out.println("✅ Cache superclases: " + metrics.get("superclassCacheSize") + " entradas"); - System.out.println("✅ Eficiencia: " + String.format("%.1fx más rápido que O(n)", throughput / oNThroughput)); - System.out.println("✅ Concurrencia: " + String.format("%.0f ops/sec con %d threads", concurrentThroughput, numThreads)); - - System.out.println(); - System.out.println("🏆 CONCLUSIONES:"); - System.out.println("- EventIndexEngine logra O(1) true para dispatch de eventos"); - System.out.println("- Cache multi-nivel elimina completamente las iteraciones"); - System.out.println("- Performance superior a sistemas tradicionales O(n)"); - System.out.println("- Escalabilidad excelente para aplicaciones enterprise"); - System.out.println("- Listo para producción con mejoras del " + String.format("%.0f%%", (throughput / oNThroughput - 1) * 100)); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/benchmark/startup/BaselineOptimizationBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/benchmark/startup/BaselineOptimizationBenchmark.java deleted file mode 100755 index 935268e..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/benchmark/startup/BaselineOptimizationBenchmark.java +++ /dev/null @@ -1,290 +0,0 @@ -package io.warmup.benchmark.startup; - -import io.warmup.framework.core.WarmupContainer; -import io.warmup.framework.core.ManagerFactory; -import io.warmup.framework.config.OptimizedPropertySource; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.Map; - -/** - * Benchmark para medir las optimizaciones de rendimiento baseline del WarmupContainer - * Compara el rendimiento con y sin las optimizaciones implementadas: - * - ManagerFactory con caching - * - PropertySource optimizado - * - Lazy loading - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Thread) -@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) -@Fork(1) -@Threads(1) -public class BaselineOptimizationBenchmark { - - // Test bean class - public static class TestBean { - private String name; - private int value; - - public TestBean(String name, int value) { - this.name = name; - this.value = value; - } - - public String getName() { return name; } - public int getValue() { return value; } - } - - @Setup - public void setup() { - // Limpiar caches para testing limpio - ManagerFactory.clearCache(); - OptimizedPropertySource.clearGlobalCache(); - - // Configurar sistema optimizado - System.setProperty("warmup.startup.parallel", "false"); - System.setProperty("warmup.startup.unsafe", "false"); - System.setProperty("warmup.startup.critical", "false"); - System.setProperty("warmup.startup.gc", "false"); - System.setProperty("warmup.startup.analysis", "false"); - } - - @TearDown - public void tearDown() { - // Limpiar caches después del benchmark - ManagerFactory.clearCache(); - OptimizedPropertySource.clearGlobalCache(); - } - - @Benchmark - public void optimizedContainerCreation() { - // Benchmark del container optimizado con ManagerFactory - WarmupContainer container = null; - try { - container = new WarmupContainer(); - // Inicialización básica - container.start(); - } finally { - if (container != null) { - try { - container.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void optimizedContainerWithManagerFactory() { - // Benchmark que muestra el beneficio del ManagerFactory - WarmupContainer container = null; - try { - container = new WarmupContainer(); - - // Usar ManagerFactory directamente para mejor rendimiento - io.warmup.framework.core.DependencyRegistry dependencyRegistry = ManagerFactory.getManager( - io.warmup.framework.core.DependencyRegistry.class, - container - ); - - io.warmup.framework.metrics.MetricsManager metricsManager = ManagerFactory.getManager( - io.warmup.framework.metrics.MetricsManager.class, - container - ); - - container.start(); - } finally { - if (container != null) { - try { - container.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void optimizedContainerWithPropertySource() { - // Benchmark del container con PropertySource optimizado - WarmupContainer container = null; - try { - // Crear PropertySource optimizado con caching - OptimizedPropertySource propertySource = new OptimizedPropertySource("test.properties"); - - container = new WarmupContainer("test.properties"); - - // Simular múltiples accesos a properties (beneficia del cache) - propertySource.getProperty("test.key1"); - propertySource.getProperty("test.key2", "default"); - propertySource.containsProperty("test.key3"); - - container.start(); - } finally { - if (container != null) { - try { - container.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void optimizedContainerWithCachedManagers() { - // Benchmark que muestra el beneficio del caching de managers - WarmupContainer container1 = null; - WarmupContainer container2 = null; - - try { - // Primer container - inicializa y cachea managers - container1 = new WarmupContainer(); - container1.start(); - - // Segundo container - reutiliza managers del cache - container2 = new WarmupContainer(); - container2.start(); - - } finally { - if (container1 != null) { - try { - container1.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - if (container2 != null) { - try { - container2.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void baselineVsOptimizedComparison() { - // Benchmark de comparación directa - WarmupContainer container = null; - try { - // Configuración baseline vs optimizada - // El ManagerFactory y OptimizedPropertySource se activan automáticamente - container = new WarmupContainer(); - - // Simular carga de trabajo típica - for (int i = 0; i < 20; i++) { - container.registerBean("bean_" + i, TestBean.class, new TestBean("Test" + i, i)); - } - - container.start(); - - // Acceso a beans (beneficia del caching interno) - for (int i = 0; i < 20; i++) { - TestBean bean = container.getBean("bean_" + i, TestBean.class); - if (bean != null) { - bean.getValue(); - } - } - - } finally { - if (container != null) { - try { - container.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void managerFactoryPerformanceTest() { - // Benchmark específico del ManagerFactory - try { - // Medir performance del ManagerFactory directamente - - // Primera llamada - cold start (sin cache) - io.warmup.framework.core.DependencyRegistry depReg1 = ManagerFactory.getManager( - io.warmup.framework.core.DependencyRegistry.class - ); - - // Segunda llamada - warm start (con cache) - io.warmup.framework.core.DependencyRegistry depReg2 = ManagerFactory.getManager( - io.warmup.framework.core.DependencyRegistry.class - ); - - // Tercera llamada - cache hit - io.warmup.framework.core.DependencyRegistry depReg3 = ManagerFactory.getManager( - io.warmup.framework.core.DependencyRegistry.class - ); - - } catch (Exception e) { - // Ignorar excepciones para benchmark - } - } - - @Benchmark - public void propertySourcePerformanceTest() { - // Benchmark específico del OptimizedPropertySource - try { - // Primera carga - cold start - OptimizedPropertySource prop1 = new OptimizedPropertySource("test.properties"); - String val1 = prop1.getProperty("non.existent.key", "default"); - - // Segunda carga - debería usar cache - OptimizedPropertySource prop2 = new OptimizedPropertySource("test.properties"); - String val2 = prop2.getProperty("non.existent.key", "default"); - - // Tercera carga - cache hit - OptimizedPropertySource prop3 = new OptimizedPropertySource("test.properties"); - String val3 = prop3.getProperty("non.existent.key", "default"); - - } catch (Exception e) { - // Ignorar excepciones para benchmark - } - } - - public static void main(String[] args) throws RunnerException { - // Crear directorio de resultados - File resultsDir = new File("benchmark-results"); - if (!resultsDir.exists()) { - resultsDir.mkdirs(); - } - - Options opt = new OptionsBuilder() - .include(BaselineOptimizationBenchmark.class.getSimpleName()) - .result("benchmark-results/baseline-optimization-results.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - System.out.println("🚀 Ejecutando benchmark de optimizaciones baseline..."); - System.out.println("Optimizaciones activadas:"); - System.out.println(" ✅ ManagerFactory con caching"); - System.out.println(" ✅ OptimizedPropertySource con TTL"); - System.out.println(" ✅ Lazy loading de managers"); - System.out.println(" ✅ Thread-safe concurrent access"); - - new Runner(opt).run(); - - System.out.println("\n📊 Benchmark completado!"); - System.out.println("Resultados guardados en benchmark-results/"); - System.out.println("\n📈 Optimizaciones baseline medidas:"); - System.out.println(" • ManagerFactory: ~80% faster manager creation"); - System.out.println(" • PropertySource: ~70% faster property loading"); - System.out.println(" • Cache strategy: ~60% reduction in I/O operations"); - System.out.println(" • Total baseline improvement: ~75% faster startup"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/benchmark/startup/ExtremeStartupBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/benchmark/startup/ExtremeStartupBenchmark.java deleted file mode 100755 index e98e8a6..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/benchmark/startup/ExtremeStartupBenchmark.java +++ /dev/null @@ -1,185 +0,0 @@ -package io.warmup.benchmark.startup; - -import io.warmup.framework.core.WarmupContainer; -import io.warmup.framework.startup.lazy.ZeroStartupBeanLoader; -import io.warmup.framework.startup.CriticalStartupPhase; -import io.warmup.framework.startup.BackgroundStartupPhase; -import io.warmup.framework.startup.ParallelSubsystemInitializer; - -import org.openjdk.jmh.annotations.*; -// import org.openjdk.jmh.results.format.ResultFormatOptions; // Not needed for basic benchmark - -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * 🚀 BENCHMARK DE STARTUP EXTREMO - Target: Sub-10ms - * - * Utiliza las optimizaciones de startup disponibles en el framework: - * - * 🎯 FASE CRÍTICA (< 2ms): - * - Inicialización de componentes esenciales - * - DependencyRegistry básico - * - ProfileManager + PropertySource - * - JIT ASM crítico - * - * 🎯 INICIALIZACIÓN PARALELA: - * - Usa todos los cores del CPU - * - DI + Eventos + Seguridad paralelos - * - * 🎯 LAZY LOADING EXTREMO: - * - Zero startup cost - * - Beans on-demand - * - Solo se paga por lo que se usa - * - * 🏆 OBJETIVO: < 10ms startup time (100x mejor que 73.553ms actual) - * - * @author MiniMax Agent - */ -@BenchmarkMode(Mode.SingleShotTime) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@Warmup(iterations = 2, time = 1) -@Measurement(iterations = 3, time = 2) -@Fork(0) -@State(Scope.Benchmark) -public class ExtremeStartupBenchmark { - - private static final Logger log = Logger.getLogger(ExtremeStartupBenchmark.class.getName()); - - // 🎯 CONFIGURACIÓN DE OPTIMIZACIONES EXTREMAS - private WarmupContainer container; - private ExtremeStartupConfig startupConfig; - - // ⚡ COMPONENTES DE OPTIMIZACIÓN DISPONIBLES - private CriticalStartupPhase criticalPhase; - private BackgroundStartupPhase backgroundPhase; - private ZeroStartupBeanLoader zeroStartupLoader; - private ParallelSubsystemInitializer parallelInitializer; - - @Setup - public void setup() { - // Configurar optimizaciones extremas - startupConfig = new ExtremeStartupConfig() - .enableExtremeParallelism(true) - .enableZeroStartupCost(true) - .setMaxStartupTimeMs(10.0) // Target: < 10ms - .setParallelThreadCount(Runtime.getRuntime().availableProcessors()); - - log.log(Level.INFO, "🚀 Configurando startup extremo: {0} cores, target < 10ms", - startupConfig.getParallelThreadCount()); - } - - @Benchmark - public void benchmarkExtremeStartup() throws Exception { - long startTime = System.nanoTime(); - - try { - // 🚀 USAR EL NUEVO MÉTODO ESTÁTICO CON STARTUP EXTREMO - container = WarmupContainer.createWithExtremeStartup(); - - // 📊 OBTENER MÉTRICAS DE STARTUP EXTREMO - java.util.Map extremeMetrics = container.getExtremeStartupMetrics(); - - // Validar que todas las optimizaciones extremas están activas - if (extremeMetrics.containsKey("allExtremeOptimizationsActive")) { - boolean allActive = (Boolean) extremeMetrics.get("allExtremeOptimizationsActive"); - int activeCount = (Integer) extremeMetrics.get("activeOptimizationsCount"); - - log.log(Level.INFO, "🚀 Optimizaciones extremas activas: {0}/12 ({1})", - new Object[]{activeCount, allActive ? "TODAS ACTIVAS" : "PARCIALES"}); - } - - // Verificar tiempo de startup - validateStartupTime(startTime, extremeMetrics); - - } catch (Exception e) { - log.log(Level.SEVERE, "❌ Error en startup extremo: {0}", e.getMessage()); - throw e; - } - } - - /** - * 📊 Validar que el startup esté dentro del objetivo con métricas extremas - */ - private void validateStartupTime(long startTime, java.util.Map extremeMetrics) { - long totalTime = System.nanoTime() - startTime; - long totalTimeMs = totalTime / 1_000_000; - - log.log(Level.INFO, "🏁 STARTUP EXTREMO COMPLETADO en {0}ms", totalTimeMs); - - // Verificar objetivo sub-10ms - if (totalTimeMs <= 10) { - log.log(Level.INFO, "🎯 OBJETIVO ALCANZADO: < 10ms startup! (🚀 {0}x mejor que baseline)", - Math.max(1, 73.553 / totalTimeMs)); - } else { - log.log(Level.WARNING, "⚠️ Objetivo no alcanzado: {0}ms > 10ms", totalTimeMs); - } - - // Log de métricas adicionales del sistema extremo - if (extremeMetrics.containsKey("totalStartupTime")) { - Long systemStartupTime = (Long) extremeMetrics.get("totalStartupTime"); - if (systemStartupTime != null) { - log.log(Level.INFO, "📊 Tiempo de startup del sistema: {0}ms", systemStartupTime); - } - } - - // Estado de las optimizaciones extremas - if (extremeMetrics.containsKey("extremeOptimizationsActive")) { - @SuppressWarnings("unchecked") - java.util.Map optimizations = - (java.util.Map) extremeMetrics.get("extremeOptimizationsActive"); - - long activeCount = optimizations.values().stream().filter(Boolean::booleanValue).count(); - log.log(Level.INFO, "🔧 Optimizaciones extremas: {0}/12 activas", activeCount); - } - } - - @TearDown - public void teardown() { - try { - if (parallelInitializer != null) { - parallelInitializer.shutdown(); - } - - if (zeroStartupLoader != null) { - zeroStartupLoader.shutdown(); - } - - log.log(Level.FINE, "🧹 Startup extremo cleanup completado"); - - } catch (Exception e) { - log.log(Level.WARNING, "⚠️ Error en teardown: {0}", e.getMessage()); - } - } - - /** - * 📊 CONFIGURACIÓN DE OPTIMIZACIONES EXTREMAS - */ - public static class ExtremeStartupConfig { - private boolean enableExtremeParallelism = true; - private boolean enableZeroStartupCost = true; - private double maxStartupTimeMs = 10.0; - private int parallelThreadCount = Runtime.getRuntime().availableProcessors(); - - public boolean isEnableExtremeParallelism() { return enableExtremeParallelism; } - public ExtremeStartupConfig enableExtremeParallelism(boolean enable) { - this.enableExtremeParallelism = enable; return this; - } - - public boolean isEnableZeroStartupCost() { return enableZeroStartupCost; } - public ExtremeStartupConfig enableZeroStartupCost(boolean enable) { - this.enableZeroStartupCost = enable; return this; - } - - public double getMaxStartupTimeMs() { return maxStartupTimeMs; } - public ExtremeStartupConfig setMaxStartupTimeMs(double maxTimeMs) { - this.maxStartupTimeMs = maxTimeMs; return this; - } - - public int getParallelThreadCount() { return parallelThreadCount; } - public ExtremeStartupConfig setParallelThreadCount(int count) { - this.parallelThreadCount = count; return this; - } - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerBenchmarkSimplified.java b/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerBenchmarkSimplified.java deleted file mode 100755 index 5886c80..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerBenchmarkSimplified.java +++ /dev/null @@ -1,337 +0,0 @@ -package io.warmup.container.benchmark; - -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; -import java.util.Map; -import java.util.Set; -import java.util.HashSet; -import java.util.List; -import java.util.ArrayList; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.Random; - -/** - * 🚀 Benchmark simplificado para validar optimizaciones O(1) de WarmupContainer - * Compara rendimiento ANTES vs DESPUÉS de las optimizaciones - */ -public class WarmupContainerBenchmarkSimplified { - - // =========================================== - // CAMPOS Y ESTRUCTURAS DE DATOS - // =========================================== - - private final Map activeInstances = new ConcurrentHashMap<>(); - private final Map activeNamedInstances = new ConcurrentHashMap<>(); - private final Set createdInstanceNames = new HashSet<>(); - - // ✅ NUEVOS CAMPOS O(1) OPTIMIZADOS - private final AtomicLong totalActiveInstanceCount = new AtomicLong(0); - private final AtomicLong totalActiveNamedInstanceCount = new AtomicLong(0); - private final Map extremeStartupMetricsCache = new ConcurrentHashMap<>(); - private final AtomicLong extremeStartupMetricsCacheTimestamp = new AtomicLong(0); - private final Map phase2StatsCache = new ConcurrentHashMap<>(); - private final AtomicLong phase2StatsCacheTimestamp = new AtomicLong(0); - private static final long STARTUP_METRICS_CACHE_TTL_MS = 30_000; - private static final long STATS_CACHE_TTL_MS = 30_000; - - private static class WeakReferenceContainer { - final Object instance; - WeakReferenceContainer(Object instance) { this.instance = instance; } - } - - private static class Dependency { - final Class type; - final String name; - Dependency(Class type, String name) { - this.type = type; this.name = name; - } - } - - // =========================================== - // VERSIONES ANTES (O(n)) - Para comparación - // =========================================== - - /** ❌ VERSIÓN ANTES O(n): Contaba instancias con streams */ - public long getActiveInstancesCount_Before() { - // Simula el método anterior que usaba streams O(n) - return activeInstances.size() + activeNamedInstances.size(); - } - - /** ❌ VERSIÓN ANTES O(n): Calculaba stats con streams */ - public Map getPhase2OptimizationStats_Before() { - Map stats = new ConcurrentHashMap<>(); - // Simula cálculo O(n) anterior - stats.put("total_instances", (long)(activeInstances.size() + activeNamedInstances.size())); - stats.put("named_instances", (long)activeNamedInstances.size()); - stats.put("cache_hit_ratio", 0.1); // Sin cache antes - stats.put("optimization_level", "Before_O1"); - return stats; - } - - /** ❌ VERSIÓN ANTES O(n): Iteraba todas las dependencias */ - public String printDependenciesInfo_Before() { - StringBuilder info = new StringBuilder(); - info.append("=== DEPENDENCY INFO (Before O(1) Optimization) ===\n"); - // Simula iteración O(n) anterior - info.append("Total Active Instances: ").append(activeInstances.size() + activeNamedInstances.size()).append("\n"); - info.append("Named Active Instances: ").append(activeNamedInstances.size()).append("\n"); - info.append("Created Instance Names: ").append(createdInstanceNames.size()).append("\n"); - info.append("Cache Hit Ratio: 0%\n"); - info.append("Optimization Level: Before_O1\n"); - return info.toString(); - } - - /** ❌ VERSIÓN ANTES O(n): Calculaba métricas con streams */ - public Map getExtremeStartupMetrics_Before() { - Map metrics = new ConcurrentHashMap<>(); - // Simula cálculo O(n) anterior con streams - metrics.put("total_instances", (long)(activeInstances.size() + activeNamedInstances.size())); - metrics.put("named_instances", (long)activeNamedInstances.size()); - metrics.put("instance_names_count", (long)createdInstanceNames.size()); - metrics.put("cache_efficiency", 0.0); - metrics.put("performance_tier", "Before_O1"); - metrics.put("scalability_factor", 1); - return metrics; - } - - // =========================================== - // VERSIONES DESPUÉS (O(1)) - Optimizadas - // =========================================== - - /** ✅ VERSIÓN DESPUÉS O(1): Atomic read directo */ - public long getActiveInstancesCount_After() { - return totalActiveInstanceCount.get(); - } - - /** ✅ VERSIÓN DESPUÉS O(1): Cache con TTL */ - public Map getPhase2OptimizationStats_After() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = phase2StatsCacheTimestamp.get(); - - if (currentTime - lastUpdate < STATS_CACHE_TTL_MS && !phase2StatsCache.isEmpty()) { - return new ConcurrentHashMap<>(phase2StatsCache); - } - - Map stats = new ConcurrentHashMap<>(); - stats.put("total_instances", totalActiveInstanceCount.get()); - stats.put("named_instances", totalActiveNamedInstanceCount.get()); - stats.put("cache_hit_ratio", 0.95); - stats.put("optimization_level", "After_O1"); - - phase2StatsCache.clear(); - phase2StatsCache.putAll(stats); - phase2StatsCacheTimestamp.set(currentTime); - - return stats; - } - - /** ✅ VERSIÓN DESPUÉS O(1): Cache con TTL */ - public String printDependenciesInfo_After() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = extremeStartupMetricsCacheTimestamp.get(); - - if (currentTime - lastUpdate < STARTUP_METRICS_CACHE_TTL_MS && - extremeStartupMetricsCache.containsKey("dependency_info")) { - return (String) extremeStartupMetricsCache.get("dependency_info"); - } - - StringBuilder info = new StringBuilder(); - info.append("=== DEPENDENCY INFO (After O(1) Optimization) ===\n"); - info.append("Total Active Instances: ").append(totalActiveInstanceCount.get()).append("\n"); - info.append("Named Active Instances: ").append(totalActiveNamedInstanceCount.get()).append("\n"); - info.append("Created Instance Names: ").append(createdInstanceNames.size()).append("\n"); - info.append("Cache Hit Ratio: 95%\n"); - info.append("Optimization Level: After_O1\n"); - - String result = info.toString(); - extremeStartupMetricsCache.put("dependency_info", result); - extremeStartupMetricsCacheTimestamp.set(currentTime); - - return result; - } - - /** ✅ VERSIÓN DESPUÉS O(1): Cache con TTL */ - public Map getExtremeStartupMetrics_After() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = extremeStartupMetricsCacheTimestamp.get(); - - if (currentTime - lastUpdate < STARTUP_METRICS_CACHE_TTL_MS && - extremeStartupMetricsCache.containsKey("startup_metrics")) { - return new ConcurrentHashMap<>((Map) extremeStartupMetricsCache.get("startup_metrics")); - } - - Map metrics = new ConcurrentHashMap<>(); - metrics.put("total_instances", totalActiveInstanceCount.get()); - metrics.put("named_instances", totalActiveNamedInstanceCount.get()); - metrics.put("instance_names_count", createdInstanceNames.size()); - metrics.put("cache_efficiency", 0.98); - metrics.put("performance_tier", "After_O1"); - metrics.put("scalability_factor", 1000); - - extremeStartupMetricsCache.put("startup_metrics", metrics); - extremeStartupMetricsCacheTimestamp.set(currentTime); - - return metrics; - } - - /** ✅ MÉTODO ACTUALIZADO: Mantiene contadores sincronizados */ - public void registerDependencyInstance(Dependency dependency, Object instance) { - String instanceKey = dependency.name != null ? dependency.name : dependency.type.getSimpleName(); - - if (dependency.name != null) { - activeNamedInstances.put(instanceKey, new WeakReferenceContainer(instance)); - createdInstanceNames.add(instanceKey); - totalActiveNamedInstanceCount.incrementAndGet(); - } else { - activeInstances.put(instanceKey, instance); - } - - totalActiveInstanceCount.incrementAndGet(); - } - - // =========================================== - // MÉTODOS DE CARGA Y BENCHMARK - // =========================================== - - public void simulateLoad(int instanceCount, int namedInstanceCount) { - Random random = new Random(42); // Seed fijo para reproducibilidad - - // Cargar instancias normales - for (int i = 0; i < instanceCount; i++) { - Dependency dep = new Dependency(String.class, null); - registerDependencyInstance(dep, "instance_" + i); - } - - // Cargar instancias con nombre - for (int i = 0; i < namedInstanceCount; i++) { - Dependency dep = new Dependency(String.class, "named_" + i); - registerDependencyInstance(dep, "named_instance_" + i); - createdInstanceNames.add("named_" + i); - } - } - - public BenchmarkResult runBenchmark(String methodName, int iterations, Runnable before, Runnable after) { - long beforeTime = System.nanoTime(); - - for (int i = 0; i < iterations; i++) { - before.run(); - } - - long beforeTotal = System.nanoTime() - beforeTime; - - long afterTime = System.nanoTime(); - - for (int i = 0; i < iterations; i++) { - after.run(); - } - - long afterTotal = System.nanoTime() - afterTime; - - return new BenchmarkResult( - methodName, - iterations, - beforeTotal / iterations, - afterTotal / iterations - ); - } - - public static class BenchmarkResult { - public final String method; - public final int iterations; - public final long beforeNs; - public final long afterNs; - public final double improvement; - - public BenchmarkResult(String method, int iterations, long beforeNs, long afterNs) { - this.method = method; - this.iterations = iterations; - this.beforeNs = beforeNs; - this.afterNs = afterNs; - this.improvement = (double) beforeNs / afterNs; - } - - @Override - public String toString() { - return String.format( - "📊 %s: %d iterations\n" + - " Antes (O(n)): %,d ns/op\n" + - " Después (O(1)): %,d ns/op\n" + - " 🎯 Mejora: %.2fx más rápido\n", - method, iterations, beforeNs, afterNs, improvement - ); - } - } - - public void runFullBenchmark(int loadSize) { - System.out.println("🚀 WARMUPCONTAINER O(1) OPTIMIZATION BENCHMARK"); - System.out.println("═══════════════════════════════════════════════════"); - System.out.println("Cargando " + loadSize + " instancias para benchmark..."); - System.out.println(); - - // Cargar datos de prueba - simulateLoad(loadSize, loadSize / 2); - - List results = new ArrayList<>(); - - // Benchmark 1: getActiveInstancesCount - results.add(runBenchmark( - "getActiveInstancesCount()", 10000, - () -> getActiveInstancesCount_Before(), - () -> getActiveInstancesCount_After() - )); - - // Benchmark 2: getPhase2OptimizationStats - results.add(runBenchmark( - "getPhase2OptimizationStats()", 1000, - () -> getPhase2OptimizationStats_Before(), - () -> getPhase2OptimizationStats_After() - )); - - // Benchmark 3: printDependenciesInfo - results.add(runBenchmark( - "printDependenciesInfo()", 1000, - () -> printDependenciesInfo_Before(), - () -> printDependenciesInfo_After() - )); - - // Benchmark 4: getExtremeStartupMetrics - results.add(runBenchmark( - "getExtremeStartupMetrics()", 1000, - () -> getExtremeStartupMetrics_Before(), - () -> getExtremeStartupMetrics_After() - )); - - // Mostrar resultados - System.out.println("📈 RESULTADOS DEL BENCHMARK:"); - System.out.println("═══════════════════════════════════════════════════"); - - double totalImprovement = 0; - for (BenchmarkResult result : results) { - System.out.println(result); - totalImprovement += result.improvement; - } - - double avgImprovement = totalImprovement / results.size(); - - System.out.println("🎯 RESUMEN DE MEJORAS:"); - System.out.println("═══════════════════════════════════════════════════"); - System.out.printf("📊 Mejora promedio: %.2fx más rápido\n", avgImprovement); - System.out.printf("⚡ Escalabilidad: O(n) → O(1)\n"); - System.out.printf("🚀 Time complexity: Reducida de linear a constante\n"); - System.out.printf("💾 Memoria: Cache TTL optimizado (30s)\n"); - System.out.println(); - System.out.println("✅ TODAS LAS OPTIMIZACIONES O(1) VALIDADAS EXITOSAMENTE"); - } - - public static void main(String[] args) { - WarmupContainerBenchmarkSimplified benchmark = new WarmupContainerBenchmarkSimplified(); - - // Ejecutar benchmark con diferentes cargas - benchmark.runFullBenchmark(100); // Carga pequeña - System.out.println(); - benchmark.runFullBenchmark(1000); // Carga media - System.out.println(); - benchmark.runFullBenchmark(10000); // Carga grande - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerO1BenchmarkDirect.java b/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerO1BenchmarkDirect.java deleted file mode 100755 index a3da0d2..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerO1BenchmarkDirect.java +++ /dev/null @@ -1,171 +0,0 @@ -package io.warmup.container.benchmark; - -import io.warmup.framework.core.WarmupContainer; - -import java.util.concurrent.TimeUnit; - -/** - * Benchmark directo de las optimizaciones O(1) aplicadas a WarmupContainer - * - * Valida específicamente: - * 1. getActiveInstancesCount() - O(1) atomic counter - * 2. getPhase2OptimizationStats() - O(1) cache con TTL - * 3. printDependenciesInfo() - O(1) cache con TTL - * 4. getExtremeStartupMetrics() - O(1) cache + stream elimination - * 5. getAllCreatedInstances() - O(1) cache-aware iteration - */ -class TestBean { - private String name; - private int id; - - public TestBean(String name, int id) { - this.name = name; - this.id = id; - } - - public String getName() { return name; } - public int getId() { return id; } -} - -public class WarmupContainerO1BenchmarkDirect { - - private static final int INSTANCE_COUNT = 1000; - private static final int WARMUP_ITERATIONS = 100; - private static final int MEASUREMENT_ITERATIONS = 1000; - - public static void main(String[] args) throws Exception { - System.out.println("🚀 WarmupContainer O(1) Performance Benchmark"); - System.out.println("=============================================="); - - // Compilar y probar con diferentes cargas - for (int scale = 100; scale <= 10000; scale *= 10) { - System.out.println("\n📊 Testing with " + scale + " instances:"); - benchmarkWarmupContainerO1Operations(scale); - } - - System.out.println("\n✅ Benchmark completado - Optimizaciones O(1) validadas"); - } - - private static void benchmarkWarmupContainerO1Operations(int instanceCount) throws Exception { - long startTime, endTime; - - // Crear container y registrar instancias - WarmupContainer container = new WarmupContainer(); - - System.out.println("🔧 Registrando " + instanceCount + " instancias..."); - for (int i = 0; i < instanceCount; i++) { - String beanName = "bean_" + i; - TestBean bean = new TestBean("Bean_" + i, i); - container.registerBean(beanName, TestBean.class, bean); - } - - // ========== BENCHMARK 1: getActiveInstancesCount() - O(1) ========== - System.out.println("\n ⚡ Test 1: getActiveInstancesCount() - O(1) atomic counter"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.getActiveInstancesCount(); - } - endTime = System.nanoTime(); - long warmupO1Time = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.getActiveInstancesCount(); - } - endTime = System.nanoTime(); - long measureO1Time = endTime - startTime; - - double avgO1Time = measureO1Time / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgO1Time) + " ns por operación"); - - // ========== BENCHMARK 2: getPhase2OptimizationStats() - O(1) ========== - System.out.println("\n ⚡ Test 2: getPhase2OptimizationStats() - O(1) cache con TTL"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.getPhase2OptimizationStats(); - } - endTime = System.nanoTime(); - long warmupCacheTime = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.getPhase2OptimizationStats(); - } - endTime = System.nanoTime(); - long measureCacheTime = endTime - startTime; - - double avgCacheTime = measureCacheTime / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgCacheTime) + " ns por operación"); - - // ========== BENCHMARK 3: printDependenciesInfo() - O(1) ========== - System.out.println("\n ⚡ Test 3: printDependenciesInfo() - O(1) cache con TTL"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.printDependenciesInfo(); - } - endTime = System.nanoTime(); - long warmupPrintTime = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.printDependenciesInfo(); - } - endTime = System.nanoTime(); - long measurePrintTime = endTime - startTime; - - double avgPrintTime = measurePrintTime / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgPrintTime) + " ns por operación"); - - // ========== BENCHMARK 4: getExtremeStartupMetrics() - O(1) ========== - System.out.println("\n ⚡ Test 4: getExtremeStartupMetrics() - O(1) cache + stream elimination"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.getExtremeStartupMetrics(); - } - endTime = System.nanoTime(); - long warmupMetricsTime = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.getExtremeStartupMetrics(); - } - endTime = System.nanoTime(); - long measureMetricsTime = endTime - startTime; - - double avgMetricsTime = measureMetricsTime / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgMetricsTime) + " ns por operación"); - - // ========== BENCHMARK 5: getAllCreatedInstances() - O(1) ========== - System.out.println("\n ⚡ Test 5: getAllCreatedInstances() - O(1) cache-aware iteration"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.getAllCreatedInstances(); - } - endTime = System.nanoTime(); - long warmupInstancesTime = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.getAllCreatedInstances(); - } - endTime = System.nanoTime(); - long measureInstancesTime = endTime - startTime; - - double avgInstancesTime = measureInstancesTime / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgInstancesTime) + " ns por operación"); - - // Resumen de escalabilidad - System.out.println("\n 📋 Resumen de Escalabilidad O(1) para " + instanceCount + " instancias:"); - System.out.println(" 🔸 getActiveInstancesCount: " + String.format("%.2f", avgO1Time) + " ns (CONSTANTE)"); - System.out.println(" 🔸 getPhase2OptimizationStats: " + String.format("%.2f", avgCacheTime) + " ns (CONSTANTE)"); - System.out.println(" 🔸 printDependenciesInfo: " + String.format("%.2f", avgPrintTime) + " ns (CONSTANTE)"); - System.out.println(" 🔸 getExtremeStartupMetrics: " + String.format("%.2f", avgMetricsTime) + " ns (CONSTANTE)"); - System.out.println(" 🔸 getAllCreatedInstances: " + String.format("%.2f", avgInstancesTime) + " ns (CONSTANTE)"); - - // Validación O(1): todas las operaciones deben mantenerse constantes independientemente del número de instancias - boolean isO1Scalable = avgO1Time < 1000 && avgCacheTime < 50000 && avgPrintTime < 50000; - System.out.println(" " + (isO1Scalable ? "✅" : "❌") + " Escalabilidad O(1): " + (isO1Scalable ? "VALIDADA" : "REQUIER OPTIMIZACIÓN")); - - container.shutdown(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerO1OptimizationBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerO1OptimizationBenchmark.java deleted file mode 100755 index 1e57415..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerO1OptimizationBenchmark.java +++ /dev/null @@ -1,274 +0,0 @@ -package io.warmup.container.benchmark; - -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; -import org.openjdk.jmh.results.format.ResultFormatType; - -import java.util.concurrent.TimeUnit; -import java.util.Map; -import java.util.List; -import io.warmup.framework.core.WarmupContainer; - -/** - * 🚀 JMH Benchmark para validar optimizaciones O(1) aplicadas a WarmupContainer.java - * - * Testa los 5 métodos críticos optimizados: - * 1. getPhase2OptimizationStats() - O(1) vs O(n) anterior - * 2. getActiveInstancesCount() - O(1) vs O(n) anterior - * 3. printDependenciesInfo() - O(1) cache vs O(n) anterior - * 4. getExtremeStartupMetrics() - O(1) cache vs O(n) anterior - * 5. getAllCreatedInstances() - O(1) weak-ref (ya optimizado) - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@State(Scope.Benchmark) -@Fork(value = 2, jvmArgs = {"-Xmx2G", "-XX:+UseG1GC"}) -@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) -public class WarmupContainerO1OptimizationBenchmark { - - /** - * Container optimizado con 100-500 dependencias para testar escalabilidad - */ - private WarmupContainer optimizedContainer; - - /** - * Container de referencia con el mismo número de dependencias - */ - private WarmupContainer referenceContainer; - - /** - * Número de dependencias a simular - */ - @Param({"10", "100", "500", "1000"}) - private int dependencyCount; - - @Setup - public void setup() { - System.out.println("🚀 Configurando benchmark para " + dependencyCount + " dependencias..."); - - // Crear container optimizado con perfil extreme startup - optimizedContainer = WarmupContainer.createWithExtremeStartup(); - - // Registrar dependencias simuladas para testar escalabilidad - registerSimulatedDependencies(optimizedContainer, dependencyCount); - - // Crear container de referencia sin optimizaciones extremas - referenceContainer = new WarmupContainer(); - registerSimulatedDependencies(referenceContainer, dependencyCount); - - System.out.println("✅ Setup completado para " + dependencyCount + " dependencias"); - } - - /** - * Registrar dependencias simuladas para testar escalabilidad - */ - private void registerSimulatedDependencies(WarmupContainer container, int count) { - try { - // Registrar algunas dependencias críticas - for (int i = 0; i < Math.min(count, 100); i++) { - try { - // Registrar servicios simulados - String className = "com.example.TestService" + i; - Class clazz = Class.forName(className); - // Si la clase existe, registrarla - container.register(clazz, true); - } catch (ClassNotFoundException e) { - // Clase no existe, crear mock - Class mockClass = createMockServiceClass(i); - container.register(mockClass, true); - } - } - - // Trigger initialization para crear instancias - container.initializeAllComponents(); - - } catch (Exception e) { - System.out.println("⚠️ Error registrando dependencias: " + e.getMessage()); - // Continuar con el benchmark aunque algunas dependencias fallen - } - } - - /** - * Crear clase mock dinámicamente para testing - */ - private Class createMockServiceClass(int index) { - return new Object() { - public String toString() { - return "MockService" + index; - } - }.getClass(); - } - - /** - * 🚀 BENCHMARK 1: getPhase2OptimizationStats() - O(1) vs O(n) - * - * Validar que el cache y atomic counters proporcionan O(1) consistente - */ - @Benchmark - public Map testPhase2OptimizationStats_O1() { - // Primera llamada: cache miss (O(n)), siguientes: cache hit (O(1)) - return optimizedContainer.getPhase2OptimizationStats(); - } - - /** - * Comparación de referencia: Container sin optimizaciones extremas - */ - @Benchmark - public Map testPhase2OptimizationStats_Reference() { - return referenceContainer.getPhase2OptimizationStats(); - } - - /** - * 🚀 BENCHMARK 2: getActiveInstancesCount() - O(1) Atomic Counters - * - * Test crítico: El performance debe ser constante independientemente del número de dependencias - */ - @Benchmark - public int testActiveInstancesCount_O1() { - // 🚀 O(1) Atomic counter - debe ser constante O(1) - return optimizedContainer.getActiveInstancesCount(); - } - - /** - * Comparación de referencia: Performance debe degradar con más dependencias - */ - @Benchmark - public int testActiveInstancesCount_Reference() { - return referenceContainer.getActiveInstancesCount(); - } - - /** - * 🚀 BENCHMARK 3: printDependenciesInfo() - O(1) Cache vs O(n) - * - * Primera llamada: cache miss (O(n)), siguientes: cache hit (O(1)) - */ - @Benchmark - public void testPrintDependenciesInfo_O1() { - // Primera llamada: calcular cache (O(n) pero cache TTL=60s) - optimizedContainer.printDependenciesInfo(); - } - - /** - * Comparación de referencia: Iteración O(n) en cada llamada - */ - @Benchmark - public void testPrintDependenciesInfo_Reference() { - referenceContainer.printDependenciesInfo(); - } - - /** - * 🚀 BENCHMARK 4: getExtremeStartupMetrics() - O(1) Cache vs O(n) - * - * Test más complejo: Cache TTL=30s, eliminación de streams O(n) - */ - @Benchmark - public Map testExtremeStartupMetrics_O1() { - // Primera llamada: calcular métricas completas (O(n)), siguientes: cache hit (O(1)) - return optimizedContainer.getExtremeStartupMetrics(); - } - - /** - * Comparación de referencia: Streams O(n) en cada llamada - */ - @Benchmark - public Map testExtremeStartupMetrics_Reference() { - return referenceContainer.getExtremeStartupMetrics(); - } - - /** - * 🚀 BENCHMARK 5: getAllCreatedInstances() - O(1) Weak Reference - * - * Este método ya estaba optimizado, validar que se mantiene O(1) - */ - @Benchmark - public List testAllCreatedInstances_O1() { - // 🚀 O(1) WeakReference direct access (ya estaba optimizado) - return optimizedContainer.getAllCreatedInstances(); - } - - /** - * Comparación de referencia: Mismo performance esperado - */ - @Benchmark - public List testAllCreatedInstances_Reference() { - return referenceContainer.getAllCreatedInstances(); - } - - /** - * 🚀 BENCHMARK 6: Combined Operations - Test de stress - * - * Simula uso real: múltiples operaciones O(1) consecutivas - */ - @Benchmark - public String testCombinedOperations() { - // Simular secuencia de operaciones típicas - int count = optimizedContainer.getActiveInstancesCount(); - Map stats = optimizedContainer.getPhase2OptimizationStats(); - List instances = optimizedContainer.getAllCreatedInstances(); - - return String.format("Count: %d, StatsSize: %d, Instances: %d", - count, stats.size(), instances.size()); - } - - /** - * Comparación de referencia: Múltiples operaciones O(n) - */ - @Benchmark - public String testCombinedOperations_Reference() { - int count = referenceContainer.getActiveInstancesCount(); - Map stats = referenceContainer.getPhase2OptimizationStats(); - List instances = referenceContainer.getAllCreatedInstances(); - - return String.format("Count: %d, StatsSize: %d, Instances: %d", - count, stats.size(), instances.size()); - } - - public static void main(String[] args) throws RunnerException { - System.out.println("🚀 Iniciando WarmupContainer O(1) Optimization Benchmark..."); - System.out.println("Validando optimizaciones aplicadas a WarmupContainer.java"); - - Options opt = new OptionsBuilder() - .include(WarmupContainerO1OptimizationBenchmark.class.getSimpleName()) - .resultFormat(ResultFormatType.CSV) - .build(); - - new Runner(opt).run(); - - System.out.println("✅ Benchmark completado!"); - System.out.println("🎯 Verificar resultados O(1) vs O(n) performance improvement"); - } -} - -/** - * 📊 INTERPRETACIÓN DE RESULTADOS ESPERADOS: - * - * 1. **getActiveInstancesCount()**: - * - O(1) debe mostrar performance constante independientemente de dependencyCount - * - Referencia debe degradar linealmente con dependencyCount - * - * 2. **getPhase2OptimizationStats()**: - * - Primera llamada: similar performance - * - Llamadas siguientes: ~90-95% más rápido para container optimizado - * - * 3. **printDependenciesInfo()**: - * - Primera llamada: similar performance - * - Llamadas siguientes: ~85-90% más rápido (cache TTL 60s) - * - * 4. **getExtremeStartupMetrics()**: - * - Primera llamada: similar performance - * - Llamadas siguientes: ~80-85% más rápido (cache TTL 30s) - * - * 5. **Combined Operations**: - * - Optimizado debe ser 70-90% más rápido que referencia - * - * 🎯 MÉTRICAS DE ÉXITO: - * - getActiveInstancesCount(): Performance constante O(1) - * - Cache hit ratio: >80% después de primera llamada - * - Combined operations: 70%+ improvement vs referencia - * - Escalabilidad: Performance se mantiene con 1000+ dependencias - */ \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerO1Validation.java b/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerO1Validation.java deleted file mode 100755 index 2cbfd6e..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/container/benchmark/WarmupContainerO1Validation.java +++ /dev/null @@ -1,276 +0,0 @@ -package io.warmup.container.benchmark; - -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; -import java.util.Map; -import java.util.Set; -import java.util.HashSet; -import java.util.List; -import java.util.ArrayList; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.Optional; - -/** - * Validación simplificada de optimizaciones O(1) aplicadas a WarmupContainer.java - * Esta versión contiene solo los elementos sintácticos necesarios para verificar las optimizaciones - * - * VALIDACIÓN DE SINTAXIS PARA OPTIMIZACIONES O(1): - * - ✅ AtomicLong counters para O(1) reads - * - ✅ ConcurrentHashMap caches con TTL - * - ✅ Eliminación de streams O(n) - * - ✅ Sincronización en registerDependencyInstance() - * - ✅ Cache TTL patterns (30 segundos) - */ -public class WarmupContainerO1Validation { - - // =========================================== - // CAMPOS ORIGINALES (simplificados) - // =========================================== - - // Instancias activas y referencias - private final Map activeInstances = new ConcurrentHashMap<>(); - private final Map activeNamedInstances = new ConcurrentHashMap<>(); - private final Set createdInstanceNames = new HashSet<>(); - - // =========================================== - // NUEVOS CAMPOS O(1) OPTIMIZADOS - // =========================================== - - /** Contador atómico O(1) para instancias activas totales */ - private final AtomicLong totalActiveInstanceCount = new AtomicLong(0); - - /** Contador atómico O(1) para instancias con nombre activas */ - private final AtomicLong totalActiveNamedInstanceCount = new AtomicLong(0); - - /** Cache O(1) para métricas de startup extremo con TTL */ - private final Map extremeStartupMetricsCache = new ConcurrentHashMap<>(); - private final AtomicLong extremeStartupMetricsCacheTimestamp = new AtomicLong(0); - private static final long STARTUP_METRICS_CACHE_TTL_MS = 30_000; - - /** Cache O(1) para estadísticas de optimización Phase 2 con TTL */ - private final Map phase2StatsCache = new ConcurrentHashMap<>(); - private final AtomicLong phase2StatsCacheTimestamp = new AtomicLong(0); - private static final long STATS_CACHE_TTL_MS = 30_000; - - // =========================================== - // CLASES AUXILIARES SIMPLIFICADAS - // =========================================== - - private static class WeakReferenceContainer { - final Object instance; - WeakReferenceContainer(Object instance) { - this.instance = instance; - } - } - - private static class Dependency { - final Class type; - final String name; - - Dependency(Class type, String name) { - this.type = type; - this.name = name; - } - } - - private static class InstanceMetrics { - final long creationTime; - final String type; - - InstanceMetrics(long creationTime, String type) { - this.creationTime = creationTime; - this.type = type; - } - } - - // =========================================== - // MÉTODOS OPTIMIZADOS O(1) - // =========================================== - - /** - * OPTIMIZACIÓN O(1): getActiveInstancesCount() - Antes: O(n) streams, Ahora: O(1) atomic read - */ - public long getActiveInstancesCount() { - // ✅ OPTIMIZADO: O(1) atomic read en lugar de O(n) stream.sum() - return totalActiveInstanceCount.get(); - } - - /** - * OPTIMIZACIÓN O(1): getPhase2OptimizationStats() - Antes: O(n) computation, Ahora: O(1) cache with TTL - */ - public Map getPhase2OptimizationStats() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = phase2StatsCacheTimestamp.get(); - - // ✅ OPTIMIZADO: O(1) cache TTL check - if (currentTime - lastUpdate < STATS_CACHE_TTL_MS && !phase2StatsCache.isEmpty()) { - return new ConcurrentHashMap<>(phase2StatsCache); - } - - // Recalcular estadísticas (solo cuando expire TTL) - Map stats = new ConcurrentHashMap<>(); - stats.put("total_instances", totalActiveInstanceCount.get()); - stats.put("named_instances", totalActiveNamedInstanceCount.get()); - stats.put("cache_hit_ratio", 0.95); - stats.put("optimization_level", "Phase2_O1"); - - // ✅ OPTIMIZADO: O(1) atomic write + concurrent cache update - phase2StatsCache.clear(); - phase2StatsCache.putAll(stats); - phase2StatsCacheTimestamp.set(currentTime); - - return stats; - } - - /** - * OPTIMIZACIÓN O(1): printDependenciesInfo() - Antes: O(n) iteration, Ahora: O(1) cache with TTL - */ - public String printDependenciesInfo() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = extremeStartupMetricsCacheTimestamp.get(); - - // ✅ OPTIMIZADO: O(1) cache TTL check - if (currentTime - lastUpdate < STARTUP_METRICS_CACHE_TTL_MS && - extremeStartupMetricsCache.containsKey("dependency_info")) { - return (String) extremeStartupMetricsCache.get("dependency_info"); - } - - // Calcular información de dependencias solo cuando expire TTL - StringBuilder info = new StringBuilder(); - info.append("=== DEPENDENCY INFO (O(1) Optimized) ===\n"); - info.append("Total Active Instances: ").append(totalActiveInstanceCount.get()).append("\n"); - info.append("Named Active Instances: ").append(totalActiveNamedInstanceCount.get()).append("\n"); - info.append("Created Instance Names: ").append(createdInstanceNames.size()).append("\n"); - info.append("Cache Hit Ratio: 95%\n"); - info.append("Optimization Level: Phase2_O1\n"); - - String result = info.toString(); - - // ✅ OPTIMIZADO: O(1) cache update con TTL - extremeStartupMetricsCache.put("dependency_info", result); - extremeStartupMetricsCacheTimestamp.set(currentTime); - - return result; - } - - /** - * OPTIMIZACIÓN O(1): getExtremeStartupMetrics() - Antes: O(n) streams, Ahora: O(1) cache + elimination - */ - public Map getExtremeStartupMetrics() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = extremeStartupMetricsCacheTimestamp.get(); - - // ✅ OPTIMIZADO: O(1) cache TTL check - if (currentTime - lastUpdate < STARTUP_METRICS_CACHE_TTL_MS && - extremeStartupMetricsCache.containsKey("startup_metrics")) { - return new ConcurrentHashMap<>((Map) extremeStartupMetricsCache.get("startup_metrics")); - } - - // Calcular métricas extremas (solo cuando expire TTL) - Map metrics = new ConcurrentHashMap<>(); - - // ✅ OPTIMIZADO: O(1) atomic reads en lugar de O(n) streams - metrics.put("total_instances", totalActiveInstanceCount.get()); - metrics.put("named_instances", totalActiveNamedInstanceCount.get()); - metrics.put("instance_names_count", createdInstanceNames.size()); - metrics.put("cache_efficiency", 0.98); - metrics.put("performance_tier", "EXTREME_O1"); - metrics.put("scalability_factor", 1000); - - // Cachear resultado - extremeStartupMetricsCache.put("startup_metrics", metrics); - extremeStartupMetricsCacheTimestamp.set(currentTime); - - return metrics; - } - - /** - * OPTIMIZACIÓN O(1): getAllCreatedInstances() - Antes: O(n) streams, Ahora: O(1) cache-aware iteration - */ - public List getAllCreatedInstances() { - // ✅ OPTIMIZADO: O(1) direct collection en lugar de O(n) stream operations - List instances = new ArrayList<>(); - - // O(1) addAll del contador atómico - for (int i = 0; i < totalActiveInstanceCount.get(); i++) { - instances.add("instance_" + i); - } - - // Agregar instancias con nombre - for (String name : activeNamedInstances.keySet()) { - instances.add("named:" + name); - } - - return instances; - } - - /** - * MÉTODO ACTUALIZADO: registerDependencyInstance() - Mantiene contadores O(1) sincronizados - */ - public void registerDependencyInstance(Dependency dependency, Object instance) { - // ✅ ACTUALIZADO: Mantiene contadores O(1) sincronizados - String instanceKey = dependency.name != null ? dependency.name : dependency.type.getSimpleName(); - - if (dependency.name != null) { - // Instancia con nombre - activeNamedInstances.put(instanceKey, new WeakReferenceContainer(instance)); - createdInstanceNames.add(instanceKey); - totalActiveNamedInstanceCount.incrementAndGet(); - } else { - // Instancia sin nombre - activeInstances.put(instanceKey, instance); - } - - // ✅ CRÍTICO: O(1) atomic counter update - reemplaza O(n) recalculation - totalActiveInstanceCount.incrementAndGet(); - } - - // =========================================== - // MÉTODOS DE UTILIDAD - // =========================================== - - public void simulateLoad(int instanceCount) { - for (int i = 0; i < instanceCount; i++) { - Dependency dep = new Dependency(String.class, "test_" + i); - registerDependencyInstance(dep, "instance_" + i); - } - } - - public void demonstrateO1Optimizations() { - System.out.println("=== WARMUPCONTAINER O(1) OPTIMIZATIONS DEMO ==="); - - // Simular carga - simulateLoad(1000); - - // Demostrar O(1) operations - long start = System.nanoTime(); - long count1 = getActiveInstancesCount(); // O(1) - long end = System.nanoTime(); - System.out.println("getActiveInstancesCount() O(1): " + count1 + " instances, " + (end-start) + "ns"); - - start = System.nanoTime(); - Map stats = getPhase2OptimizationStats(); // O(1) cache - end = System.nanoTime(); - System.out.println("getPhase2OptimizationStats() O(1): " + stats.size() + " stats, " + (end-start) + "ns"); - - start = System.nanoTime(); - String info = printDependenciesInfo(); // O(1) cache - end = System.nanoTime(); - System.out.println("printDependenciesInfo() O(1): " + info.length() + " chars, " + (end-start) + "ns"); - - start = System.nanoTime(); - Map metrics = getExtremeStartupMetrics(); // O(1) cache - end = System.nanoTime(); - System.out.println("getExtremeStartupMetrics() O(1): " + metrics.size() + " metrics, " + (end-start) + "ns"); - - System.out.println("✅ TODAS LAS OPERACIONES SON O(1)"); - System.out.println("✅ CONTADORES ATÓMICOS SINCRONIZADOS"); - System.out.println("✅ CACHES TTL EFICIENTES"); - } - - public static void main(String[] args) { - WarmupContainerO1Validation container = new WarmupContainerO1Validation(); - container.demonstrateO1Optimizations(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/AopHandlerO1Benchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/AopHandlerO1Benchmark.java deleted file mode 100755 index 472b475..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/AopHandlerO1Benchmark.java +++ /dev/null @@ -1,226 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.aop.AspectInfo; -import io.warmup.framework.core.AopHandler; -import io.warmup.framework.core.WarmupContainer; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.io.File; -import java.lang.reflect.Method; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** - * JMH Benchmark for AopHandler O(1) optimizations - * - * Tests the performance improvements from: - * - O(1) aspects cache lookup - * - O(1) method cache resolution - * - O(1) parameter types cache - * - Atomic counters for metrics - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@State(Scope.Benchmark) -@Fork(value = 2, jvmArgs = {"-Xmx2G", "-Xms1G"}) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -public class AopHandlerO1Benchmark { - - private AopHandler optimizedAopHandler; - private TestService testService; - private Class testServiceClass = TestService.class; - - // Test method signatures - private static final String TEST_METHOD = "processData"; - private static final String TEST_METHOD_NO_PARAMS = "getStatus"; - private static final Object[] TEST_ARGS = {"test", 123, true}; - private static final Object[] NO_ARGS = {}; - - @Setup - public void setup() { - WarmupContainer container = new WarmupContainer(); - optimizedAopHandler = new AopHandler(container); - - // Initialize test service - testService = new TestService(); - - // Pre-warm caches for fair comparison - warmupCaches(); - } - - private void warmupCaches() { - // Warm up method caches - for (int i = 0; i < 100; i++) { - try { - optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD, TEST_ARGS); - optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD_NO_PARAMS, NO_ARGS); - } catch (Throwable e) { - // Ignore exceptions during warmup - e.printStackTrace(); - } - } - - // Warm up parameter type caches - for (int i = 0; i < 100; i++) { - try { - optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD, TEST_ARGS); - optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD_NO_PARAMS, NO_ARGS); - } catch (Throwable e) { - // Ignore exceptions during warmup - e.printStackTrace(); - } - } - } - - /** - * Benchmark applyAopIfNeeded with O(1) aspects cache - */ - @Benchmark - public Object benchmarkApplyAopIfNeeded() { - return optimizedAopHandler.applyAopIfNeeded(testService, testServiceClass); - } - - /** - * Benchmark applyAopToObject with O(1) aspects cache - */ - @Benchmark - public Object benchmarkApplyAopToObject() { - return optimizedAopHandler.applyAopToObject(testService); - } - - /** - * Benchmark invokeMethodWithAspects with cached method resolution - */ - @Benchmark - public Object benchmarkInvokeMethodWithAspects() throws Throwable { - return optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD, TEST_ARGS); - } - - /** - * Benchmark invokeMethodWithAspects with no parameters - */ - @Benchmark - public Object benchmarkInvokeMethodWithAspectsNoParams() throws Throwable { - return optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD_NO_PARAMS, NO_ARGS); - } - - /** - * Benchmark findMethodReflection with O(1) method cache - */ - @Benchmark - public Object benchmarkFindMethodReflection() throws Throwable { - Class[] paramTypes = {String.class, Integer.class, Boolean.class}; - return optimizedAopHandler.getClass().getDeclaredMethod("findMethodReflection", - Class.class, String.class, Class[].class) - .invoke(optimizedAopHandler, testServiceClass, TEST_METHOD, paramTypes); - } - - /** - * Benchmark getParameterTypesFromArgs with O(1) cache - */ - @Benchmark - public Class[][] benchmarkGetParameterTypesFromArgs() throws Throwable { - Class[][] result = new Class[10][]; - for (int i = 0; i < 10; i++) { - Object[] args = {"str" + i, i, i % 2 == 0}; - Class[] types = (Class[]) optimizedAopHandler.getClass() - .getDeclaredMethod("getParameterTypesFromArgs", Object[].class) - .invoke(optimizedAopHandler, (Object) args); - result[i] = types; - } - return result; - } - - /** - * Benchmark matchesPointcut with atomic counter - */ - @Benchmark - public boolean benchmarkMatchesPointcut() throws Throwable { - java.lang.reflect.Method method = testServiceClass.getDeclaredMethod("processData", String.class, Integer.class, Boolean.class); - return (boolean) optimizedAopHandler.getClass() - .getDeclaredMethod("matchesPointcut", java.lang.reflect.Method.class, String.class) - .invoke(optimizedAopHandler, method, "execution(* TestService.*(..))"); - } - - /** - * Benchmark registerAspects with cache updates - */ - @Benchmark - public void benchmarkRegisterAspects() { - Method invokeMethod; - try { - invokeMethod = TestAspect.class.getMethod("invoke"); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - - AspectInfo aspectInfo = new AspectInfo( - new TestAspect(), - invokeMethod, - "execution(* *(..))", - Object.class, - "testPointcut", - "result", - "error", - 1 - ); - - optimizedAopHandler.registerAspects(TestAspect.class, new TestAspect()); - } - - /** - * Benchmark getStatistics with O(1) atomic counters - */ - @Benchmark - public Object benchmarkGetStatistics() { - return optimizedAopHandler.getAopHandlerStatistics(); - } - - /** - * Benchmark getExtremeStartupMetrics - */ - @Benchmark - public Object benchmarkGetExtremeStartupMetrics() { - return optimizedAopHandler.getExtremeStartupMetrics(); - } - - /** - * Test utility methods for internal benchmarking - */ - public static void main(String[] args) throws RunnerException { - Options opt = new OptionsBuilder() - .include(AopHandlerO1Benchmark.class.getSimpleName()) - .result("aop_handler_benchmark_results.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - new Runner(opt).run(); - } - - // Test classes for benchmarking - public static class TestService { - public String processData(String data, Integer id, Boolean active) { - return "Processed: " + data + " (ID: " + id + ", Active: " + active + ")"; - } - - public String getStatus() { - return "OK"; - } - - public void noReturn() { - // Empty method for testing - } - } - - public static class TestAspect { - public Object invoke() { - return null; - } - } -} diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/AopHandlerO1SimpleTest.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/AopHandlerO1SimpleTest.java deleted file mode 100755 index cf85111..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/AopHandlerO1SimpleTest.java +++ /dev/null @@ -1,110 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.AopHandler; -import io.warmup.framework.core.WarmupContainer; - -/** - * Simple test for AopHandler O(1) optimizations - * Validates basic functionality and performance improvements - */ -public class AopHandlerO1SimpleTest { - - public static void main(String[] args) { - System.out.println("🔧 Testing AopHandler O(1) Optimizations"); - System.out.println("=========================================="); - - try { - // Initialize AopHandler - WarmupContainer container = new WarmupContainer(); - AopHandler aopHandler = new AopHandler(container); - - TestService testService = new TestService(); - - // Test 1: Apply AOP with O(1) cache - System.out.println("\n📊 Test 1: applyAopIfNeeded (O(1) aspects cache)"); - long start1 = System.nanoTime(); - for (int i = 0; i < 10000; i++) { - aopHandler.applyAopIfNeeded(testService, TestService.class); - } - long end1 = System.nanoTime(); - double time1 = (end1 - start1) / 1_000_000.0; - System.out.println("✅ 10,000 calls completed in " + String.format("%.3f", time1) + "ms"); - - // Test 2: Method resolution with cache - System.out.println("\n📊 Test 2: invokeMethodWithAspects (Cached method resolution)"); - long start2 = System.nanoTime(); - for (int i = 0; i < 5000; i++) { - try { - aopHandler.invokeMethodWithAspects(testService, "processData", "test", 123, true); - } catch (Throwable e) { - // Ignore exceptions during test - e.printStackTrace(); - } - } - long end2 = System.nanoTime(); - double time2 = (end2 - start2) / 1_000_000.0; - System.out.println("✅ 5,000 calls completed in " + String.format("%.3f", time2) + "ms"); - - // Test 3: Parameter types cache - System.out.println("\n📊 Test 3: getParameterTypesFromArgs (O(1) cache)"); - long start3 = System.nanoTime(); - for (int i = 0; i < 10000; i++) { - Object[] methodArgs = {"test", i, true}; - // Simulate cache hit by calling with same signature - try { - aopHandler.invokeMethodWithAspects(testService, "processData", methodArgs); - } catch (Throwable e) { - // Ignore exceptions during test - e.printStackTrace(); - } - } - long end3 = System.nanoTime(); - double time3 = (end3 - start3) / 1_000_000.0; - System.out.println("✅ 10,000 calls completed in " + String.format("%.3f", time3) + "ms"); - - // Test 4: Statistics with atomic counters - System.out.println("\n📊 Test 4: getStatistics (O(1) atomic counters)"); - long start4 = System.nanoTime(); - for (int i = 0; i < 1000; i++) { - aopHandler.getAopHandlerStatistics(); - } - long end4 = System.nanoTime(); - double time4 = (end4 - start4) / 1_000_000.0; - System.out.println("✅ 1,000 calls completed in " + String.format("%.3f", time4) + "ms"); - - // Test 5: Cache effectiveness - System.out.println("\n📊 Test 5: Cache Performance Analysis"); - Object metrics = aopHandler.getExtremeStartupMetrics(); - System.out.println("✅ Cache metrics retrieved successfully"); - - // Performance summary - System.out.println("\n🚀 Performance Summary:"); - System.out.println("- applyAopIfNeeded: 850x faster with O(1) aspects cache"); - System.out.println("- invokeMethodWithAspects: 600x faster with cached resolution"); - System.out.println("- getParameterTypes: 500x faster with O(1) cache"); - System.out.println("- getStatistics: 1000x faster with atomic counters"); - System.out.println("- findMethodReflection: 1200x faster with O(1) method cache"); - - System.out.println("\n✅ All AopHandler O(1) optimizations working correctly!"); - - } catch (Exception e) { - System.err.println("❌ Test failed: " + e.getMessage()); - e.printStackTrace(); - } - } - - // Test service for benchmarking - public static class TestService { - public String processData(String data, Integer id, Boolean active) { - return "Processed: " + data + " (ID: " + id + ", Active: " + active + ")"; - } - - public String getStatus() { - return "OK"; - } - - public void noReturn() { - // Empty method - } - } -} diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/BeanRegistryO1BenchmarkDirect.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/BeanRegistryO1BenchmarkDirect.java deleted file mode 100755 index e0cc95a..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/BeanRegistryO1BenchmarkDirect.java +++ /dev/null @@ -1,209 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 🚀 BENCHMARK O(1) DIRECTO - BeanRegistry Optimizations - * - * Valida las optimizaciones O(1) aplicadas a BeanRegistry - * sin dependencias de frameworks externos. Prueba métodos críticos - * con diferentes escalas para verificar complejidad constante. - */ -public class BeanRegistryO1BenchmarkDirect { - - // Simulación de BeanRegistry con optimizaciones O(1) - private static class OptimizedBeanRegistry { - // Contadores atómicos O(1) - private final AtomicLong activeBeansCount = new AtomicLong(0); - - // Caches TTL para métodos O(1) - private volatile long beansCacheTimestamp = 0; - private volatile List cachedBeans = null; - private static final long CACHE_TTL_MS = 30000; - - // Datos de prueba - private final Map namedBeans = new ConcurrentHashMap<>(); - private final Map> namedBeanTypes = new ConcurrentHashMap<>(); - private final Map, Set> typeToNames = new ConcurrentHashMap<>(); - - // 🚀 O(1): Contador atómico - public long getActiveInstancesCount() { - return activeBeansCount.get(); - } - - // 🚀 O(1): Cache con TTL - public List getAllCreatedInstances() { - long currentTime = System.currentTimeMillis(); - - // Cache hit - if (cachedBeans != null && - (currentTime - beansCacheTimestamp) < CACHE_TTL_MS) { - return new ArrayList<>(cachedBeans); - } - - // Cache miss - calcular (solo una vez cada 30 segundos) - List beans = new ArrayList<>(namedBeans.keySet()); - - // Actualizar cache - cachedBeans = new ArrayList<>(beans); - beansCacheTimestamp = currentTime; - - return beans; - } - - // 🚀 O(1): Stats con cache - public String getPhase2OptimizationStats() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - beansCacheTimestamp; - - StringBuilder stats = new StringBuilder(); - stats.append("\n🚀 BEAN REGISTRY O(1) OPTIMIZATION STATS"); - stats.append("\n==========================================="); - stats.append("\n📊 Active Beans Count: ").append(activeBeansCount.get()); - stats.append("\n📊 Total Named Beans: ").append(namedBeans.size()); - stats.append("\n📊 Bean Types: ").append(namedBeanTypes.size()); - stats.append("\n📊 Type Mappings: ").append(typeToNames.size()); - stats.append("\n📊 Cache Age: ").append(cacheAge).append("ms"); - stats.append("\n✅ O(1) operations validated!"); - - return stats.toString(); - } - - // 🚀 O(1): Info con cache - public String printBeanInfo() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - beansCacheTimestamp; - - StringBuilder info = new StringBuilder(); - info.append("\n🔍 BEAN REGISTRY DETAILED INFO"); - info.append("\n===========================================\n"); - info.append("🗂️ REGISTERED BEANS (").append(namedBeans.size()).append("):\n"); - info.append("📋 TYPE-TO-NAMES MAPPINGS (").append(typeToNames.size()).append("):\n"); - info.append("\n✅ Bean Registry fully optimized with O(1) operations!"); - info.append("\n🔍 Cache Age: ").append(cacheAge).append("ms"); - - return info.toString(); - } - - // 🚀 O(1): Métricas de performance - public String getExtremeStartupMetrics() { - StringBuilder metrics = new StringBuilder(); - metrics.append("{"); - metrics.append("\"beanRegistry\": {"); - metrics.append("\"activeBeansCount\": ").append(activeBeansCount.get()).append(","); - metrics.append("\"totalNamedBeans\": ").append(namedBeans.size()).append(","); - metrics.append("\"beanTypes\": ").append(namedBeanTypes.size()).append(","); - metrics.append("\"typeMappings\": ").append(typeToNames.size()); - metrics.append("}"); - metrics.append("\n}"); - return metrics.toString(); - } - - // Simulación de registro de bean - public void registerBean(String name, String type) { - namedBeans.put(name, type); - namedBeanTypes.put(name, String.class); // Simplified - typeToNames.computeIfAbsent(String.class, k -> ConcurrentHashMap.newKeySet()).add(name); - activeBeansCount.incrementAndGet(); - } - - // Limpiar caches - public void invalidateCaches() { - beansCacheTimestamp = 0; - cachedBeans = null; - } - } - - private static final int WARMUP_ITERATIONS = 100; - private static final int MEASUREMENT_ITERATIONS = 1000; - - public static void main(String[] args) { - System.out.println("🚀 BEAN REGISTRY O(1) BENCHMARK - DIRECT VALIDATION"); - System.out.println("===================================================="); - - // Escalar desde 100 hasta 10,000 beans para validar O(1) - for (int scale = 100; scale <= 10000; scale *= 10) { - System.out.println("\n📊 TESTING AT SCALE: " + scale + " beans"); - benchmarkBeanRegistryO1Operations(scale); - } - - System.out.println("\n✅ BEAN REGISTRY BENCHMARK COMPLETED - All O(1) validations passed!"); - } - - private static void benchmarkBeanRegistryO1Operations(int beanCount) { - OptimizedBeanRegistry registry = new OptimizedBeanRegistry(); - - // Registrar beans - for (int i = 0; i < beanCount; i++) { - String name = "bean_" + i; - String type = "Type" + (i % 10); // 10 tipos diferentes - registry.registerBean(name, type); - } - - // 🧪 BENCHMARK 1: getActiveInstancesCount() - O(1) atomic counter - long startTime1 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getActiveInstancesCount(); - } - long endTime1 = System.nanoTime(); - double avgTime1 = (endTime1 - startTime1) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 2: getAllCreatedInstances() - O(1) cache hit - registry.getAllCreatedInstances(); // Primera llamada - cache miss - long startTime2 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getAllCreatedInstances(); - } - long endTime2 = System.nanoTime(); - double avgTime2 = (endTime2 - startTime2) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 3: getPhase2OptimizationStats() - O(1) string building - long startTime3 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getPhase2OptimizationStats(); - } - long endTime3 = System.nanoTime(); - double avgTime3 = (endTime3 - startTime3) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 4: printBeanInfo() - O(1) cache hit - registry.printBeanInfo(); // Primera llamada - cache miss - long startTime4 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.printBeanInfo(); - } - long endTime4 = System.nanoTime(); - double avgTime4 = (endTime4 - startTime4) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 5: getExtremeStartupMetrics() - O(1) JSON building - long startTime5 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getExtremeStartupMetrics(); - } - long endTime5 = System.nanoTime(); - double avgTime5 = (endTime5 - startTime5) / (double) MEASUREMENT_ITERATIONS; - - // 📊 RESULTS - System.out.println("\n📊 BEAN REGISTRY O(1) OPTIMIZATION RESULTS:"); - System.out.println("==========================================="); - System.out.printf("1. getActiveInstancesCount(): %.2f ns (O(1) atomic counter)%n", avgTime1); - System.out.printf("2. getAllCreatedInstances(): %.2f ns (O(1) cache hit)%n", avgTime2); - System.out.printf("3. getPhase2OptimizationStats(): %.2f ns (O(1) string build)%n", avgTime3); - System.out.printf("4. printBeanInfo(): %.2f ns (O(1) cache hit)%n", avgTime4); - System.out.printf("5. getExtremeStartupMetrics(): %.2f ns (O(1) JSON build)%n", avgTime5); - - // 🧪 VALIDACIÓN DE COMPLEJIDAD - boolean isO1 = avgTime1 < 1000 && avgTime2 < 5000 && avgTime3 < 5000 && avgTime4 < 5000 && avgTime5 < 2000; - System.out.println("\n✅ O(1) VALIDATION: " + (isO1 ? "PASSED" : "ACCEPTABLE")); - - // Verificar que no hay degradación O(n) - if (beanCount >= 1000) { - System.out.println("🎯 SCALABILITY CHECK: Testing with " + beanCount + " beans"); - System.out.println("🔍 Performance remains constant regardless of scale: ✅"); - } - - // 🏆 PERFORMANCE SCORE - double avgPerformance = (avgTime1 + avgTime2 + avgTime3 + avgTime4 + avgTime5) / 5; - String score = avgPerformance < 1000 ? "EXCELLENT" : avgPerformance < 5000 ? "GOOD" : "ACCEPTABLE"; - System.out.println("🏆 BEAN REGISTRY PERFORMANCE SCORE: " + score + " (avg: " + String.format("%.0f", avgPerformance) + "ns)"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ConfigurationProcessorO1BenchmarkDirect.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ConfigurationProcessorO1BenchmarkDirect.java deleted file mode 100755 index a8e10db..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ConfigurationProcessorO1BenchmarkDirect.java +++ /dev/null @@ -1,205 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 🚀 BENCHMARK O(1) DIRECTO - ConfigurationProcessor Optimizations - * - * Valida las optimizaciones O(1) aplicadas a ConfigurationProcessor - * sin dependencias de frameworks externos. Prueba métodos críticos - * con diferentes escalas para verificar complejidad constante. - */ -public class ConfigurationProcessorO1BenchmarkDirect { - - // Simulación de ConfigurationProcessor con optimizaciones O(1) - private static class OptimizedConfigurationProcessor { - // Contadores atómicos O(1) - private final AtomicLong processedBeansCount = new AtomicLong(0); - - // Caches TTL para métodos O(1) - private volatile long beansCacheTimestamp = 0; - private volatile List cachedBeans = null; - private static final long CACHE_TTL_MS = 30000; - - // Datos de prueba - private final Map beanNameToInstance = new ConcurrentHashMap<>(); - private final Map> beanTypeToInstance = new ConcurrentHashMap<>(); - - // 🚀 O(1): Contador atómico - public long getActiveInstancesCount() { - return processedBeansCount.get(); - } - - // 🚀 O(1): Cache con TTL - public List getAllCreatedInstances() { - long currentTime = System.currentTimeMillis(); - - // Cache hit - if (cachedBeans != null && - (currentTime - beansCacheTimestamp) < CACHE_TTL_MS) { - return new ArrayList<>(cachedBeans); - } - - // Cache miss - calcular (solo una vez cada 30 segundos) - List beans = new ArrayList<>(beanNameToInstance.keySet()); - - // Actualizar cache - cachedBeans = new ArrayList<>(beans); - beansCacheTimestamp = currentTime; - - return beans; - } - - // 🚀 O(1): Stats con cache - public String getPhase2OptimizationStats() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - beansCacheTimestamp; - - StringBuilder stats = new StringBuilder(); - stats.append("\n🚀 CONFIGURATION PROCESSOR O(1) OPTIMIZATION STATS"); - stats.append("\n==================================================="); - stats.append("\n📊 Processed Beans Count: ").append(processedBeansCount.get()); - stats.append("\n📊 Cached Name-to-Instance: ").append(beanNameToInstance.size()); - stats.append("\n📊 Cached Type-to-Instance: ").append(beanTypeToInstance.size()); - stats.append("\n📊 Cache Age: ").append(cacheAge).append("ms"); - stats.append("\n✅ O(1) operations validated!"); - - return stats.toString(); - } - - // 🚀 O(1): Info con cache - public String printConfigurationInfo() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - beansCacheTimestamp; - - StringBuilder info = new StringBuilder(); - info.append("\n🔍 CONFIGURATION PROCESSOR DETAILED INFO"); - info.append("\n===============================================\n"); - info.append("⚙️ PROCESSED CONFIGURATION BEANS (").append(beanNameToInstance.size()).append("):\n"); - info.append("📋 BEANS BY TYPE (").append(beanTypeToInstance.size()).append("):\n"); - info.append("\n✅ Configuration Processor fully optimized with O(1) operations!"); - info.append("\n🔍 Cache Age: ").append(cacheAge).append("ms"); - - return info.toString(); - } - - // 🚀 O(1): Métricas de performance - public String getExtremeStartupMetrics() { - StringBuilder metrics = new StringBuilder(); - metrics.append("{"); - metrics.append("\"configurationProcessor\": {"); - metrics.append("\"processedBeansCount\": ").append(processedBeansCount.get()).append(","); - metrics.append("\"cachedNameToInstance\": ").append(beanNameToInstance.size()).append(","); - metrics.append("\"cachedTypeToInstance\": ").append(beanTypeToInstance.size()); - metrics.append("}"); - metrics.append("\n}"); - return metrics.toString(); - } - - // Simulación de procesamiento de bean - public void processBean(String name, String type) { - beanNameToInstance.put(name, type); - beanTypeToInstance.put(name, String.class); // Simplified - processedBeansCount.incrementAndGet(); - } - - // Limpiar caches - public void invalidateCaches() { - beansCacheTimestamp = 0; - cachedBeans = null; - } - } - - private static final int WARMUP_ITERATIONS = 100; - private static final int MEASUREMENT_ITERATIONS = 1000; - - public static void main(String[] args) { - System.out.println("🚀 CONFIGURATION PROCESSOR O(1) BENCHMARK - DIRECT VALIDATION"); - System.out.println("============================================================"); - - // Escalar desde 100 hasta 10,000 beans para validar O(1) - for (int scale = 100; scale <= 10000; scale *= 10) { - System.out.println("\n📊 TESTING AT SCALE: " + scale + " beans"); - benchmarkConfigurationProcessorO1Operations(scale); - } - - System.out.println("\n✅ CONFIGURATION PROCESSOR BENCHMARK COMPLETED - All O(1) validations passed!"); - } - - private static void benchmarkConfigurationProcessorO1Operations(int beanCount) { - OptimizedConfigurationProcessor processor = new OptimizedConfigurationProcessor(); - - // Procesar beans - for (int i = 0; i < beanCount; i++) { - String name = "configBean_" + i; - String type = "ConfigType" + (i % 10); // 10 tipos diferentes - processor.processBean(name, type); - } - - // 🧪 BENCHMARK 1: getActiveInstancesCount() - O(1) atomic counter - long startTime1 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.getActiveInstancesCount(); - } - long endTime1 = System.nanoTime(); - double avgTime1 = (endTime1 - startTime1) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 2: getAllCreatedInstances() - O(1) cache hit - processor.getAllCreatedInstances(); // Primera llamada - cache miss - long startTime2 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.getAllCreatedInstances(); - } - long endTime2 = System.nanoTime(); - double avgTime2 = (endTime2 - startTime2) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 3: getPhase2OptimizationStats() - O(1) string building - long startTime3 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.getPhase2OptimizationStats(); - } - long endTime3 = System.nanoTime(); - double avgTime3 = (endTime3 - startTime3) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 4: printConfigurationInfo() - O(1) cache hit - processor.printConfigurationInfo(); // Primera llamada - cache miss - long startTime4 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.printConfigurationInfo(); - } - long endTime4 = System.nanoTime(); - double avgTime4 = (endTime4 - startTime4) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 5: getExtremeStartupMetrics() - O(1) JSON building - long startTime5 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.getExtremeStartupMetrics(); - } - long endTime5 = System.nanoTime(); - double avgTime5 = (endTime5 - startTime5) / (double) MEASUREMENT_ITERATIONS; - - // 📊 RESULTS - System.out.println("\n📊 CONFIGURATION PROCESSOR O(1) OPTIMIZATION RESULTS:"); - System.out.println("=================================================="); - System.out.printf("1. getActiveInstancesCount(): %.2f ns (O(1) atomic counter)%n", avgTime1); - System.out.printf("2. getAllCreatedInstances(): %.2f ns (O(1) cache hit)%n", avgTime2); - System.out.printf("3. getPhase2OptimizationStats(): %.2f ns (O(1) string build)%n", avgTime3); - System.out.printf("4. printConfigurationInfo(): %.2f ns (O(1) cache hit)%n", avgTime4); - System.out.printf("5. getExtremeStartupMetrics(): %.2f ns (O(1) JSON build)%n", avgTime5); - - // 🧪 VALIDACIÓN DE COMPLEJIDAD - boolean isO1 = avgTime1 < 1000 && avgTime2 < 5000 && avgTime3 < 5000 && avgTime4 < 5000 && avgTime5 < 2000; - System.out.println("\n✅ O(1) VALIDATION: " + (isO1 ? "PASSED" : "ACCEPTABLE")); - - // Verificar que no hay degradación O(n) - if (beanCount >= 1000) { - System.out.println("🎯 SCALABILITY CHECK: Testing with " + beanCount + " beans"); - System.out.println("🔍 Performance remains constant regardless of scale: ✅"); - } - - // 🏆 PERFORMANCE SCORE - double avgPerformance = (avgTime1 + avgTime2 + avgTime3 + avgTime4 + avgTime5) / 5; - String score = avgPerformance < 1000 ? "EXCELLENT" : avgPerformance < 5000 ? "GOOD" : "ACCEPTABLE"; - System.out.println("🏆 CONFIGURATION PROCESSOR PERFORMANCE SCORE: " + score + " (avg: " + String.format("%.0f", avgPerformance) + "ns)"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ContainerMetricsO1Benchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ContainerMetricsO1Benchmark.java deleted file mode 100755 index 73b918e..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ContainerMetricsO1Benchmark.java +++ /dev/null @@ -1,414 +0,0 @@ -package io.warmup.framework.benchmark; - -import java.util.*; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Benchmark para validar optimizaciones O(1) en ContainerMetrics. - * Compara implementación optimizada (AtomicLong + TTL caches) vs secuencial. - * - * Operaciones testadas: - * - getActiveInstances(): O(1) atomic read vs O(n) stream filter - * - getResolutionCounts(): O(1) cache hit/miss vs O(n) iteration - * - getDependencyResolutionStats(): O(1) cache hit/miss vs O(n) multiple iterations - * - * Expected: Linear improvement en escalas altas (10x-100x) - */ -public class ContainerMetricsO1Benchmark { - - // ============================= - // SECUENTIAL IMPLEMENTATION (Baseline) - // ============================= - - static class MockDependency { - private final String className; - private final Object cachedInstance; - - public MockDependency(String className, boolean hasInstance) { - this.className = className; - this.cachedInstance = hasInstance ? new Object() : null; - } - - public Object getCachedInstance() { - return cachedInstance; - } - } - - static class MockContainer { - private final Map dependencies = new HashMap<>(); - - public void addDependency(String name, boolean hasInstance) { - dependencies.put(name, new MockDependency(name, hasInstance)); - } - - public Map getDependencies() { - return dependencies; - } - } - - static class SequentialContainerMetrics { - private final MockContainer container; - private final Map resolutionCounts = new HashMap<>(); - - public SequentialContainerMetrics(MockContainer container) { - this.container = container; - } - - // O(n) - stream filter over all dependencies - public int getActiveInstances() { - return (int) container.getDependencies().values().stream() - .filter(dep -> dep.getCachedInstance() != null) - .count(); - } - - // O(n) - iterate over all entries - public Map getResolutionCounts() { - Map counts = new HashMap<>(); - for (Map.Entry entry : resolutionCounts.entrySet()) { - counts.put(entry.getKey(), entry.getValue()); - } - return counts; - } - - // O(n) - multiple iterations - public Map getDependencyResolutionStats() { - Map stats = new HashMap<>(); - - // Iteration 1: calculate averages - double totalAvg = 0; - int count = 0; - for (Map.Entry entry : resolutionCounts.entrySet()) { - long value = entry.getValue(); - totalAvg += value; - count++; - } - stats.put("averageTime", count > 0 ? totalAvg / count : 0.0); - - // Iteration 2: find max - long maxTime = 0; - for (Map.Entry entry : resolutionCounts.entrySet()) { - if (entry.getValue() > maxTime) { - maxTime = entry.getValue(); - } - } - stats.put("maxTime", maxTime); - - // Iteration 3: count entries - stats.put("totalEntries", resolutionCounts.size()); - - return stats; - } - - public void addResolutionCount(String className) { - resolutionCounts.put(className, - resolutionCounts.getOrDefault(className, 0L) + 1); - } - } - - // ============================= - // OPTIMIZED IMPLEMENTATION (O(1)) - // ============================= - - static class OptimizedContainerMetrics { - private final MockContainer container; - private final Map resolutionCounts = new HashMap<>(); - - // O(1) Atomic counters - private final AtomicLong activeInstancesCount = new AtomicLong(0); - private final AtomicLong totalResolutionCountsCalls = new AtomicLong(0); - private final AtomicLong totalResolutionStatsCalls = new AtomicLong(0); - - // TTL cache fields - private volatile long activeInstancesCacheTimestamp = 0; - private volatile Integer cachedActiveInstances = null; - private volatile long resolutionCountsCacheTimestamp = 0; - private volatile Map cachedResolutionCounts = null; - private volatile long resolutionStatsCacheTimestamp = 0; - private volatile Map cachedResolutionStats = null; - private static final long CONTAINER_METRICS_CACHE_TTL_MS = 30000; - - public OptimizedContainerMetrics(MockContainer container) { - this.container = container; - } - - public void addResolutionCount(String className) { - resolutionCounts.put(className, - resolutionCounts.getOrDefault(className, 0L) + 1); - - // Invalidate caches for O(1) optimization - invalidateActiveInstancesCache(); - invalidateResolutionCountsCache(); - invalidateResolutionStatsCache(); - } - - // O(1) atomic read + TTL cache - public int getActiveInstances() { - long now = System.currentTimeMillis(); - - // Check cache validity (O(1)) - if (cachedActiveInstances != null && (now - activeInstancesCacheTimestamp) < CONTAINER_METRICS_CACHE_TTL_MS) { - return cachedActiveInstances; - } - - // Cache miss - O(n) operation - int count = (int) container.getDependencies().values().stream() - .filter(dep -> dep.getCachedInstance() != null) - .count(); - - // Update cache (O(1)) - cachedActiveInstances = count; - activeInstancesCacheTimestamp = now; - activeInstancesCount.set(count); - - return count; - } - - // O(1) atomic read + TTL cache - public Map getResolutionCounts() { - totalResolutionCountsCalls.incrementAndGet(); - long now = System.currentTimeMillis(); - - // Check cache validity (O(1)) - if (cachedResolutionCounts != null && (now - resolutionCountsCacheTimestamp) < CONTAINER_METRICS_CACHE_TTL_MS) { - return cachedResolutionCounts; - } - - // Cache miss - O(n) operation - Map counts = new HashMap<>(); - for (Map.Entry entry : resolutionCounts.entrySet()) { - counts.put(entry.getKey(), entry.getValue()); - } - - // Update cache (O(1)) - cachedResolutionCounts = counts; - resolutionCountsCacheTimestamp = now; - - return cachedResolutionCounts; - } - - // O(1) calculation with TTL cache - public Map getDependencyResolutionStats() { - totalResolutionStatsCalls.incrementAndGet(); - long now = System.currentTimeMillis(); - - // Check cache validity (O(1)) - if (cachedResolutionStats != null && (now - resolutionStatsCacheTimestamp) < CONTAINER_METRICS_CACHE_TTL_MS) { - return cachedResolutionStats; - } - - // Cache miss - O(n) operation - Map stats = new HashMap<>(); - - // Single iteration for all calculations - double totalAvg = 0; - int count = 0; - long maxTime = 0; - for (Map.Entry entry : resolutionCounts.entrySet()) { - long value = entry.getValue(); - totalAvg += value; - count++; - if (value > maxTime) { - maxTime = value; - } - } - - stats.put("averageTime", count > 0 ? totalAvg / count : 0.0); - stats.put("maxTime", maxTime); - stats.put("totalEntries", resolutionCounts.size()); - - // Update cache (O(1)) - cachedResolutionStats = stats; - resolutionStatsCacheTimestamp = now; - - return cachedResolutionStats; - } - - // O(1) cache invalidation methods - private void invalidateActiveInstancesCache() { - cachedActiveInstances = null; - activeInstancesCacheTimestamp = 0; - } - - private void invalidateResolutionCountsCache() { - cachedResolutionCounts = null; - resolutionCountsCacheTimestamp = 0; - } - - private void invalidateResolutionStatsCache() { - cachedResolutionStats = null; - resolutionStatsCacheTimestamp = 0; - } - - // O(1) getters for optimization metrics - public long getActiveInstancesCount() { - return activeInstancesCount.get(); - } - - public long getTotalResolutionCountsCalls() { - return totalResolutionCountsCalls.get(); - } - - public long getTotalResolutionStatsCalls() { - return totalResolutionStatsCalls.get(); - } - } - - // ============================= - // BENCHMARK EXECUTION - // ============================= - - public static void main(String[] args) { - System.out.println("🚀 ContainerMetrics O(1) Optimization Benchmark"); - System.out.println("=============================================="); - - int[] scales = {10, 50, 100, 500, 1000}; - - for (int scale : scales) { - System.out.println("\n📊 Testing at scale: " + scale); - for (int i = 0; i < 50; i++) { - System.out.print("-"); - } - System.out.println(); - - benchmarkContainerMetrics(scale); - } - - System.out.println("\n✅ Benchmark completed!"); - } - - private static void benchmarkContainerMetrics(int scale) { - // Setup data - MockContainer container = new MockContainer(); - String[] dependencyNames = new String[scale]; - Random random = new Random(42); - - for (int i = 0; i < scale; i++) { - dependencyNames[i] = "Dependency" + i; - boolean hasInstance = random.nextBoolean(); // 50% success rate - container.addDependency(dependencyNames[i], hasInstance); - } - - // Sequential (baseline) - SequentialContainerMetrics sequential = new SequentialContainerMetrics(container); - for (int i = 0; i < scale; i++) { - sequential.addResolutionCount(dependencyNames[i]); - } - - long seqStart = System.nanoTime(); - long seqGetActiveInstances = measureGetActiveInstances(sequential, scale); - long seqGetResolutionCounts = measureGetResolutionCounts(sequential, scale); - long seqGetResolutionStats = measureGetResolutionStats(sequential, scale); - long seqEnd = System.nanoTime(); - long seqTotal = seqEnd - seqStart; - - // Optimized (O(1)) - OptimizedContainerMetrics optimized = new OptimizedContainerMetrics(container); - for (int i = 0; i < scale; i++) { - optimized.addResolutionCount(dependencyNames[i]); - } - - // Warm up caches - optimized.getActiveInstances(); - optimized.getResolutionCounts(); - optimized.getDependencyResolutionStats(); - optimized.getActiveInstances(); - optimized.getResolutionCounts(); - optimized.getDependencyResolutionStats(); - - long optStart = System.nanoTime(); - long optGetActiveInstances = measureGetActiveInstances(optimized, scale); - long optGetResolutionCounts = measureGetResolutionCounts(optimized, scale); - long optGetResolutionStats = measureGetResolutionStats(optimized, scale); - long optEnd = System.nanoTime(); - long optTotal = optEnd - optStart; - - // Results - printResults(scale, seqGetActiveInstances, optGetActiveInstances, - seqGetResolutionCounts, optGetResolutionCounts, - seqGetResolutionStats, optGetResolutionStats, - seqTotal, optTotal); - } - - private static long measureGetActiveInstances(SequentialContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getActiveInstances(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetActiveInstances(OptimizedContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getActiveInstances(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetResolutionCounts(SequentialContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getResolutionCounts(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetResolutionCounts(OptimizedContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getResolutionCounts(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetResolutionStats(SequentialContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getDependencyResolutionStats(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetResolutionStats(OptimizedContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getDependencyResolutionStats(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static void printResults(int scale, - long seqGetActiveInstances, long optGetActiveInstances, - long seqGetResolutionCounts, long optGetResolutionCounts, - long seqGetResolutionStats, long optGetResolutionStats, - long seqTotal, long optTotal) { - - double improvementActiveInstances = (double)seqGetActiveInstances / optGetActiveInstances; - double improvementResolutionCounts = (double)seqGetResolutionCounts / optGetResolutionCounts; - double improvementResolutionStats = (double)seqGetResolutionStats / optGetResolutionStats; - double totalImprovement = (double)seqTotal / optTotal; - - System.out.printf("📈 getActiveInstances(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetActiveInstances, optGetActiveInstances, improvementActiveInstances); - System.out.printf("📈 getResolutionCounts(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetResolutionCounts, optGetResolutionCounts, improvementResolutionCounts); - System.out.printf("📈 getDependencyResolutionStats(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetResolutionStats, optGetResolutionStats, improvementResolutionStats); - System.out.printf("🎯 Total Improvement: %.1fx faster\n", totalImprovement); - - // O(1) validation - if (improvementActiveInstances >= 5.0 && improvementResolutionCounts >= 5.0) { - System.out.println("✅ O(1) operations validated!"); - } - - if (scale >= 100 && improvementResolutionStats >= 2.0) { - System.out.println("✅ Cache effectiveness validated!"); - } - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DependencyRegistryO1BenchmarkDirect.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DependencyRegistryO1BenchmarkDirect.java deleted file mode 100755 index 05fb73e..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DependencyRegistryO1BenchmarkDirect.java +++ /dev/null @@ -1,185 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 🚀 BENCHMARK O(1) DIRECTO - DependencyRegistry Optimizations - * - * Valida las optimizaciones O(1) aplicadas a DependencyRegistry - * sin dependencias de frameworks externos. Prueba métodos críticos - * con diferentes escalas para verificar complejidad constante. - */ -public class DependencyRegistryO1BenchmarkDirect { - - // Simulación de DependencyRegistry con optimizaciones O(1) - private static class OptimizedDependencyRegistry { - // Contadores atómicos O(1) - private final AtomicLong activeInstancesCount = new AtomicLong(0); - - // Caches TTL para métodos O(1) - private volatile long instancesCacheTimestamp = 0; - private volatile List cachedInstances = null; - private static final long CACHE_TTL_MS = 30000; - - // Índices O(1) - private final Map> nameToTypes = new ConcurrentHashMap<>(); - private final Map> typeToNames = new ConcurrentHashMap<>(); - - // Datos de prueba - private final Map namedDependencies = new ConcurrentHashMap<>(); - - // 🚀 O(1): Contador atómico - public long getActiveInstancesCount() { - return activeInstancesCount.get(); - } - - // 🚀 O(1): Cache con TTL - public List getAllCreatedInstances() { - long currentTime = System.currentTimeMillis(); - - // Cache hit - if (cachedInstances != null && - (currentTime - instancesCacheTimestamp) < CACHE_TTL_MS) { - return new ArrayList<>(cachedInstances); - } - - // Cache miss - calcular (solo una vez cada 30 segundos) - List instances = new ArrayList<>(namedDependencies.keySet()); - - // Actualizar cache - cachedInstances = new ArrayList<>(instances); - instancesCacheTimestamp = currentTime; - - return instances; - } - - // 🚀 O(1): Lookup por índice - public Set getDependenciesByType(String type) { - Set result = typeToNames.get(type); - return result != null ? new HashSet<>(result) : new HashSet<>(); - } - - // 🚀 O(1): Vista cached - public Map getAllDependencies() { - return new HashMap<>(namedDependencies); - } - - // 🚀 O(1): Stats con cache - public String getPhase2OptimizationStats() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - instancesCacheTimestamp; - - StringBuilder stats = new StringBuilder(); - stats.append("\n🚀 DEPENDENCY REGISTRY O(1) OPTIMIZATION STATS"); - stats.append("\n==========================================="); - stats.append("\n📊 Active Instances: ").append(activeInstancesCount.get()); - stats.append("\n📊 Total Dependencies: ").append(namedDependencies.size()); - stats.append("\n📊 Type Index Size: ").append(typeToNames.size()); - stats.append("\n📊 Cache Age: ").append(cacheAge).append("ms"); - stats.append("\n✅ O(1) operations validated!"); - - return stats.toString(); - } - - // Simulación de registro de dependencia - public void registerNamed(String name, String type) { - namedDependencies.put(name, type); - typeToNames.computeIfAbsent(type, k -> ConcurrentHashMap.newKeySet()).add(name); - nameToTypes.computeIfAbsent(name, k -> new ConcurrentHashMap<>()).put("type", type); - activeInstancesCount.incrementAndGet(); - } - - // Limpiar caches - public void invalidateCaches() { - instancesCacheTimestamp = 0; - cachedInstances = null; - } - } - - private static final int WARMUP_ITERATIONS = 100; - private static final int MEASUREMENT_ITERATIONS = 1000; - - public static void main(String[] args) { - System.out.println("🚀 DEPENDENCY REGISTRY O(1) BENCHMARK - DIRECT VALIDATION"); - System.out.println("================================================================"); - - // Escalar desde 100 hasta 10,000 dependencias para validar O(1) - for (int scale = 100; scale <= 10000; scale *= 10) { - System.out.println("\n📊 TESTING AT SCALE: " + scale + " dependencies"); - benchmarkDependencyRegistryO1Operations(scale); - } - - System.out.println("\n✅ BENCHMARK COMPLETED - All O(1) validations passed!"); - } - - private static void benchmarkDependencyRegistryO1Operations(int dependencyCount) { - OptimizedDependencyRegistry registry = new OptimizedDependencyRegistry(); - - // Registrar dependencias - for (int i = 0; i < dependencyCount; i++) { - String name = "dependency_" + i; - String type = "Type" + (i % 10); // 10 tipos diferentes - registry.registerNamed(name, type); - } - - // 🧪 BENCHMARK 1: getActiveInstancesCount() - O(1) atomic counter - long startTime1 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getActiveInstancesCount(); - } - long endTime1 = System.nanoTime(); - double avgTime1 = (endTime1 - startTime1) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 2: getAllCreatedInstances() - O(1) cache hit - registry.getAllCreatedInstances(); // Primera llamada - cache miss - long startTime2 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getAllCreatedInstances(); - } - long endTime2 = System.nanoTime(); - double avgTime2 = (endTime2 - startTime2) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 3: getDependenciesByType() - O(1) index lookup - long startTime3 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getDependenciesByType("Type0"); - } - long endTime3 = System.nanoTime(); - double avgTime3 = (endTime3 - startTime3) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 4: getAllDependencies() - O(1) map copy - long startTime4 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getAllDependencies(); - } - long endTime4 = System.nanoTime(); - double avgTime4 = (endTime4 - startTime4) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 5: getPhase2OptimizationStats() - O(1) string building - long startTime5 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getPhase2OptimizationStats(); - } - long endTime5 = System.nanoTime(); - double avgTime5 = (endTime5 - startTime5) / (double) MEASUREMENT_ITERATIONS; - - // 📊 RESULTS - System.out.println("\n📊 O(1) OPTIMIZATION RESULTS:"); - System.out.println("=============================="); - System.out.printf("1. getActiveInstancesCount(): %.2f ns (O(1) atomic counter)%n", avgTime1); - System.out.printf("2. getAllCreatedInstances(): %.2f ns (O(1) cache hit)%n", avgTime2); - System.out.printf("3. getDependenciesByType(): %.2f ns (O(1) index lookup)%n", avgTime3); - System.out.printf("4. getAllDependencies(): %.2f ns (O(1) map copy)%n", avgTime4); - System.out.printf("5. getPhase2OptimizationStats(): %.2f ns (O(1) string build)%n", avgTime5); - - // 🧪 VALIDACIÓN DE COMPLEJIDAD - boolean isO1 = avgTime1 < 1000 && avgTime2 < 5000 && avgTime3 < 1000 && avgTime4 < 2000 && avgTime5 < 10000; - System.out.println("\n✅ O(1) VALIDATION: " + (isO1 ? "PASSED" : "FAILED")); - - // Verificar que no hay degradación O(n) - if (dependencyCount >= 1000) { - System.out.println("🎯 SCALABILITY CHECK: Testing with " + dependencyCount + " dependencies"); - System.out.println("🔍 Performance remains constant regardless of scale: ✅"); - } - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DependencyRegistryO1ComparisonBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DependencyRegistryO1ComparisonBenchmark.java deleted file mode 100755 index 6755c37..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DependencyRegistryO1ComparisonBenchmark.java +++ /dev/null @@ -1,208 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 🚀 COMPARATIVA O(1) vs O(n) - DependencyRegistry Performance - * - * Compara las optimizaciones O(1) aplicadas contra implementación - * secuencial O(n) para demostrar la mejora de rendimiento. - */ -public class DependencyRegistryO1ComparisonBenchmark { - - // Implementación O(n) SECUENCIAL (sin optimizaciones) - private static class SequentialDependencyRegistry { - private final Map dependencies = new HashMap<>(); - private long activeInstancesCount = 0; - - // ❌ O(n): Búsqueda secuencial - public List getAllCreatedInstances() { - List instances = new ArrayList<>(); - for (String key : dependencies.keySet()) { // Bucle O(n) - instances.add(key); - } - return instances; - } - - // ❌ O(n): Búsqueda secuencial por tipo - public List getDependenciesByType(String targetType) { - List result = new ArrayList<>(); - for (Map.Entry entry : dependencies.entrySet()) { // Bucle O(n) - if (entry.getValue().equals(targetType)) { - result.add(entry.getKey()); - } - } - return result; - } - - // ❌ O(n): Iteración completa - public Map getAllDependencies() { - Map result = new HashMap<>(); - for (Map.Entry entry : dependencies.entrySet()) { // Bucle O(n) - result.put(entry.getKey(), entry.getValue()); - } - return result; - } - - // ❌ O(n): Conteo secuencial - public long getActiveInstancesCount() { - long count = 0; - for (String key : dependencies.keySet()) { // Bucle O(n) - count++; - } - return count; - } - - public void registerNamed(String name, String type) { - dependencies.put(name, type); - activeInstancesCount++; - } - } - - // Implementación O(1) OPTIMIZADA (con nuestras optimizaciones) - private static class OptimizedDependencyRegistry { - private final AtomicLong activeInstancesCount = new AtomicLong(0); - private volatile long cacheTimestamp = 0; - private volatile List cachedInstances = null; - private static final long CACHE_TTL_MS = 30000; - - private final Map> nameToTypes = new ConcurrentHashMap<>(); - private final Map> typeToNames = new ConcurrentHashMap<>(); - private final Map namedDependencies = new ConcurrentHashMap<>(); - - // ✅ O(1): Contador atómico - public long getActiveInstancesCount() { - return activeInstancesCount.get(); - } - - // ✅ O(1): Cache con TTL - public List getAllCreatedInstances() { - long currentTime = System.currentTimeMillis(); - - if (cachedInstances != null && - (currentTime - cacheTimestamp) < CACHE_TTL_MS) { - return new ArrayList<>(cachedInstances); - } - - List instances = new ArrayList<>(namedDependencies.keySet()); - cachedInstances = new ArrayList<>(instances); - cacheTimestamp = currentTime; - - return instances; - } - - // ✅ O(1): Lookup directo por índice - public Set getDependenciesByType(String type) { - Set result = typeToNames.get(type); - return result != null ? new HashSet<>(result) : new HashSet<>(); - } - - // ✅ O(1): Map copy directo - public Map getAllDependencies() { - return new HashMap<>(namedDependencies); - } - - public void registerNamed(String name, String type) { - namedDependencies.put(name, type); - typeToNames.computeIfAbsent(type, k -> ConcurrentHashMap.newKeySet()).add(name); - activeInstancesCount.incrementAndGet(); - } - } - - private static final int MEASUREMENT_ITERATIONS = 500; - - public static void main(String[] args) { - System.out.println("🚀 O(1) vs O(n) COMPARISON - DependencyRegistry Performance"); - System.out.println("==========================================================="); - - // Escalar para mostrar diferencia O(1) vs O(n) - for (int scale = 100; scale <= 5000; scale *= 5) { - System.out.println("\n📊 COMPARISON AT SCALE: " + scale + " dependencies"); - compareO1VsOnPerformance(scale); - } - - System.out.println("\n🏆 CONCLUSION: O(1) optimizations provide constant-time performance!"); - } - - private static void compareO1VsOnPerformance(int dependencyCount) { - SequentialDependencyRegistry sequential = new SequentialDependencyRegistry(); - OptimizedDependencyRegistry optimized = new OptimizedDependencyRegistry(); - - // Poblar ambas implementaciones - for (int i = 0; i < dependencyCount; i++) { - String name = "dep_" + i; - String type = "Type" + (i % 20); // 20 tipos diferentes - sequential.registerNamed(name, type); - optimized.registerNamed(name, type); - } - - // 🧪 Benchmark getAllCreatedInstances() - long seqStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - sequential.getAllCreatedInstances(); - } - long seqEnd = System.nanoTime(); - long sequentialTime = (seqEnd - seqStart) / MEASUREMENT_ITERATIONS; - - long optStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - optimized.getAllCreatedInstances(); - } - long optEnd = System.nanoTime(); - long optimizedTime = (optEnd - optStart) / MEASUREMENT_ITERATIONS; - - double improvement = (double) sequentialTime / optimizedTime; - - System.out.println("📈 getAllCreatedInstances():"); - System.out.printf(" Sequential O(n): %,d ns%n", sequentialTime); - System.out.printf(" Optimized O(1): %,d ns%n", optimizedTime); - System.out.printf(" 🚀 IMPROVEMENT: %.1fx faster%n", improvement); - - // 🧪 Benchmark getActiveInstancesCount() - seqStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - sequential.getActiveInstancesCount(); - } - seqEnd = System.nanoTime(); - sequentialTime = (seqEnd - seqStart) / MEASUREMENT_ITERATIONS; - - optStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - optimized.getActiveInstancesCount(); - } - optEnd = System.nanoTime(); - optimizedTime = (optEnd - optStart) / MEASUREMENT_ITERATIONS; - - improvement = (double) sequentialTime / optimizedTime; - - System.out.println("📈 getActiveInstancesCount():"); - System.out.printf(" Sequential O(n): %,d ns%n", sequentialTime); - System.out.printf(" Optimized O(1): %,d ns%n", optimizedTime); - System.out.printf(" 🚀 IMPROVEMENT: %.1fx faster%n", improvement); - - // 🧪 Benchmark getDependenciesByType() - String testType = "Type0"; - seqStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - sequential.getDependenciesByType(testType); - } - seqEnd = System.nanoTime(); - sequentialTime = (seqEnd - seqStart) / MEASUREMENT_ITERATIONS; - - optStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - optimized.getDependenciesByType(testType); - } - optEnd = System.nanoTime(); - optimizedTime = (optEnd - optStart) / MEASUREMENT_ITERATIONS; - - improvement = (double) sequentialTime / optimizedTime; - - System.out.println("📈 getDependenciesByType():"); - System.out.printf(" Sequential O(n): %,d ns%n", sequentialTime); - System.out.printf(" Optimized O(1): %,d ns%n", optimizedTime); - System.out.printf(" 🚀 IMPROVEMENT: %.1fx faster%n", improvement); - - System.out.println("✅ O(1) optimizations validated at scale " + dependencyCount); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DependencyResolutionBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DependencyResolutionBenchmark.java deleted file mode 100755 index a960aa4..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DependencyResolutionBenchmark.java +++ /dev/null @@ -1,147 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.DependencyRegistry; -import io.warmup.framework.core.Dependency; -import io.warmup.framework.core.WarmupContainer; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.io.File; -import java.util.concurrent.TimeUnit; - -/** - * 🚀 BENCHMARK O(1) vs O(n) - Dependency Resolution Performance - * - * Demuestra el verdadero diferencial competitivo de Warmup: - * - Búsquedas O(1) vs O(n) de Spring - * - Escalabilidad superior - * - Performance arquitectónicamente superior - */ -@BenchmarkMode({Mode.AverageTime, Mode.SampleTime}) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Benchmark) -@Fork(value = 1, jvmArgs = {"-Xmx2G"}) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -public class DependencyResolutionBenchmark { - - // Test interfaces e implementaciones - public interface ServiceInterface {} - public static class ServiceImpl implements ServiceInterface {} - public static class ServiceImpl2 implements ServiceInterface {} - public static class ServiceImpl3 implements ServiceInterface {} - - // Configuración del benchmark - @Param({"10", "100", "1000"}) - private int dependencyCount; - - private DependencyRegistry registry; - private WarmupContainer container; - private ServiceInterface[] services; - - @Setup - public void setup() { - System.out.println("🔧 Configurando benchmark con " + dependencyCount + " dependencias..."); - - container = new WarmupContainer(); - registry = new DependencyRegistry(container, null, java.util.Collections.singleton("default")); - - // Crear múltiples servicios para el benchmark - services = new ServiceInterface[dependencyCount]; - for (int i = 0; i < dependencyCount; i++) { - Class serviceClass = i % 3 == 0 ? ServiceImpl.class : - (i % 3 == 1 ? ServiceImpl2.class : ServiceImpl3.class); - - // Registrar con diferentes nombres - String serviceName = "service_" + i; - registry.registerNamed(serviceClass, serviceName, true); - - // Pre-cargar algunas para cache - if (i < dependencyCount / 10) { - services[i] = registry.getNamed(ServiceInterface.class, serviceName); - } - } - } - - @Benchmark - @BenchmarkMode(Mode.AverageTime) - public ServiceInterface benchmarkO1NamedLookup() { - // 🚀 OPTIMIZACIÓN O(1): Lookup directo por índice - String name = "service_" + (dependencyCount / 2); - return registry.getNamed(ServiceInterface.class, name); - } - - @Benchmark - @BenchmarkMode(Mode.AverageTime) - public java.util.Map benchmarkO1InterfaceLookups() { - // 🚀 OPTIMIZACIÓN O(1): Búsqueda por interfaz sin bucles - return registry.getNamedImplementations(ServiceInterface.class); - } - - @Benchmark - @BenchmarkMode(Mode.AverageTime) - public ServiceInterface benchmarkDirectGet() { - // Prueba de lookup directo simple - Class serviceClass = ServiceImpl.class; - ServiceImpl service = registry.getBean(serviceClass); - return service; - } - - /** - * 🎯 MÉTRICAS ARQUITECTÓNICAS CLAVE - */ - @TearDown - public void printArchitecturalMetrics() { - System.out.println("\n🏗️ MÉTRICAS ARQUITECTÓNICAS:"); - System.out.println("Dependencies: " + dependencyCount); - System.out.println("Registry namedDependencies: " + registry.getNamedDependencies().size()); - System.out.println("Registry dependencies: " + registry.getDependencies().size()); - - // Simular métricas de eficiencia O(1) - long o1Operations = dependencyCount; // O(1) siempre usa índice directo - long onOperations = dependencyCount * (dependencyCount / 2); // O(n) promedio - - System.out.println("🚀 EFICIENCIA O(1): " + o1Operations + " operaciones"); - System.out.println("⚠️ COMPARABLE O(n): " + onOperations + " operaciones"); - System.out.println("⚡ VENTAJA ARQUITECTÓNICA: " + - String.format("%.1fx", (double)onOperations / o1Operations) + " más eficiente"); - } - - /** - * 🚀 DEMOSTRAR DIFERENCIAL COMPETITIVO - */ - public static void main(String[] args) throws RunnerException { - System.out.println("🎯 WARMUP O(1) vs O(n) - BENCHMARK DE DIFERENCIAL COMPETITIVO"); - System.out.println("================================================================"); - - // Ejecutar benchmark - Options opt = new OptionsBuilder() - .include(DependencyResolutionBenchmark.class.getSimpleName()) - .result("benchmark-results/" + System.currentTimeMillis() + "-dependency-resolution.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - new Runner(opt).run(); - - // Análisis de resultados - analyzeCompetitiveAdvantage(); - } - - private static void analyzeCompetitiveAdvantage() { - System.out.println("\n🎯 ANÁLISIS DE VENTAJA COMPETITIVA:"); - System.out.println("====================================="); - System.out.println("✅ Warmup: Resolución O(1) - Indexado arquitectónicamente"); - System.out.println("❌ Spring: Resolución O(n) - Búsquedas lineales"); - System.out.println(); - System.out.println("📊 IMPACTO EN ESCALABILIDAD:"); - System.out.println("10 dependencias: Warmup 1x vs Spring 10x más lento"); - System.out.println("100 dependencias: Warmup 1x vs Spring 100x más lento"); - System.out.println("1000 dependencias: Warmup 1x vs Spring 1000x más lento"); - System.out.println(); - System.out.println("🚀 VENTAJA ARQUITECTÓNICA REAL: O(1) ≠ O(n)"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DirectComplexityBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DirectComplexityBenchmark.java deleted file mode 100755 index e96f149..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/DirectComplexityBenchmark.java +++ /dev/null @@ -1,341 +0,0 @@ -package io.warmup.framework.benchmark; - -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -/** - * Benchmark directo que demuestra la superioridad de O(1) vs O(n) vs O(log n) - * - * Este benchmark simula los principios de resolución de dependencias: - * - O(1): HashMap/ConcurrentHashMap (como Warmup optimizado) - * - O(log n): TreeMap (búsqueda binaria) - * - O(n): ArrayList (búsqueda lineal, como frameworks tradicionales) - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Benchmark) -@Fork(value = 2, jvmArgs = {"-Xmx2G", "-Xms1G", "-XX:+UseG1GC"}) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -public class DirectComplexityBenchmark { - - // ==================== DATA STRUCTURES ==================== - // O(1) - ConcurrentHashMap (como WarmupContainer) - private ConcurrentHashMap concurrentHashMap; - - // O(1) - HashMap baseline - private HashMap hashMap; - - // O(log n) - TreeMap (búsqueda binaria) - private TreeMap treeMap; - - // O(n) - ArrayList (búsqueda lineal, como frameworks tradicionales) - private ArrayList arrayList; - - // ==================== TEST DATA ==================== - private static final int DATASET_SIZE = 1000; - private String[] keys; - private Object[] values; - - // Helper class para ArrayList entries - private static class ObjectEntry { - final String key; - final Object value; - - ObjectEntry(String key, Object value) { - this.key = key; - this.value = value; - } - } - - @Setup - public void setup() { - System.out.println("🔧 Setting up DirectComplexityBenchmark with dataset size: " + DATASET_SIZE); - - // Generate test data - keys = new String[DATASET_SIZE]; - values = new Object[DATASET_SIZE]; - - for (int i = 0; i < DATASET_SIZE; i++) { - keys[i] = "key_" + i; - int finalI = i; // Variable effectively final para inner class - values[i] = new Object() { - @Override - public String toString() { - return "Value_" + finalI; - } - }; - } - - // Initialize O(1) structures - concurrentHashMap = new ConcurrentHashMap<>(); - hashMap = new HashMap<>(); - - // Initialize O(log n) structure - treeMap = new TreeMap<>(); - - // Initialize O(n) structure - arrayList = new ArrayList<>(); - - // Populate all structures with same data - for (int i = 0; i < DATASET_SIZE; i++) { - String key = keys[i]; - Object value = values[i]; - - concurrentHashMap.put(key, value); - hashMap.put(key, value); - treeMap.put(key, value); - arrayList.add(new ObjectEntry(key, value)); - } - - System.out.println("✅ Data structures initialized"); - } - - // ==================== O(1) BENCHMARKS ==================== - - /** - * Benchmark: ConcurrentHashMap O(1) - Simula WarmupContainer.get() - * ConcurrentHashMap es thread-safe y usado en Warmup para resolución O(1) - */ - @Benchmark - public Object concurrentHashMapGet() { - // Simula búsqueda en el medio del dataset - return concurrentHashMap.get("key_" + (DATASET_SIZE / 2)); - } - - /** - * Benchmark: HashMap O(1) baseline - * HashMap estándar para comparación - */ - @Benchmark - public Object hashMapGet() { - return hashMap.get("key_" + (DATASET_SIZE / 2)); - } - - /** - * Benchmark: ConcurrentHashMap con claves aleatorias - * Simula búsquedas más realistas - */ - @Benchmark - public Object concurrentHashMapRandomAccess() { - int index = (int) (System.nanoTime() % DATASET_SIZE); - return concurrentHashMap.get("key_" + index); - } - - // ==================== O(log n) BENCHMARKS ==================== - - /** - * Benchmark: TreeMap O(log n) - Búsqueda binaria - * TreeMap mantiene ordenamiento y usa red-black trees - */ - @Benchmark - public Object treeMapGet() { - return treeMap.get("key_" + (DATASET_SIZE / 2)); - } - - /** - * Benchmark: TreeMap con floorEntry (O(log n) operation) - */ - @Benchmark - public Object treeMapFloorEntry() { - return treeMap.floorEntry("key_" + (DATASET_SIZE / 2)); - } - - // ==================== O(n) BENCHMARKS ==================== - - /** - * Benchmark: ArrayList O(n) - Búsqueda lineal - * Simula el comportamiento de frameworks DI tradicionales - */ - @Benchmark - public Object arrayListGet() { - String targetKey = "key_" + (DATASET_SIZE / 2); - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - return entry.value; - } - } - return null; - } - - /** - * Benchmark: ArrayList búsqueda desde el inicio - * Peor caso para búsqueda lineal - */ - @Benchmark - public Object arrayListGetFromStart() { - String targetKey = "key_" + (DATASET_SIZE - 1); // Last element - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - return entry.value; - } - } - return null; - } - - /** - * Benchmark: ArrayList búsqueda desde el final - * Mejor caso para búsqueda lineal - */ - @Benchmark - public Object arrayListGetFromEnd() { - String targetKey = "key_0"; // First element - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - return entry.value; - } - } - return null; - } - - /** - * Benchmark: ArrayList con múltiples búsquedas - * Simula uso real con múltiples resoluciones - */ - @Benchmark - public String arrayListMultipleSearches() { - StringBuilder result = new StringBuilder(); - - // Buscar 3 elementos diferentes - for (int i = 0; i < 3; i++) { - String targetKey = "key_" + (i * 100); - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - result.append(entry.value.toString()).append("-"); - break; - } - } - } - - return result.toString(); - } - - // ==================== COMPARISON BENCHMARKS ==================== - - /** - * Benchmark: Múltiples búsquedas O(1) vs O(n) - * Demuestra la diferencia escalando el problema - */ - @Benchmark - public String concurrentHashMapVsArrayList() { - StringBuilder result = new StringBuilder(); - - // O(1) búsquedas - for (int i = 0; i < 10; i++) { - Object obj1 = concurrentHashMap.get("key_" + (i * 10)); - result.append(obj1 != null ? obj1.toString() : "null").append(","); - } - - result.append("|"); - - // O(n) búsquedas - for (int i = 0; i < 10; i++) { - String targetKey = "key_" + (i * 10); - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - result.append(entry.value.toString()).append(","); - break; - } - } - } - - return result.toString(); - } - - /** - * Benchmark: Carga de trabajo mixta - * Simula patrones de acceso reales - */ - @Benchmark - public Object mixedWorkload() { - // 70% búsquedas O(1) - Object result1 = concurrentHashMap.get("key_" + (DATASET_SIZE / 2)); - - // 30% búsquedas O(n) para comparación - String targetKey = "key_" + (DATASET_SIZE / 2); - Object result2 = null; - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - result2 = entry.value; - break; - } - } - - return result1 != null ? result1 : result2; - } - - // ==================== SCALABILITY TESTS ==================== - - /** - * Benchmark: Escalabilidad O(1) - * Muestra que O(1) se mantiene constante - */ - @Benchmark - public Object scalabilityO1() { - int index = (int) (System.nanoTime() % DATASET_SIZE); - return concurrentHashMap.get("key_" + index); - } - - /** - * Benchmark: Escalabilidad O(n) - * Muestra que O(n) degrada linealmente - */ - @Benchmark - public Object scalabilityOn() { - int index = (int) (System.nanoTime() % DATASET_SIZE); - String targetKey = "key_" + index; - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - return entry.value; - } - } - return null; - } - - /** - * Benchmark: Escalabilidad O(log n) - * Muestra que O(log n) crece lentamente - */ - @Benchmark - public Object scalabilityOlogN() { - int index = (int) (System.nanoTime() % DATASET_SIZE); - return treeMap.get("key_" + index); - } - - public static void main(String[] args) throws RunnerException { - System.out.println("🚀 Iniciando DirectComplexityBenchmark..."); - System.out.println("Demostrando la superioridad de O(1) vs O(n) vs O(log n)"); - System.out.println("Dataset size: " + DATASET_SIZE + " elementos"); - - // Configurar el benchmark - Options opt = new OptionsBuilder() - .include(DirectComplexityBenchmark.class.getSimpleName()) - .output("complexity-benchmark-results.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - // Ejecutar benchmark - new Runner(opt).run(); - - System.out.println("✅ Benchmark completado. Resultados en complexity-benchmark-results.json"); - - // Mostrar resumen esperado - System.out.println("\n📊 RESULTADOS ESPERADOS:"); - System.out.println("🏆 O(1) - ConcurrentHashMap/HashMap: ~0.001-0.005 μs (GANADOR)"); - System.out.println("🥈 O(log n) - TreeMap: ~0.005-0.015 μs"); - System.out.println("🥉 O(n) - ArrayList: ~0.050-0.500 μs (degrada con tamaño)"); - System.out.println("\n💡 CONCLUSIÓN:"); - System.out.println("• Warmup Framework usa O(1) ConcurrentHashMap"); - System.out.println("• Frameworks tradicionales usan O(n) linear search"); - System.out.println("• Diferencia de rendimiento: 10x-100x a favor de O(1)"); - System.out.println("• Warmup es el futuro de la inyección de dependencias!"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/EventBusO1BenchmarkDirect.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/EventBusO1BenchmarkDirect.java deleted file mode 100755 index 53b25a2..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/EventBusO1BenchmarkDirect.java +++ /dev/null @@ -1,464 +0,0 @@ -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Consumer; - -/** - * EventBus O(1) Optimization Benchmark Direct - * Validates O(1) optimizations for EventBus with real performance testing - * - * @author MiniMax Agent - * @version 1.0 - */ -public class EventBusO1BenchmarkDirect { - - // ========== OPTIMIZED EVENTBUS IMPLEMENTATION ========== - - interface Event { - String getName(); - } - - interface EventListener { - void onEvent(T event); - } - - interface EventStatistics { - void recordAction(String action); - } - - static class SimpleEventStatistics implements EventStatistics { - private final AtomicLong publishedCount = new AtomicLong(0); - private final AtomicLong processedCount = new AtomicLong(0); - private final AtomicLong failedCount = new AtomicLong(0); - private final AtomicLong totalProcessingTime = new AtomicLong(0); - - @Override - public void recordAction(String action) { - switch (action.toLowerCase()) { - case "published": publishedCount.incrementAndGet(); break; - case "processed": processedCount.incrementAndGet(); break; - case "failed": failedCount.incrementAndGet(); break; - } - } - } - - static class OptimizedEventBus { - private final ConcurrentHashMap, List>> listeners = new ConcurrentHashMap<>(); - private final ConcurrentHashMap, EventStatistics> eventStatistics = new ConcurrentHashMap<>(); - - // O(1) OPTIMIZATION FIELDS - private final AtomicLong totalListenersCount = new AtomicLong(0); - private final AtomicLong totalEventsPublishedCount = new AtomicLong(0); - - private volatile long listenerStatsCacheTimestamp = 0; - private volatile String cachedListenerStats = null; - private volatile long allStatsCacheTimestamp = 0; - private volatile ConcurrentHashMap, EventStatistics> cachedAllStats = null; - - private static final long LISTENER_STATS_CACHE_TTL_MS = 30000; // 30 seconds - private static final long ALL_STATS_CACHE_TTL_MS = 30000; // 30 seconds - - private void invalidateListenerCaches() { - listenerStatsCacheTimestamp = 0; - cachedListenerStats = null; - } - - private void invalidateAllStatsCache() { - allStatsCacheTimestamp = 0; - cachedAllStats = null; - } - - private void invalidateAllCaches() { - invalidateListenerCaches(); - invalidateAllStatsCache(); - } - - public void registerListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - listeners.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>()).add(listener); - totalListenersCount.incrementAndGet(); // O(1) atomic increment - invalidateListenerCaches(); // Clear cached stats - } - - public void unregisterListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - List> eventListeners = listeners.get(eventType); - if (eventListeners != null) { - boolean removed = eventListeners.remove(listener); - if (removed) { - totalListenersCount.decrementAndGet(); // O(1) atomic decrement - invalidateListenerCaches(); // Clear cached stats - } - - if (eventListeners.isEmpty()) { - listeners.remove(eventType); - } - } - } - - @SuppressWarnings("unchecked") - public void publishEvent(T event) { - if (event == null) return; - - Class eventType = event.getClass(); - List> eventListeners = listeners.get(eventType); - - EventStatistics stats = eventStatistics.computeIfAbsent(eventType, k -> new SimpleEventStatistics()); - stats.recordAction("published"); - totalEventsPublishedCount.incrementAndGet(); // O(1) atomic increment - - if (eventListeners != null && !eventListeners.isEmpty()) { - for (EventListener listener : eventListeners) { - try { - ((EventListener) listener).onEvent(event); - stats.recordAction("processed"); - } catch (Exception e) { - stats.recordAction("failed"); - } - } - } - } - - // O(1) OPTIMIZED METHODS - public long getListenerCount() { - return totalListenersCount.get(); // O(1) atomic read - } - - public long getTotalEventsPublishedCount() { - return totalEventsPublishedCount.get(); // O(1) atomic read - } - - public long getEventBusExtremeStartupMetrics() { - long listeners = getListenerCount(); - long events = totalEventsPublishedCount.get(); - - long baseCost = 50; // 50ns base cost - long listenerCost = listeners * 2; // 2ns per listener - long eventCost = events * 5; // 5ns per event - - return baseCost + listenerCost + eventCost; - } - - public void clearAllListeners() { - listeners.clear(); - totalListenersCount.set(0); // O(1) atomic reset - invalidateAllCaches(); // Clear all cached data - } - } - - // ========== SEQUENTIAL O(n) IMPLEMENTATION FOR COMPARISON ========== - - static class SequentialEventBus { - private final java.util.Map, List>> listeners = new java.util.HashMap<>(); - private final java.util.Map, EventStatistics> eventStatistics = new java.util.HashMap<>(); - private long totalListenersCount = 0; - private long totalEventsPublishedCount = 0; - - public void registerListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - listeners.computeIfAbsent(eventType, k -> new java.util.ArrayList<>()).add(listener); - totalListenersCount++; // O(n) increment - } - - public void unregisterListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - List> eventListeners = listeners.get(eventType); - if (eventListeners != null) { - boolean removed = eventListeners.remove(listener); - if (removed) totalListenersCount--; // O(n) decrement - if (eventListeners.isEmpty()) listeners.remove(eventType); - } - } - - @SuppressWarnings("unchecked") - public void publishEvent(T event) { - if (event == null) return; - - Class eventType = event.getClass(); - List> eventListeners = listeners.get(eventType); - - EventStatistics stats = eventStatistics.computeIfAbsent(eventType, k -> new SimpleEventStatistics()); - stats.recordAction("published"); - totalEventsPublishedCount++; // O(n) increment - - if (eventListeners != null && !eventListeners.isEmpty()) { - for (EventListener listener : eventListeners) { - try { - ((EventListener) listener).onEvent(event); - stats.recordAction("processed"); - } catch (Exception e) { - stats.recordAction("failed"); - } - } - } - } - - public long getListenerCount() { - // O(n) - iterate through all lists - return listeners.values().stream() - .mapToInt(List::size) - .sum(); - } - - public long getTotalEventsPublishedCount() { - return totalEventsPublishedCount; - } - - public long getEventBusExtremeStartupMetrics() { - long listeners = getListenerCount(); - long events = totalEventsPublishedCount; - - // O(n) calculation with additional overhead - long baseCost = 100; // Higher base cost due to O(n) operations - long listenerCost = (long)(listeners * 10.5); // 10.5ns per listener (higher due to iteration) - long eventCost = (long)(events * 25.3); // 25.3ns per event (higher due to O(n)) - - return baseCost + listenerCost + eventCost; - } - - public void clearAllListeners() { - listeners.clear(); - totalListenersCount = 0; - } - } - - // ========== TEST EVENTS AND LISTENERS ========== - - static class TestEvent implements Event { - private final String name; - private final String data; - - public TestEvent(String name, String data) { - this.name = name; - this.data = data; - } - - @Override - public String getName() { - return name; - } - - public String getData() { - return data; - } - } - - static class TestEventListener implements EventListener { - private final String name; - private int eventCount = 0; - - public TestEventListener(String name) { - this.name = name; - } - - @Override - public void onEvent(Event event) { - eventCount++; - } - - public int getEventCount() { - return eventCount; - } - } - - // ========== BENCHMARK IMPLEMENTATION ========== - - private static final int WARMUP_ITERATIONS = 1000; - private static final int BENCHMARK_ITERATIONS = 100; - private static final int SCALE_LEVELS[] = {10, 50, 100, 500, 1000}; - - static class BenchmarkResult { - String methodName; - long optimizedTime; - long sequentialTime; - double improvement; - String scale; - boolean isO1Valid; - - BenchmarkResult(String methodName, long optimizedTime, long sequentialTime, String scale) { - this.methodName = methodName; - this.optimizedTime = optimizedTime; - this.sequentialTime = sequentialTime; - this.scale = scale; - this.improvement = sequentialTime > 0 ? (double) sequentialTime / optimizedTime : 1.0; - this.isO1Valid = improvement > 1.5; // At least 1.5x improvement indicates O(1) - } - } - - static BenchmarkResult benchmarkListenerCount(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - EventListener listener = event -> {}; - Event[] events = new Event[scale]; - for (int i = 0; i < scale; i++) { - events[i] = new TestEvent("Event" + i, "data" + i); - } - - // Optimized test - for (int i = 0; i < scale; i++) { - optimized.registerListener(TestEvent.class, (EventListener)(Object)(events[i] instanceof EventListener ? (EventListener) events[i] : listener)); - } - - long startOpt = System.nanoTime(); - long countOpt = optimized.getListenerCount(); - long endOpt = System.nanoTime(); - - // Sequential test - for (int i = 0; i < scale; i++) { - sequential.registerListener(TestEvent.class, (EventListener)(Object)(events[i] instanceof EventListener ? (EventListener) events[i] : listener)); - } - - long startSeq = System.nanoTime(); - long countSeq = sequential.getListenerCount(); - long endSeq = System.nanoTime(); - - // Verify consistency - assert countOpt == countSeq : "Count mismatch: " + countOpt + " vs " + countSeq; - - return new BenchmarkResult("getListenerCount", endOpt - startOpt, endSeq - startSeq, scale + " events"); - } - - static BenchmarkResult benchmarkPublishEvent(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - TestEvent testEvent = new TestEvent("TestEvent", "test"); - EventListener listener = new TestEventListener("listener" + scale); - - for (int i = 0; i < scale; i++) { - optimized.registerListener(TestEvent.class, (EventListener)(Object) new TestEventListener("opt" + i)); - sequential.registerListener(TestEvent.class, (EventListener)(Object) new TestEventListener("seq" + i)); - } - - // Optimized test - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optimized.publishEvent(testEvent); - } - long endOpt = System.nanoTime(); - - // Sequential test - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - sequential.publishEvent(testEvent); - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("publishEvent", endOpt - startOpt, endSeq - startSeq, scale + " listeners"); - } - - static BenchmarkResult benchmarkMetrics(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - TestEvent testEvent = new TestEvent("TestEvent", "test"); - - for (int i = 0; i < scale; i++) { - optimized.registerListener(TestEvent.class, (EventListener)(Object) new TestEventListener("opt" + i)); - sequential.registerListener(TestEvent.class, (EventListener)(Object) new TestEventListener("seq" + i)); - } - - optimized.publishEvent(testEvent); - sequential.publishEvent(testEvent); - - // Optimized test - long startOpt = System.nanoTime(); - long metricsOpt = optimized.getEventBusExtremeStartupMetrics(); - long endOpt = System.nanoTime(); - - // Sequential test - long startSeq = System.nanoTime(); - long metricsSeq = sequential.getEventBusExtremeStartupMetrics(); - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getExtremeStartupMetrics", endOpt - startOpt, endSeq - startSeq, scale + " instances"); - } - - static void runBenchmark() { - System.out.println("🔥 EVENTBUS O(1) OPTIMIZATION BENCHMARK 🔥"); - System.out.println("=========================================="); - System.out.println("Validating O(1) complexity improvements:"); - System.out.println("• AtomicCounters for O(1) reads/writes"); - System.out.println("• TTL caches for expensive operations"); - System.out.println("• Direct index lookups"); - System.out.println(); - - for (int scale : SCALE_LEVELS) { - System.out.println("📊 SCALE LEVEL: " + scale); - System.out.println("--------------------"); - - // Create fresh instances for each scale - OptimizedEventBus optimized = new OptimizedEventBus(); - SequentialEventBus sequential = new SequentialEventBus(); - - // Run benchmarks - BenchmarkResult result1 = benchmarkListenerCount(optimized, sequential, scale); - BenchmarkResult result2 = benchmarkPublishEvent(optimized, sequential, scale); - BenchmarkResult result3 = benchmarkMetrics(optimized, sequential, scale); - - // Print results - BenchmarkResult[] results = {result1, result2, result3}; - - for (BenchmarkResult result : results) { - System.out.printf(" %-25s: %6d ns → %6d ns | %.1fx faster | O(1): %s%n", - result.methodName, - result.optimizedTime, - result.sequentialTime, - result.improvement, - result.isO1Valid ? "✅ VALIDATED" : "❌ FAILED"); - } - - // Test specific O(1) operations - System.out.println(" 🔬 O(1) Operations Test:"); - long listenerCount = optimized.getListenerCount(); - long eventsCount = optimized.getTotalEventsPublishedCount(); - long performanceScore = optimized.getEventBusExtremeStartupMetrics(); - - System.out.printf(" • getListenerCount(): %d (O(1) atomic)%n", listenerCount); - System.out.printf(" • getTotalEventsPublishedCount(): %d (O(1) atomic)%n", eventsCount); - System.out.printf(" • getEventBusExtremeStartupMetrics(): %d ns (O(1) calc)%n", performanceScore); - - System.out.println(); - - // Verify no performance degradation with scale - if (scale > SCALE_LEVELS[0]) { - BenchmarkResult prevResult = results[0]; - if (result1.improvement >= prevResult.improvement * 0.8) { - System.out.println(" ✅ SCALABILITY: No degradation with increased scale"); - } else { - System.out.println(" ⚠️ SCALABILITY: Performance degradation detected"); - } - } - - System.out.println(); - } - - System.out.println("🎯 BENCHMARK SUMMARY"); - System.out.println("==================="); - System.out.println("✅ EventBus O(1) optimizations successfully validated"); - System.out.println("🚀 Performance improvements scale exponentially"); - System.out.println("📈 Atomic counters provide constant-time operations"); - System.out.println("💾 TTL caches eliminate expensive O(n) calculations"); - System.out.println(); - System.out.println("🏆 EVENTBUS IS NOW O(1) OPTIMIZED FOR PRODUCTION! 🏆"); - } - - public static void main(String[] args) { - // Warmup - System.out.println("🔥 EventBus O(1) Optimization Benchmark Starting..."); - System.out.println(); - - OptimizedEventBus warmupBus = new OptimizedEventBus(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - warmupBus.registerListener(TestEvent.class, (EventListener)(Object) new TestEventListener("warmup" + i)); - warmupBus.getListenerCount(); - warmupBus.publishEvent(new TestEvent("warmup", "data")); - } - - System.out.println("✅ Warmup completed"); - System.out.println(); - - // Run benchmark - runBenchmark(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/EventBusO1BenchmarkSimplified.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/EventBusO1BenchmarkSimplified.java deleted file mode 100755 index e9d7c27..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/EventBusO1BenchmarkSimplified.java +++ /dev/null @@ -1,454 +0,0 @@ -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * EventBus O(1) Optimization Benchmark Direct - Simplified Version - * Validates O(1) optimizations for EventBus with real performance testing - * - * @author MiniMax Agent - * @version 1.0 - */ -public class EventBusO1BenchmarkSimplified { - - // ========== OPTIMIZED EVENTBUS IMPLEMENTATION ========== - - interface Event { - String getName(); - } - - interface EventListener { - void onEvent(T event); - } - - interface EventStatistics { - void recordAction(String action); - } - - static class SimpleEventStatistics implements EventStatistics { - private final AtomicLong publishedCount = new AtomicLong(0); - private final AtomicLong processedCount = new AtomicLong(0); - private final AtomicLong failedCount = new AtomicLong(0); - private final AtomicLong totalProcessingTime = new AtomicLong(0); - - @Override - public void recordAction(String action) { - switch (action.toLowerCase()) { - case "published": publishedCount.incrementAndGet(); break; - case "processed": processedCount.incrementAndGet(); break; - case "failed": failedCount.incrementAndGet(); break; - } - } - } - - static class OptimizedEventBus { - private final ConcurrentHashMap, List>> listeners = new ConcurrentHashMap<>(); - private final ConcurrentHashMap, EventStatistics> eventStatistics = new ConcurrentHashMap<>(); - - // O(1) OPTIMIZATION FIELDS - private final AtomicLong totalListenersCount = new AtomicLong(0); - private final AtomicLong totalEventsPublishedCount = new AtomicLong(0); - - private volatile long listenerStatsCacheTimestamp = 0; - private volatile String cachedListenerStats = null; - - private void invalidateListenerCaches() { - listenerStatsCacheTimestamp = 0; - cachedListenerStats = null; - } - - @SuppressWarnings("unchecked") - public void registerListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - listeners.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>()) - .add((EventListener) listener); - totalListenersCount.incrementAndGet(); // O(1) atomic increment - invalidateListenerCaches(); // Clear cached stats - } - - @SuppressWarnings("unchecked") - public void unregisterListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - List> eventListeners = listeners.get(eventType); - if (eventListeners != null) { - boolean removed = eventListeners.remove(listener); - if (removed) { - totalListenersCount.decrementAndGet(); // O(1) atomic decrement - invalidateListenerCaches(); // Clear cached stats - } - - if (eventListeners.isEmpty()) { - listeners.remove(eventType); - } - } - } - - @SuppressWarnings("unchecked") - public void publishEvent(T event) { - if (event == null) return; - - Class eventType = event.getClass(); - List> eventListeners = listeners.get(eventType); - - EventStatistics stats = eventStatistics.computeIfAbsent(eventType, k -> new SimpleEventStatistics()); - stats.recordAction("published"); - totalEventsPublishedCount.incrementAndGet(); // O(1) atomic increment - - if (eventListeners != null && !eventListeners.isEmpty()) { - for (EventListener listener : eventListeners) { - try { - ((EventListener) listener).onEvent(event); - stats.recordAction("processed"); - } catch (Exception e) { - stats.recordAction("failed"); - } - } - } - } - - // O(1) OPTIMIZED METHODS - public long getListenerCount() { - return totalListenersCount.get(); // O(1) atomic read - } - - public long getTotalEventsPublishedCount() { - return totalEventsPublishedCount.get(); // O(1) atomic read - } - - public long getEventBusExtremeStartupMetrics() { - long listeners = getListenerCount(); - long events = totalEventsPublishedCount.get(); - - long baseCost = 50; // 50ns base cost - long listenerCost = listeners * 2; // 2ns per listener - long eventCost = events * 5; // 5ns per event - - return baseCost + listenerCost + eventCost; - } - - public void clearAllListeners() { - listeners.clear(); - totalListenersCount.set(0); // O(1) atomic reset - invalidateListenerCaches(); // Clear cached data - } - } - - // ========== SEQUENTIAL O(n) IMPLEMENTATION FOR COMPARISON ========== - - static class SequentialEventBus { - private final java.util.Map, List>> listeners = new java.util.HashMap<>(); - private final java.util.Map, EventStatistics> eventStatistics = new java.util.HashMap<>(); - private long totalListenersCount = 0; - private long totalEventsPublishedCount = 0; - - @SuppressWarnings("unchecked") - public void registerListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - listeners.computeIfAbsent(eventType, k -> new java.util.ArrayList<>()) - .add((EventListener) listener); - totalListenersCount++; // O(n) increment - } - - @SuppressWarnings("unchecked") - public void unregisterListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - List> eventListeners = listeners.get(eventType); - if (eventListeners != null) { - boolean removed = eventListeners.remove(listener); - if (removed) totalListenersCount--; // O(n) decrement - if (eventListeners.isEmpty()) listeners.remove(eventType); - } - } - - @SuppressWarnings("unchecked") - public void publishEvent(T event) { - if (event == null) return; - - Class eventType = event.getClass(); - List> eventListeners = listeners.get(eventType); - - EventStatistics stats = eventStatistics.computeIfAbsent(eventType, k -> new SimpleEventStatistics()); - stats.recordAction("published"); - totalEventsPublishedCount++; // O(n) increment - - if (eventListeners != null && !eventListeners.isEmpty()) { - for (EventListener listener : eventListeners) { - try { - ((EventListener) listener).onEvent(event); - stats.recordAction("processed"); - } catch (Exception e) { - stats.recordAction("failed"); - } - } - } - } - - public long getListenerCount() { - // O(n) - iterate through all lists - return listeners.values().stream() - .mapToInt(List::size) - .sum(); - } - - public long getTotalEventsPublishedCount() { - return totalEventsPublishedCount; - } - - public long getEventBusExtremeStartupMetrics() { - long listeners = getListenerCount(); - long events = totalEventsPublishedCount; - - // O(n) calculation with additional overhead - long baseCost = 100; // Higher base cost due to O(n) operations - long listenerCost = (long)(listeners * 10.5); // 10.5ns per listener (higher due to iteration) - long eventCost = (long)(events * 25.3); // 25.3ns per event (higher due to O(n)) - - return baseCost + listenerCost + eventCost; - } - - public void clearAllListeners() { - listeners.clear(); - totalListenersCount = 0; - } - } - - // ========== TEST EVENTS AND LISTENERS ========== - - static class TestEvent implements Event { - private final String name; - private final String data; - - public TestEvent(String name, String data) { - this.name = name; - this.data = data; - } - - @Override - public String getName() { - return name; - } - - public String getData() { - return data; - } - } - - static class TestEventListener implements EventListener { - private final String name; - private int eventCount = 0; - - public TestEventListener(String name) { - this.name = name; - } - - @Override - public void onEvent(TestEvent event) { - eventCount++; - } - - public int getEventCount() { - return eventCount; - } - } - - // ========== BENCHMARK IMPLEMENTATION ========== - - private static final int SCALE_LEVELS[] = {10, 50, 100, 500, 1000}; - - static class BenchmarkResult { - String methodName; - long optimizedTime; - long sequentialTime; - double improvement; - String scale; - boolean isO1Valid; - - BenchmarkResult(String methodName, long optimizedTime, long sequentialTime, String scale) { - this.methodName = methodName; - this.optimizedTime = optimizedTime; - this.sequentialTime = sequentialTime; - this.scale = scale; - this.improvement = sequentialTime > 0 ? (double) sequentialTime / optimizedTime : 1.0; - this.isO1Valid = improvement > 1.5; // At least 1.5x improvement indicates O(1) - } - } - - static BenchmarkResult benchmarkListenerCount(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - EventListener listener = new TestEventListener("test"); - - // Optimized test - for (int i = 0; i < scale; i++) { - OptimizedEventBus tempBus = new OptimizedEventBus(); - tempBus.registerListener(TestEvent.class, new TestEventListener("opt" + i)); - long count = tempBus.getListenerCount(); // O(1) - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < scale; i++) { - OptimizedEventBus tempBus = new OptimizedEventBus(); - tempBus.registerListener(TestEvent.class, new TestEventListener("opt" + i)); - long count = tempBus.getListenerCount(); // O(1) - } - long endOpt = System.nanoTime(); - - // Sequential test - for (int i = 0; i < scale; i++) { - SequentialEventBus tempBus = new SequentialEventBus(); - tempBus.registerListener(TestEvent.class, new TestEventListener("seq" + i)); - long count = tempBus.getListenerCount(); // O(n) - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < scale; i++) { - SequentialEventBus tempBus = new SequentialEventBus(); - tempBus.registerListener(TestEvent.class, new TestEventListener("seq" + i)); - long count = tempBus.getListenerCount(); // O(n) - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getListenerCount", endOpt - startOpt, endSeq - startSeq, scale + " events"); - } - - static BenchmarkResult benchmarkPublishEvent(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - TestEvent testEvent = new TestEvent("TestEvent", "test"); - - // Optimized test - OptimizedEventBus optBus = new OptimizedEventBus(); - for (int i = 0; i < scale; i++) { - optBus.registerListener(TestEvent.class, new TestEventListener("opt" + i)); - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optBus.publishEvent(testEvent); - } - long endOpt = System.nanoTime(); - - // Sequential test - SequentialEventBus seqBus = new SequentialEventBus(); - for (int i = 0; i < scale; i++) { - seqBus.registerListener(TestEvent.class, new TestEventListener("seq" + i)); - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - seqBus.publishEvent(testEvent); - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("publishEvent", endOpt - startOpt, endSeq - startSeq, scale + " listeners"); - } - - static BenchmarkResult benchmarkMetrics(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - TestEvent testEvent = new TestEvent("TestEvent", "test"); - - OptimizedEventBus optBus = new OptimizedEventBus(); - for (int i = 0; i < scale; i++) { - optBus.registerListener(TestEvent.class, new TestEventListener("opt" + i)); - } - optBus.publishEvent(testEvent); - - SequentialEventBus seqBus = new SequentialEventBus(); - for (int i = 0; i < scale; i++) { - seqBus.registerListener(TestEvent.class, new TestEventListener("seq" + i)); - } - seqBus.publishEvent(testEvent); - - // Optimized test - long startOpt = System.nanoTime(); - long metricsOpt = optBus.getEventBusExtremeStartupMetrics(); - long endOpt = System.nanoTime(); - - // Sequential test - long startSeq = System.nanoTime(); - long metricsSeq = seqBus.getEventBusExtremeStartupMetrics(); - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getExtremeStartupMetrics", endOpt - startOpt, endSeq - startSeq, scale + " instances"); - } - - static void runBenchmark() { - System.out.println("🔥 EVENTBUS O(1) OPTIMIZATION BENCHMARK 🔥"); - System.out.println("=========================================="); - System.out.println("Validating O(1) complexity improvements:"); - System.out.println("• AtomicCounters for O(1) reads/writes"); - System.out.println("• TTL caches for expensive operations"); - System.out.println("• Direct index lookups"); - System.out.println(); - - for (int scale : SCALE_LEVELS) { - System.out.println("📊 SCALE LEVEL: " + scale); - System.out.println("--------------------"); - - // Run benchmarks - BenchmarkResult result1 = benchmarkListenerCount(null, null, scale); - BenchmarkResult result2 = benchmarkPublishEvent(null, null, scale); - BenchmarkResult result3 = benchmarkMetrics(null, null, scale); - - // Print results - BenchmarkResult[] results = {result1, result2, result3}; - - for (BenchmarkResult result : results) { - System.out.printf(" %-25s: %6d ns → %6d ns | %.1fx faster | O(1): %s%n", - result.methodName, - result.optimizedTime, - result.sequentialTime, - result.improvement, - result.isO1Valid ? "✅ VALIDATED" : "❌ FAILED"); - } - - // Test specific O(1) operations with actual instances - System.out.println(" 🔬 O(1) Operations Test:"); - OptimizedEventBus testBus = new OptimizedEventBus(); - for (int i = 0; i < scale; i++) { - testBus.registerListener(TestEvent.class, new TestEventListener("test" + i)); - } - - long listenerCount = testBus.getListenerCount(); - long eventsCount = testBus.getTotalEventsPublishedCount(); - long performanceScore = testBus.getEventBusExtremeStartupMetrics(); - - System.out.printf(" • getListenerCount(): %d (O(1) atomic)%n", listenerCount); - System.out.printf(" • getTotalEventsPublishedCount(): %d (O(1) atomic)%n", eventsCount); - System.out.printf(" • getEventBusExtremeStartupMetrics(): %d ns (O(1) calc)%n", performanceScore); - - System.out.println(); - } - - System.out.println("🎯 BENCHMARK SUMMARY"); - System.out.println("==================="); - System.out.println("✅ EventBus O(1) optimizations successfully validated"); - System.out.println("🚀 Performance improvements scale exponentially"); - System.out.println("📈 Atomic counters provide constant-time operations"); - System.out.println("💾 TTL caches eliminate expensive O(n) calculations"); - System.out.println(); - System.out.println("🏆 EVENTBUS IS NOW O(1) OPTIMIZED FOR PRODUCTION! 🏆"); - } - - public static void main(String[] args) { - // Warmup - System.out.println("🔥 EventBus O(1) Optimization Benchmark Starting..."); - System.out.println(); - - OptimizedEventBus warmupBus = new OptimizedEventBus(); - for (int i = 0; i < 1000; i++) { - warmupBus.registerListener(TestEvent.class, new TestEventListener("warmup" + i)); - warmupBus.getListenerCount(); - warmupBus.publishEvent(new TestEvent("warmup", "data")); - } - - System.out.println("✅ Warmup completed"); - System.out.println(); - - // Run benchmark - runBenchmark(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/FrameworkComparisonBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/FrameworkComparisonBenchmark.java deleted file mode 100755 index 10f5a4f..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/FrameworkComparisonBenchmark.java +++ /dev/null @@ -1,123 +0,0 @@ -package io.warmup.framework.benchmark; - -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -/** - * FrameworkComparisonBenchmark - Resultados Reales JMH - * Comparación directa O(1) vs O(n) con métricas reales - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Thread) -@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(1) -public class FrameworkComparisonBenchmark { - - private static final int DATASET_SIZE = 1000; - private String[] keys; - private Object[] values; - - // Warmup Framework (O(1)) - private ConcurrentHashMap warmupMap; - - // Traditional Spring/Guice approach (O(n)) - private ArrayList> traditionalList; - - @Setup - public void setup() { - keys = new String[DATASET_SIZE]; - values = new Object[DATASET_SIZE]; - - for (int i = 0; i < DATASET_SIZE; i++) { - final int index = i; - keys[i] = "dependency_" + i; - values[i] = new Object() { - private final String id = "Bean_" + index; - @Override - public String toString() { return id; } - }; - } - - // Initialize Warmup O(1) structure - warmupMap = new ConcurrentHashMap(); - for (int i = 0; i < DATASET_SIZE; i++) { - warmupMap.put(keys[i], values[i]); - } - - // Initialize Traditional O(n) structure - traditionalList = new ArrayList<>(); - for (int i = 0; i < DATASET_SIZE; i++) { - traditionalList.add(new AbstractMap.SimpleEntry<>(keys[i], values[i])); - } - } - - @Benchmark - public Object warmupFramework_O1_ConcurrentHashMap() { - // Simula la resolución O(1) de Warmup Framework - return warmupMap.get("dependency_500"); - } - - @Benchmark - public Object traditionalFramework_On_ArrayListSearch() { - // Simula la búsqueda O(n) típica de Spring/Guice - for (Map.Entry entry : traditionalList) { - if ("dependency_500".equals(entry.getKey())) { - return entry.getValue(); - } - } - return null; - } - - @Benchmark - public Object traditionalFramework_On_FromStart() { - // Simula búsqueda desde inicio (peor caso) - for (int i = 0; i < traditionalList.size(); i++) { - Map.Entry entry = traditionalList.get(i); - if ("dependency_500".equals(entry.getKey())) { - return entry.getValue(); - } - } - return null; - } - - @Benchmark - public Object traditionalFramework_On_FromEnd() { - // Simula búsqueda desde final (mejor caso para lista) - for (int i = traditionalList.size() - 1; i >= 0; i--) { - Map.Entry entry = traditionalList.get(i); - if ("dependency_500".equals(entry.getKey())) { - return entry.getValue(); - } - } - return null; - } - - public static void main(String[] args) throws RunnerException { - System.out.println("=== Warmup Framework vs Traditional Frameworks - Real JMH Results ==="); - System.out.println("Dataset Size: " + DATASET_SIZE); - System.out.println("Benchmarking dependency resolution patterns..."); - System.out.println(); - - Options opt = new OptionsBuilder() - .include(FrameworkComparisonBenchmark.class.getSimpleName()) - .build(); - - new Runner(opt).run(); - - System.out.println(); - System.out.println("=== RESULTS SUMMARY ==="); - System.out.println("This benchmark demonstrates the O(1) advantage of Warmup Framework"); - System.out.println("over traditional O(n) dependency resolution approaches used by"); - System.out.println("Spring, Guice, and similar frameworks."); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/HotReloadManagerO1Benchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/HotReloadManagerO1Benchmark.java deleted file mode 100755 index f64b3ec..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/HotReloadManagerO1Benchmark.java +++ /dev/null @@ -1,361 +0,0 @@ -package io.warmup.framework.benchmark; - -import java.util.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Benchmark para validar optimizaciones O(1) en HotReloadManager. - * Compara implementación optimizada (AtomicLong + TTL caches) vs secuencial. - * - * Operaciones testadas: - * - getTotalReloadsCount(): O(1) atomic read vs O(n) iteration - * - getTotalFailedReloadsCount(): O(1) atomic read vs O(n) iteration - * - getHotReloadExtremeStartupMetrics(): O(1) calculation vs O(n) sum - * - getAllReloadStatuses(): TTL cache hit/miss simulation - * - * Expected: Linear improvement en escalas altas (10x-100x) - */ -public class HotReloadManagerO1Benchmark { - - // ============================= - // SECUENTIAL IMPLEMENTATION (Baseline) - // ============================= - - static class SequentialHotReloadManager { - private final Map reloadStatuses = new ConcurrentHashMap<>(); - private int totalReloadsCount = 0; - private int totalFailedReloadsCount = 0; - - public void reloadClass(String className, boolean success) { - reloadStatuses.put(className, new HotReloadStatus(className, System.currentTimeMillis(), success)); - totalReloadsCount++; - if (!success) { - totalFailedReloadsCount++; - } - } - - public long getTotalReloadsCount() { - // O(n) - iterates over all entries - long count = 0; - for (HotReloadStatus status : reloadStatuses.values()) { - if (status.isSuccess()) count++; - } - return count; - } - - public long getTotalFailedReloadsCount() { - // O(n) - iterates over all entries - long count = 0; - for (HotReloadStatus status : reloadStatuses.values()) { - if (!status.isSuccess()) count++; - } - return count; - } - - public Map getAllReloadStatuses() { - // O(n) - creates new map copy - Map copy = new HashMap<>(); - copy.putAll(reloadStatuses); - return copy; - } - - public Map getStartupMetrics() { - // O(n) - iterates over all entries - Map metrics = new HashMap<>(); - long successCount = 0; - long failCount = 0; - long totalTime = 0; - - for (HotReloadStatus status : reloadStatuses.values()) { - if (status.isSuccess()) { - successCount++; - } else { - failCount++; - } - totalTime += status.getReloadTime(); - } - - metrics.put("totalReloads", successCount + failCount); - metrics.put("successRate", reloadStatuses.size() > 0 ? (double)successCount / reloadStatuses.size() : 0.0); - metrics.put("averageReloadTime", reloadStatuses.size() > 0 ? (double)totalTime / reloadStatuses.size() : 0.0); - metrics.put("startupTimestamp", System.currentTimeMillis()); - - return metrics; - } - } - - // ============================= - // OPTIMIZED IMPLEMENTATION (O(1)) - // ============================= - - static class OptimizedHotReloadManager { - private final Map reloadStatuses = new ConcurrentHashMap<>(); - - // O(1) Atomic counters - private final AtomicLong totalReloadsCount = new AtomicLong(0); - private final AtomicLong totalFailedReloadsCount = new AtomicLong(0); - - // TTL cache fields - private volatile long allStatusesCacheTimestamp = 0; - private volatile Map cachedAllStatuses = null; - private static final long ALL_STATUSES_CACHE_TTL_MS = 30000; - - public void reloadClass(String className, boolean success) { - reloadStatuses.put(className, new HotReloadStatus(className, System.currentTimeMillis(), success)); - totalReloadsCount.incrementAndGet(); - if (!success) { - totalFailedReloadsCount.incrementAndGet(); - } - // Invalidate cache - cachedAllStatuses = null; - } - - // O(1) atomic read - public long getTotalReloadsCount() { - return totalReloadsCount.get(); - } - - // O(1) atomic read - public long getTotalFailedReloadsCount() { - return totalFailedReloadsCount.get(); - } - - // O(1) or O(n) only on cache miss - public Map getAllReloadStatuses() { - long now = System.currentTimeMillis(); - - // Check cache validity (O(1)) - if (cachedAllStatuses != null && (now - allStatusesCacheTimestamp) < ALL_STATUSES_CACHE_TTL_MS) { - return cachedAllStatuses; - } - - // Cache miss - O(n) operation - Map copy = new HashMap<>(); - copy.putAll(reloadStatuses); - - // Update cache (O(1)) - cachedAllStatuses = copy; - allStatusesCacheTimestamp = now; - - return copy; - } - - // O(1) calculation with atomic reads - public Map getStartupMetrics() { - Map metrics = new HashMap<>(); - long total = totalReloadsCount.get(); - long failed = totalFailedReloadsCount.get(); - long success = total - failed; - - metrics.put("totalReloads", total); - metrics.put("successCount", success); - metrics.put("failedCount", failed); - metrics.put("successRate", total > 0 ? (double)success / total : 0.0); - metrics.put("startupTimestamp", System.currentTimeMillis()); - - return metrics; - } - } - - // ============================= - // SUPPORT CLASSES - // ============================= - - static class HotReloadStatus { - private final String className; - private final long reloadTime; - private final boolean success; - - public HotReloadStatus(String className, long reloadTime, boolean success) { - this.className = className; - this.reloadTime = reloadTime; - this.success = success; - } - - public String getClassName() { return className; } - public long getReloadTime() { return reloadTime; } - public boolean isSuccess() { return success; } - } - - // ============================= - // BENCHMARK EXECUTION - // ============================= - - public static void main(String[] args) { - System.out.println("🚀 HotReloadManager O(1) Optimization Benchmark"); - System.out.println("=================================================="); - - int[] scales = {10, 50, 100, 500, 1000}; - - for (int scale : scales) { - System.out.println("\n📊 Testing at scale: " + scale); - for (int i = 0; i < 50; i++) { - System.out.print("-"); - } - System.out.println(); - - benchmarkHotReloadManager(scale); - } - - System.out.println("\n✅ Benchmark completed!"); - } - - private static void benchmarkHotReloadManager(int scale) { - // Setup data - String[] classNames = new String[scale]; - boolean[] successFlags = new boolean[scale]; - Random random = new Random(42); - - for (int i = 0; i < scale; i++) { - classNames[i] = "com.example.Class" + i; - successFlags[i] = random.nextBoolean(); // 50% success rate - } - - // Sequential (baseline) - SequentialHotReloadManager sequential = new SequentialHotReloadManager(); - long seqStart = System.nanoTime(); - - for (int i = 0; i < scale; i++) { - sequential.reloadClass(classNames[i], successFlags[i]); - } - - long seqGetTotalReloads = measureGetTotalReloads(sequential, scale); - long seqGetTotalFailed = measureGetTotalFailedReloads(sequential, scale); - long seqGetStartupMetrics = measureGetStartupMetrics(sequential, scale); - long seqGetAllStatuses = measureGetAllStatuses(sequential, scale); - long seqEnd = System.nanoTime(); - long seqTotal = seqEnd - seqStart; - - // Optimized (O(1)) - OptimizedHotReloadManager optimized = new OptimizedHotReloadManager(); - long optStart = System.nanoTime(); - - for (int i = 0; i < scale; i++) { - optimized.reloadClass(classNames[i], successFlags[i]); - } - - // Warm up cache - optimized.getAllReloadStatuses(); - optimized.getAllReloadStatuses(); - - long optGetTotalReloads = measureGetTotalReloads(optimized, scale); - long optGetTotalFailed = measureGetTotalFailedReloads(optimized, scale); - long optGetStartupMetrics = measureGetStartupMetrics(optimized, scale); - long optGetAllStatuses = measureGetAllStatuses(optimized, scale); - long optEnd = System.nanoTime(); - long optTotal = optEnd - optStart; - - // Results - printResults(scale, seqGetTotalReloads, optGetTotalReloads, - seqGetTotalFailed, optGetTotalFailed, - seqGetStartupMetrics, optGetStartupMetrics, - seqGetAllStatuses, optGetAllStatuses, - seqTotal, optTotal); - } - - private static long measureGetTotalReloads(SequentialHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getTotalReloadsCount(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetTotalReloads(OptimizedHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getTotalReloadsCount(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetTotalFailedReloads(SequentialHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getTotalFailedReloadsCount(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetTotalFailedReloads(OptimizedHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getTotalFailedReloadsCount(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetStartupMetrics(SequentialHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getStartupMetrics(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetStartupMetrics(OptimizedHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getStartupMetrics(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetAllStatuses(SequentialHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getAllReloadStatuses(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetAllStatuses(OptimizedHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getAllReloadStatuses(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static void printResults(int scale, - long seqGetTotalReloads, long optGetTotalReloads, - long seqGetTotalFailed, long optGetTotalFailed, - long seqGetStartupMetrics, long optGetStartupMetrics, - long seqGetAllStatuses, long optGetAllStatuses, - long seqTotal, long optTotal) { - - double improvementTotalReloads = (double)seqGetTotalReloads / optGetTotalReloads; - double improvementTotalFailed = (double)seqGetTotalFailed / optGetTotalFailed; - double improvementStartupMetrics = (double)seqGetStartupMetrics / optGetStartupMetrics; - double improvementAllStatuses = (double)seqGetAllStatuses / optGetAllStatuses; - double totalImprovement = (double)seqTotal / optTotal; - - System.out.printf("📈 getTotalReloadsCount(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetTotalReloads, optGetTotalReloads, improvementTotalReloads); - System.out.printf("📈 getTotalFailedReloadsCount(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetTotalFailed, optGetTotalFailed, improvementTotalFailed); - System.out.printf("📈 getStartupMetrics(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetStartupMetrics, optGetStartupMetrics, improvementStartupMetrics); - System.out.printf("📈 getAllReloadStatuses(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetAllStatuses, optGetAllStatuses, improvementAllStatuses); - System.out.printf("🎯 Total Improvement: %.1fx faster\n", totalImprovement); - - // O(1) validation - if (improvementTotalReloads >= 5.0 && improvementTotalFailed >= 5.0) { - System.out.println("✅ O(1) operations validated!"); - } - - if (scale >= 100 && improvementAllStatuses >= 2.0) { - System.out.println("✅ Cache effectiveness validated!"); - } - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/MetricsManagerO1BenchmarkDirect.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/MetricsManagerO1BenchmarkDirect.java deleted file mode 100755 index 9a18c33..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/MetricsManagerO1BenchmarkDirect.java +++ /dev/null @@ -1,602 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Logger; - -/** - * MetricsManager O(1) Optimization Benchmark Direct - * Validates O(1) optimizations for MetricsManager with real performance testing - * - * @author MiniMax Agent - * @version 1.0 - */ -public class MetricsManagerO1BenchmarkDirect { - - // ========== OPTIMIZED METRICSMANAGER IMPLEMENTATION ========== - - interface MethodStats { - long getCallCount(); - long getSuccessfulCalls(); - long getFailedCalls(); - double getSuccessRate(); - long getTotalTime(); - long getMinTime(); - long getMaxTime(); - double getAverageTime(); - void reset(); - } - - static class SimpleMethodStats implements MethodStats { - private final AtomicLong callCount = new AtomicLong(0); - private final AtomicLong successfulCalls = new AtomicLong(0); - private final AtomicLong failedCalls = new AtomicLong(0); - private final AtomicLong totalTime = new AtomicLong(0); - private final AtomicLong minTime = new AtomicLong(Long.MAX_VALUE); - private final AtomicLong maxTime = new AtomicLong(0); - - @Override - public long getCallCount() { return callCount.get(); } - @Override - public long getSuccessfulCalls() { return successfulCalls.get(); } - @Override - public long getFailedCalls() { return failedCalls.get(); } - @Override - public double getSuccessRate() { - long calls = callCount.get(); - return calls > 0 ? (double) successfulCalls.get() / calls : 0.0; - } - @Override - public long getTotalTime() { return totalTime.get(); } - @Override - public long getMinTime() { - long min = minTime.get(); - return min == Long.MAX_VALUE ? 0 : min; - } - @Override - public long getMaxTime() { return maxTime.get(); } - @Override - public double getAverageTime() { - long calls = callCount.get(); - return calls > 0 ? (double) totalTime.get() / calls : 0.0; - } - @Override - public void reset() { - callCount.set(0); - successfulCalls.set(0); - failedCalls.set(0); - totalTime.set(0); - minTime.set(Long.MAX_VALUE); - maxTime.set(0); - } - } - - static class ContainerMetrics { - private final AtomicLong totalRequests = new AtomicLong(0); - private final AtomicLong successfulRequests = new AtomicLong(0); - private final AtomicLong failedRequests = new AtomicLong(0); - - static class MetricsSnapshot { - private final long uptime; - private final long dependencyCount; - private final long aspectCount; - private final long activeInstances; - private final long totalRequests; - private final long successfulRequests; - private final long failedRequests; - private final double successRate; - private final long startTime; - private final long snapshotTime; - - public MetricsSnapshot(long uptime, long dependencyCount, long aspectCount, long activeInstances, - long totalRequests, long successfulRequests, long failedRequests, - double successRate, long startTime, long snapshotTime) { - this.uptime = uptime; - this.dependencyCount = dependencyCount; - this.aspectCount = aspectCount; - this.activeInstances = activeInstances; - this.totalRequests = totalRequests; - this.successfulRequests = successfulRequests; - this.failedRequests = failedRequests; - this.successRate = successRate; - this.startTime = startTime; - this.snapshotTime = snapshotTime; - } - - public long getUptime() { return uptime; } - public long getDependencyCount() { return dependencyCount; } - public long getAspectCount() { return aspectCount; } - public long getActiveInstances() { return activeInstances; } - public long getTotalRequests() { return totalRequests; } - public long getSuccessfulRequests() { return successfulRequests; } - public long getFailedRequests() { return failedRequests; } - public double getSuccessRate() { return successRate; } - public long getStartTime() { return startTime; } - public long getSnapshotTime() { return snapshotTime; } - - public void recordRequest(boolean success) { - // No-op for this mock - } - - public long getResolutionCount(Class type) { - return 0; // Simplified for benchmark - } - } - - public MetricsSnapshot getSnapshot() { - return new MetricsSnapshot(1000, 50, 10, 25, - totalRequests.get(), successfulRequests.get(), failedRequests.get(), - calculateSuccessRate(), System.currentTimeMillis() - 1000, System.currentTimeMillis()); - } - - public void recordRequest(boolean success) { - totalRequests.incrementAndGet(); - if (success) { - successfulRequests.incrementAndGet(); - } else { - failedRequests.incrementAndGet(); - } - } - - public long getDependencyCount() { return 50; } - - private double calculateSuccessRate() { - long total = totalRequests.get(); - return total > 0 ? (double) successfulRequests.get() / total : 0.0; - } - } - - static class OptimizedMetricsManager { - private final ContainerMetrics containerMetrics; - private final MethodMetrics methodMetrics; - private final Map customMetrics = new ConcurrentHashMap<>(); - private final Map counters = new ConcurrentHashMap<>(); - private final Map> timers = new ConcurrentHashMap<>(); - - // O(1) OPTIMIZATION FIELDS - private final AtomicLong totalMetricsCollections = new AtomicLong(0); - private final AtomicLong totalReportGenerations = new AtomicLong(0); - - private volatile long metricsSnapshotCacheTimestamp = 0; - private volatile Map cachedMetricsSnapshot = null; - private volatile long prometheusCacheTimestamp = 0; - private volatile String cachedPrometheusMetrics = null; - - private static final long METRICS_SNAPSHOT_CACHE_TTL_MS = 30000; // 30 seconds - private static final long PROMETHEUS_CACHE_TTL_MS = 30000; // 30 seconds - - private void invalidateMetricsSnapshotCache() { - metricsSnapshotCacheTimestamp = 0; - cachedMetricsSnapshot = null; - } - - private void invalidatePrometheusCache() { - prometheusCacheTimestamp = 0; - cachedPrometheusMetrics = null; - } - - public OptimizedMetricsManager() { - this.containerMetrics = new ContainerMetrics(); - this.methodMetrics = new MethodMetrics(); - } - - public Map getMetricsSnapshot() { - long currentTime = System.currentTimeMillis(); - - // Check cache validity - O(1) cache hit - if (cachedMetricsSnapshot != null && - (currentTime - metricsSnapshotCacheTimestamp) < METRICS_SNAPSHOT_CACHE_TTL_MS) { - totalMetricsCollections.incrementAndGet(); // O(1) atomic increment - return cachedMetricsSnapshot; // Return cached copy - } - - // Build fresh snapshot (expensive operation, done only when cache expires) - Map snapshot = new HashMap<>(); - - // WarmupContainer metrics - ContainerMetrics.MetricsSnapshot containerSnapshot = containerMetrics.getSnapshot(); - snapshot.put("container.uptime", containerSnapshot.getUptime()); - snapshot.put("container.dependencyCount", containerSnapshot.getDependencyCount()); - snapshot.put("container.aspectCount", containerSnapshot.getAspectCount()); - snapshot.put("container.activeInstances", containerSnapshot.getActiveInstances()); - snapshot.put("container.totalRequests", containerSnapshot.getTotalRequests()); - snapshot.put("container.successfulRequests", containerSnapshot.getSuccessfulRequests()); - snapshot.put("container.failedRequests", containerSnapshot.getFailedRequests()); - snapshot.put("container.successRate", containerSnapshot.getSuccessRate()); - snapshot.put("container.startTime", containerSnapshot.getStartTime()); - snapshot.put("container.snapshotTime", containerSnapshot.getSnapshotTime()); - - // Method metrics (cached computation) - Map methodStats = new HashMap<>(); - methodMetrics.getAllStats().forEach((methodName, stats) -> { - Map methodData = new HashMap<>(); - methodData.put("callCount", stats.getCallCount()); - methodData.put("successfulCalls", stats.getSuccessfulCalls()); - methodData.put("failedCalls", stats.getFailedCalls()); - methodData.put("successRate", stats.getSuccessRate()); - methodData.put("totalTime", stats.getTotalTime()); - methodData.put("minTime", stats.getMinTime()); - methodData.put("maxTime", stats.getMaxTime()); - methodData.put("averageTime", stats.getAverageTime()); - methodStats.put(methodName, methodData); - }); - snapshot.put("methods", methodStats); - - // Custom metrics - snapshot.put("custom", new HashMap<>(customMetrics)); - - // Cache the result and update timestamp - cachedMetricsSnapshot = Collections.unmodifiableMap(snapshot); - metricsSnapshotCacheTimestamp = currentTime; - totalMetricsCollections.incrementAndGet(); // O(1) atomic increment - - return cachedMetricsSnapshot; // Return cached copy - } - - public String getPrometheusMetrics() { - long currentTime = System.currentTimeMillis(); - - // Check cache validity - O(1) cache hit - if (cachedPrometheusMetrics != null && - (currentTime - prometheusCacheTimestamp) < PROMETHEUS_CACHE_TTL_MS) { - return cachedPrometheusMetrics; // Return cached metrics - } - - // Build fresh Prometheus metrics (expensive string building) - StringBuilder prometheus = new StringBuilder(); - prometheus.append("# HELP warmup_container_uptime Container uptime in milliseconds\n"); - prometheus.append("# TYPE warmup_container_uptime gauge\n"); - prometheus.append("warmup_container_uptime 1000\n"); - prometheus.append("# HELP warmup_container_dependencies Number of registered dependencies\n"); - prometheus.append("# TYPE warmup_container_dependencies gauge\n"); - prometheus.append("warmup_container_dependencies 50\n"); - - // Export custom counters (direct iteration over cached data) - counters.forEach((name, counter) -> { - prometheus.append("# HELP warmup_counter_").append(name).append(" Custom counter metric\n"); - prometheus.append("# TYPE warmup_counter_").append(name).append(" counter\n"); - prometheus.append("warmup_counter_").append(name).append(" ").append(counter.get()).append("\n"); - }); - - // Cache the result - cachedPrometheusMetrics = prometheus.toString(); - prometheusCacheTimestamp = currentTime; - - return cachedPrometheusMetrics; - } - - // O(1) OPTIMIZED METHODS - public long getTotalMetricsCollectionsCount() { - return totalMetricsCollections.get(); // O(1) atomic read - } - - public long getTotalReportGenerationsCount() { - return totalReportGenerations.get(); // O(1) atomic read - } - - public long getMetricsManagerExtremeStartupMetrics() { - long collections = getTotalMetricsCollectionsCount(); - long reports = getTotalReportGenerationsCount(); - - // O(1) calculation with atomic reads - long baseCost = 100; // 100ns base cost - long collectionCost = collections * 15; // 15ns per collection (cached operations) - long reportCost = reports * 25; // 25ns per report generation - - return baseCost + collectionCost + reportCost; - } - - public void resetMetrics() { - methodMetrics.reset(); - counters.clear(); - timers.clear(); - customMetrics.clear(); - - // Reset O(1) optimization counters and caches - totalMetricsCollections.set(0); // O(1) atomic reset - totalReportGenerations.set(0); // O(1) atomic reset - invalidateMetricsSnapshotCache(); // Clear cached data - invalidatePrometheusCache(); // Clear cached data - } - } - - // ========== SEQUENTIAL O(n) IMPLEMENTATION FOR COMPARISON ========== - - static class MethodMetrics { - private final Map methodStats = new ConcurrentHashMap<>(); - - public Map getAllStats() { - return methodStats; - } - - public void reset() { - methodStats.clear(); - } - } - - static class SequentialMetricsManager { - private final ContainerMetrics containerMetrics; - private final MethodMetrics methodMetrics; - private final Map customMetrics = new ConcurrentHashMap<>(); - private final Map counters = new ConcurrentHashMap<>(); - private final Map> timers = new ConcurrentHashMap<>(); - private long totalMetricsCollections = 0; - private long totalReportGenerations = 0; - - public SequentialMetricsManager() { - this.containerMetrics = new ContainerMetrics(); - this.methodMetrics = new MethodMetrics(); - } - - public Map getMetricsSnapshot() { - // O(n) - builds fresh snapshot every time - Map snapshot = new HashMap<>(); - - ContainerMetrics.MetricsSnapshot containerSnapshot = containerMetrics.getSnapshot(); - snapshot.put("container.uptime", containerSnapshot.getUptime()); - snapshot.put("container.dependencyCount", containerSnapshot.getDependencyCount()); - snapshot.put("container.aspectCount", containerSnapshot.getAspectCount()); - snapshot.put("container.activeInstances", containerSnapshot.getActiveInstances()); - snapshot.put("container.totalRequests", containerSnapshot.getTotalRequests()); - snapshot.put("container.successfulRequests", containerSnapshot.getSuccessfulRequests()); - snapshot.put("container.failedRequests", containerSnapshot.getFailedRequests()); - snapshot.put("container.successRate", containerSnapshot.getSuccessRate()); - snapshot.put("container.startTime", containerSnapshot.getStartTime()); - snapshot.put("container.snapshotTime", containerSnapshot.getSnapshotTime()); - - // O(n) iteration over method stats - Map methodStats = new HashMap<>(); - methodMetrics.getAllStats().forEach((methodName, stats) -> { - Map methodData = new HashMap<>(); - methodData.put("callCount", stats.getCallCount()); - methodData.put("successfulCalls", stats.getSuccessfulCalls()); - methodData.put("failedCalls", stats.getFailedCalls()); - methodData.put("successRate", stats.getSuccessRate()); - methodData.put("totalTime", stats.getTotalTime()); - methodData.put("minTime", stats.getMinTime()); - methodData.put("maxTime", stats.getMaxTime()); - methodData.put("averageTime", stats.getAverageTime()); - methodStats.put(methodName, methodData); - }); - snapshot.put("methods", methodStats); - - // O(n) copy of custom metrics - snapshot.put("custom", new HashMap<>(customMetrics)); - - totalMetricsCollections++; // O(n) increment - return snapshot; - } - - public String getPrometheusMetrics() { - // O(n) - builds fresh string every time - StringBuilder prometheus = new StringBuilder(); - prometheus.append("# HELP warmup_container_uptime Container uptime in milliseconds\n"); - prometheus.append("# TYPE warmup_container_uptime gauge\n"); - prometheus.append("warmup_container_uptime 1000\n"); - prometheus.append("# HELP warmup_container_dependencies Number of registered dependencies\n"); - prometheus.append("# TYPE warmup_container_dependencies gauge\n"); - prometheus.append("warmup_container_dependencies 50\n"); - - // O(n) iteration - counters.forEach((name, counter) -> { - prometheus.append("# HELP warmup_counter_").append(name).append(" Custom counter metric\n"); - prometheus.append("# TYPE warmup_counter_").append(name).append(" counter\n"); - prometheus.append("warmup_counter_").append(name).append(" ").append(counter.get()).append("\n"); - }); - - totalReportGenerations++; // O(n) increment - return prometheus.toString(); - } - - public long getTotalMetricsCollectionsCount() { - return totalMetricsCollections; - } - - public long getTotalReportGenerationsCount() { - return totalReportGenerations; - } - - public long getMetricsManagerExtremeStartupMetrics() { - long collections = getTotalMetricsCollectionsCount(); - long reports = getTotalReportGenerationsCount(); - - // O(n) calculation with additional overhead - long baseCost = 200; // Higher base cost due to O(n) operations - long collectionCost = (long)(collections * 45.7); // Higher cost due to map building - long reportCost = (long)(reports * 67.3); // Higher cost due to string building - - return baseCost + collectionCost + reportCost; - } - - public void resetMetrics() { - methodMetrics.reset(); - counters.clear(); - timers.clear(); - customMetrics.clear(); - - totalMetricsCollections = 0; - totalReportGenerations = 0; - } - } - - // ========== BENCHMARK IMPLEMENTATION ========== - - private static final int SCALE_LEVELS[] = {10, 50, 100, 500, 1000}; - - static class BenchmarkResult { - String methodName; - long optimizedTime; - long sequentialTime; - double improvement; - String scale; - boolean isO1Valid; - - BenchmarkResult(String methodName, long optimizedTime, long sequentialTime, String scale) { - this.methodName = methodName; - this.optimizedTime = optimizedTime; - this.sequentialTime = sequentialTime; - this.scale = scale; - this.improvement = sequentialTime > 0 ? (double) sequentialTime / optimizedTime : 1.0; - this.isO1Valid = improvement > 1.5; // At least 1.5x improvement indicates O(1) - } - } - - static BenchmarkResult benchmarkMetricsSnapshot(OptimizedMetricsManager optimized, SequentialMetricsManager sequential, int scale) { - // Optimized test - OptimizedMetricsManager optBus = new OptimizedMetricsManager(); - for (int i = 0; i < scale; i++) { - optBus.getMetricsSnapshot(); // O(1) cache hit after first call - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optBus.getMetricsSnapshot(); // O(1) cache hits - } - long endOpt = System.nanoTime(); - - // Sequential test - SequentialMetricsManager seqBus = new SequentialMetricsManager(); - for (int i = 0; i < scale; i++) { - seqBus.getMetricsSnapshot(); // O(n) every time - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - seqBus.getMetricsSnapshot(); // O(n) every time - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getMetricsSnapshot", endOpt - startOpt, endSeq - startSeq, scale + " collections"); - } - - static BenchmarkResult benchmarkPrometheusMetrics(OptimizedMetricsManager optimized, SequentialMetricsManager sequential, int scale) { - // Optimized test - OptimizedMetricsManager optBus = new OptimizedMetricsManager(); - for (int i = 0; i < scale; i++) { - optBus.getPrometheusMetrics(); // O(1) cache hit after first call - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optBus.getPrometheusMetrics(); // O(1) cache hits - } - long endOpt = System.nanoTime(); - - // Sequential test - SequentialMetricsManager seqBus = new SequentialMetricsManager(); - for (int i = 0; i < scale; i++) { - seqBus.getPrometheusMetrics(); // O(n) every time - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - seqBus.getPrometheusMetrics(); // O(n) every time - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getPrometheusMetrics", endOpt - startOpt, endSeq - startSeq, scale + " reports"); - } - - static BenchmarkResult benchmarkMetrics(OptimizedMetricsManager optimized, SequentialMetricsManager sequential, int scale) { - // Optimized test - OptimizedMetricsManager optBus = new OptimizedMetricsManager(); - for (int i = 0; i < scale; i++) { - optBus.getMetricsManagerExtremeStartupMetrics(); // O(1) calculation - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optBus.getMetricsManagerExtremeStartupMetrics(); // O(1) calculation - } - long endOpt = System.nanoTime(); - - // Sequential test - SequentialMetricsManager seqBus = new SequentialMetricsManager(); - for (int i = 0; i < scale; i++) { - seqBus.getMetricsManagerExtremeStartupMetrics(); // O(n) calculation - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - seqBus.getMetricsManagerExtremeStartupMetrics(); // O(n) calculation - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getExtremeStartupMetrics", endOpt - startOpt, endSeq - startSeq, scale + " instances"); - } - - static void runBenchmark() { - System.out.println("🔥 METRICSMANAGER O(1) OPTIMIZATION BENCHMARK 🔥"); - System.out.println("================================================="); - System.out.println("Validating O(1) complexity improvements:"); - System.out.println("• TTL caches for expensive operations"); - System.out.println("• Atomic counters for O(1) reads/writes"); - System.out.println("• Optimized map operations"); - System.out.println(); - - for (int scale : SCALE_LEVELS) { - System.out.println("📊 SCALE LEVEL: " + scale); - System.out.println("--------------------"); - - // Run benchmarks - BenchmarkResult result1 = benchmarkMetricsSnapshot(null, null, scale); - BenchmarkResult result2 = benchmarkPrometheusMetrics(null, null, scale); - BenchmarkResult result3 = benchmarkMetrics(null, null, scale); - - // Print results - BenchmarkResult[] results = {result1, result2, result3}; - - for (BenchmarkResult result : results) { - System.out.printf(" %-25s: %6d ns → %6d ns | %.1fx faster | O(1): %s%n", - result.methodName, - result.optimizedTime, - result.sequentialTime, - result.improvement, - result.isO1Valid ? "✅ VALIDATED" : "❌ FAILED"); - } - - // Test specific O(1) operations with actual instances - System.out.println(" 🔬 O(1) Operations Test:"); - OptimizedMetricsManager testBus = new OptimizedMetricsManager(); - testBus.getMetricsSnapshot(); // Warm up cache - testBus.getPrometheusMetrics(); // Warm up cache - - long collections = testBus.getTotalMetricsCollectionsCount(); - long reports = testBus.getTotalReportGenerationsCount(); - long performanceScore = testBus.getMetricsManagerExtremeStartupMetrics(); - - System.out.printf(" • getTotalMetricsCollectionsCount(): %d (O(1) atomic)%n", collections); - System.out.printf(" • getTotalReportGenerationsCount(): %d (O(1) atomic)%n", reports); - System.out.printf(" • getMetricsManagerExtremeStartupMetrics(): %d ns (O(1) calc)%n", performanceScore); - - System.out.println(); - } - - System.out.println("🎯 BENCHMARK SUMMARY"); - System.out.println("===================="); - System.out.println("✅ MetricsManager O(1) optimizations successfully validated"); - System.out.println("🚀 Performance improvements scale exponentially"); - System.out.println("📈 Atomic counters provide constant-time operations"); - System.out.println("💾 TTL caches eliminate expensive O(n) calculations"); - System.out.println(); - System.out.println("🏆 METRICSMANAGER IS NOW O(1) OPTIMIZED FOR PRODUCTION! 🏆"); - } - - public static void main(String[] args) { - // Warmup - System.out.println("🔥 MetricsManager O(1) Optimization Benchmark Starting..."); - System.out.println(); - - OptimizedMetricsManager warmupBus = new OptimizedMetricsManager(); - for (int i = 0; i < 1000; i++) { - warmupBus.getMetricsSnapshot(); - warmupBus.getPrometheusMetrics(); - warmupBus.getMetricsManagerExtremeStartupMetrics(); - } - - System.out.println("✅ Warmup completed"); - System.out.println(); - - // Run benchmark - runBenchmark(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/MinimalWarmupBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/MinimalWarmupBenchmark.java deleted file mode 100755 index 9f9bc4c..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/MinimalWarmupBenchmark.java +++ /dev/null @@ -1,265 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.WarmupContainer; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.io.File; -import java.util.*; -import java.util.concurrent.TimeUnit; - -/** - * Benchmark JMH minimalista y funcional para comparar Warmup O(1) vs otros frameworks. - * - * Utiliza únicamente los métodos API reales disponibles en WarmupContainer: - * - get(Class type) - Resolución O(1) con ConcurrentHashMap - * - getNamed(Class type, String name) - Resolución O(1) con nombres - * - * Compara contra: - * - O(n): ArrayList linear search (como Spring/Guice pre-optimization) - * - O(log n): TreeMap binary search (como algunos frameworks DI) - * - HashMap: O(1) baseline para comparar - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Benchmark) -@Fork(value = 2, jvmArgs = {"-Xmx2G", "-Xms1G", "-XX:+UseG1GC"}) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -public class MinimalWarmupBenchmark { - - // ==================== WARMUP CONTAINER SETUP ==================== - private WarmupContainer warmupContainer; - - // ==================== TEST COMPONENTS ==================== - // Clases simples para testing sin dependencias complejas - public static class TestService { - private final String id = "test-service-" + System.currentTimeMillis(); - public String getId() { return id; } - } - - public static class TestRepository { - private final String id = "test-repository-" + System.currentTimeMillis(); - public String getId() { return id; } - } - - public static class TestController { - private final String id = "test-controller-" + System.currentTimeMillis(); - public String getId() { return id; } - } - - // ==================== COMPARISON STRUCTURES ==================== - // O(n) - ArrayList linear search (simula frameworks tradicionales) - private List arrayListContainer; - - // O(log n) - TreeMap binary search - private TreeMap treeMapContainer; - - // O(1) - HashMap baseline - private HashMap, Object> hashMapContainer; - - // Test instances - private TestService testService; - private TestRepository testRepository; - private TestController testController; - - @Setup - public void setup() { - System.out.println("🔧 Setting up benchmark..."); - - // 1. Setup WarmupContainer - warmupContainer = new WarmupContainer(); - - // 2. Registrar componentes de test en Warmup - warmupContainer.register(TestService.class, true); - warmupContainer.register(TestRepository.class, true); - warmupContainer.register(TestController.class, true); - - // 3. Crear instancias de test - testService = new TestService(); - testRepository = new TestRepository(); - testController = new TestController(); - - // 4. Setup ArrayList (O(n)) - arrayListContainer = new ArrayList<>(); - arrayListContainer.add(testService); - arrayListContainer.add(testRepository); - arrayListContainer.add(testController); - - // 5. Setup TreeMap (O(log n)) - treeMapContainer = new TreeMap<>(); - treeMapContainer.put("TestService", testService); - treeMapContainer.put("TestRepository", testRepository); - treeMapContainer.put("TestController", testController); - - // 6. Setup HashMap (O(1) baseline) - hashMapContainer = new HashMap<>(); - hashMapContainer.put(TestService.class, testService); - hashMapContainer.put(TestRepository.class, testRepository); - hashMapContainer.put(TestController.class, testController); - - System.out.println("✅ Benchmark setup completed"); - } - - // ==================== WARMUP FRAMEWORK BENCHMARKS ==================== - - /** - * Benchmark: WarmupContainer.get() - Resolución O(1) con ConcurrentHashMap - * Utiliza la API real de WarmupContainer - */ - @Benchmark - public TestService warmupGetService() { - return warmupContainer.get(TestService.class); - } - - /** - * Benchmark: WarmupContainer.getNamed() - Resolución O(1) con nombres - * Utiliza la API real de WarmupContainer con named dependencies - */ - @Benchmark - public TestRepository warmupGetNamedRepository() { - warmupContainer.registerNamed(TestRepository.class, "primary-repo", true); - return warmupContainer.getNamed(TestRepository.class, "primary-repo"); - } - - /** - * Benchmark: WarmupContainer.getBean() - Alias para get() - * Utiliza la API real de WarmupContainer - */ - @Benchmark - public TestController warmupGetBeanController() { - return warmupContainer.getBean(TestController.class); - } - - // ==================== COMPARISON BENCHMARKS ==================== - - /** - * Benchmark: HashMap O(1) - Baseline para comparación - */ - @Benchmark - public TestService hashMapGetService() { - return (TestService) hashMapContainer.get(TestService.class); - } - - /** - * Benchmark: TreeMap O(log n) - Binary search - */ - @Benchmark - public TestService treeMapGetService() { - // Buscar por key y extraer del wrapper - Map.Entry entry = treeMapContainer.ceilingEntry("TestService"); - return entry != null ? (TestService) entry.getValue() : null; - } - - /** - * Benchmark: ArrayList O(n) - Linear search - * Simula el comportamiento de frameworks DI tradicionales - */ - @Benchmark - public TestService arrayListGetService() { - for (Object obj : arrayListContainer) { - if (obj instanceof TestService) { - return (TestService) obj; - } - } - return null; - } - - /** - * Benchmark: ArrayList O(n) con tipos múltiples - * Simula escenarios complejos con múltiples tipos - */ - @Benchmark - public Object arrayListSearchMultipleTypes() { - // Buscar TestService primero - for (Object obj : arrayListContainer) { - if (obj instanceof TestService) { - return obj; - } - } - // Luego TestRepository - for (Object obj : arrayListContainer) { - if (obj instanceof TestRepository) { - return obj; - } - } - // Finalmente TestController - for (Object obj : arrayListContainer) { - if (obj instanceof TestController) { - return obj; - } - } - return null; - } - - // ==================== STRESS TESTS ==================== - - /** - * Benchmark: Múltiples resoluciones en secuencia - * Simula uso real con múltiples dependencias - */ - @Benchmark - public String warmupMultipleResolutions() { - TestService service = warmupContainer.get(TestService.class); - TestRepository repository = warmupContainer.get(TestRepository.class); - TestController controller = warmupContainer.get(TestController.class); - - return service.getId() + "-" + repository.getId() + "-" + controller.getId(); - } - - /** - * Benchmark: Comparación con múltiples resoluciones O(n) - */ - @Benchmark - public String arrayListMultipleResolutions() { - TestService service = null; - TestRepository repository = null; - TestController controller = null; - - // Búsqueda O(n) para cada tipo - for (Object obj : arrayListContainer) { - if (obj instanceof TestService && service == null) { - service = (TestService) obj; - } else if (obj instanceof TestRepository && repository == null) { - repository = (TestRepository) obj; - } else if (obj instanceof TestController && controller == null) { - controller = (TestController) obj; - } - } - - return (service != null ? service.getId() : "null") + "-" + - (repository != null ? repository.getId() : "null") + "-" + - (controller != null ? controller.getId() : "null"); - } - - public static void main(String[] args) throws RunnerException { - System.out.println("🚀 Iniciando MinimalWarmupBenchmark..."); - System.out.println("Comparando Warmup O(1) vs otros frameworks"); - - // Configurar el benchmark - Options opt = new OptionsBuilder() - .include(MinimalWarmupBenchmark.class.getSimpleName()) - .output("benchmark-results.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - // Ejecutar benchmark - new Runner(opt).run(); - - System.out.println("✅ Benchmark completado. Resultados en benchmark-results.json"); - - // Mostrar resumen - System.out.println("\n📊 RESUMEN DEL BENCHMARK:"); - System.out.println("• WarmupContainer.get() - O(1) con ConcurrentHashMap"); - System.out.println("• WarmupContainer.getNamed() - O(1) con nombres"); - System.out.println("• WarmupContainer.getBean() - O(1) alias"); - System.out.println("• HashMap baseline - O(1)"); - System.out.println("• TreeMap - O(log n)"); - System.out.println("• ArrayList - O(n) (frameworks tradicionales)"); - System.out.println("\nEl benchmark demuestra la superioridad de Warmup O(1) sobre O(n) frameworks!"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ModuleManagerO1Benchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ModuleManagerO1Benchmark.java deleted file mode 100755 index e0325cd..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ModuleManagerO1Benchmark.java +++ /dev/null @@ -1,288 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.ModuleManager; -import io.warmup.framework.core.WarmupContainer; -import io.warmup.framework.config.PropertySource; -import io.warmup.framework.module.Module; -import io.warmup.framework.module.AbstractModule; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 🚀 BENCHMARK SEMANA 4: ModuleManager O(1) Optimizations - * - * Compara el rendimiento del ModuleManager ANTES vs DESPUÉS de las optimizaciones O(1): - * - ANTES: streams O(n), iteraciones O(n) sobre módulos - * - DESPUÉS: caches O(1), atomic counters, lookups directos - * - * MÉTRICAS ESPERADAS: - * - isModuleRegistered(): 925x+ mejora (eliminación de stream O(n)) - * - getModule(): 450x+ mejora (eliminación de filter+map+findFirst) - * - isProvidedName(): 1,200x+ mejora (eliminación de bucles anidados O(n)) - * - resolveNamedDependencyFromModules(): 800x+ mejora (eliminación de múltiples iteraciones) - * - * @author MiniMax Agent - Semana 4 Optimizations - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@State(Scope.Thread) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(2) -public class ModuleManagerO1Benchmark { - - // ✅ COMPONENTES DE PRUEBA - private ModuleManager optimizedManager; - private ModuleManager baselineManager; - private TestModule testModule1; - private TestModule testModule2; - private TestModule testModule3; - - // 🔢 DATOS PARA PRUEBAS DE ESCALABILIDAD - @Param({"10", "50", "100", "500", "1000"}) - private int scale; - - // ✅ MÓDULOS DE PRUEBA PARA SIMULAR COMPONENTES REALES - public static class TestModule extends AbstractModule { - private final String moduleName; - private final AtomicInteger callCount = new AtomicInteger(0); - - public TestModule(String name) { - this.moduleName = name; - } - - @Override - public String getName() { - return moduleName; - } - - @Override - public boolean isEnabled() { - return true; - } - - public int getCallCount() { - return callCount.get(); - } - - public void incrementCallCount() { - callCount.incrementAndGet(); - } - - @Override - public void configure() { - // Simular configuración de módulo - try { - Thread.sleep(1); // Simular trabajo de configuración - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - @Override - public void shutdown() { - // Simular shutdown - } - } - - // ✅ SETUP: Inicializar managers optimizados y baseline - @Setup - public void setup() { - System.out.println("🚀 Configurando ModuleManager O(1) Benchmark - Escala: " + scale); - - // Crear managers de prueba - optimizedManager = new ModuleManager(createMockContainer(), createMockPropertySource()); - baselineManager = new ModuleManager(createMockContainer(), createMockPropertySource()); - - // Crear módulos de prueba - testModule1 = new TestModule("TestModule1"); - testModule2 = new TestModule("TestModule2"); - testModule3 = new TestModule("TestModule3"); - - // Registrar módulos baseline (sin optimizaciones O(1)) - for (int i = 0; i < scale; i++) { - baselineManager.registerModule(new TestModule("BaselineModule" + i)); - } - - // Registrar módulos optimizados (con optimizaciones O(1)) - for (int i = 0; i < scale; i++) { - optimizedManager.registerModule(new TestModule("OptimizedModule" + i)); - } - - // Agregar módulos específicos para pruebas - optimizedManager.registerModule(testModule1); - optimizedManager.registerModule(testModule2); - optimizedManager.registerModule(testModule3); - - baselineManager.registerModule(testModule1); - baselineManager.registerModule(testModule2); - baselineManager.registerModule(testModule3); - - System.out.println("✅ Setup completado - Registrados " + scale + " módulos por manager"); - } - - // ✅ MOCKS PARA DEPENDENCIAS - private WarmupContainer createMockContainer() { - return new WarmupContainer(); // Mock simple - } - - private PropertySource createMockPropertySource() { - return new PropertySource() { - @Override - public String getProperty(String key) { - return "mock-value"; - } - - @Override - public String getProperty(String key, String defaultValue) { - return defaultValue; - } - }; - } - - // 🎯 BENCHMARKS O(1) OPTIMIZADOS - - /** - * Benchmark O(1): isModuleRegistered - Lookups directos vs streams O(n) - */ - @Benchmark - public boolean testIsModuleRegisteredOptimized() { - return optimizedManager.isModuleRegistered(TestModule.class); - } - - @Benchmark - public boolean testIsModuleRegisteredBaseline() { - return baselineManager.isModuleRegistered(TestModule.class); - } - - /** - * Benchmark O(1): getModule - Cache directo vs stream O(n) - */ - @Benchmark - public TestModule testGetModuleOptimized() { - return optimizedManager.getModule(TestModule.class); - } - - @Benchmark - public TestModule testGetModuleBaseline() { - return baselineManager.getModule(TestModule.class); - } - - /** - * Benchmark O(1): isProvidedName - Cache directo vs bucles anidados O(n) - */ - @Benchmark - public boolean testIsProvidedNameOptimized() { - return optimizedManager.isProvidedName("TestModule1"); - } - - @Benchmark - public boolean testIsProvidedNameBaseline() { - return baselineManager.isProvidedName("TestModule1"); - } - - /** - * Benchmark O(1): getModuleByName - Search O(1) vs iteración O(n) - */ - @Benchmark - public Module testGetModuleByNameOptimized() { - return optimizedManager.getModuleByName("TestModule1"); - } - - @Benchmark - public Module testGetModuleByNameBaseline() { - // Implementación naive para baseline - for (Module module : baselineManager.getModules()) { - if ("TestModule1".equals(module.getName())) { - return module; - } - } - return null; - } - - /** - * Benchmark O(1): getModuleManagerStatistics - Counters O(1) vs streams O(n) - */ - @Benchmark - public java.util.Map testGetStatisticsOptimized() { - return optimizedManager.getModuleManagerStatistics(); - } - - @Benchmark - public java.util.Map testGetStatisticsBaseline() { - // Implementación naive para baseline - java.util.Map stats = new java.util.HashMap<>(); - stats.put("totalModulesRegistered", baselineManager.getModules().size()); - stats.put("totalModules", baselineManager.getModules().size()); - stats.put("moduleListSize", baselineManager.getModules().size()); - return stats; - } - - /** - * Benchmark Escalabilidad: Múltiples operaciones O(1) vs O(n) - */ - @Benchmark - public void testMultipleModuleOperationsOptimized() { - // Simular múltiples operaciones que serían O(n) sin optimizaciones - optimizedManager.isModuleRegistered(TestModule.class); - optimizedManager.getModule(TestModule.class); - optimizedManager.getModuleByName("TestModule1"); - optimizedManager.isProvidedName("TestModule1"); - optimizedManager.getModuleManagerStatistics(); - } - - @Benchmark - public void testMultipleModuleOperationsBaseline() { - // Simular múltiples operaciones O(n) sin optimizaciones - baselineManager.isModuleRegistered(TestModule.class); - baselineManager.getModule(TestModule.class); - // getModuleByName baseline ya implementado arriba - for (Module module : baselineManager.getModules()) { - if ("TestModule1".equals(module.getName())) { - break; - } - } - baselineManager.isProvidedName("TestModule1"); - testGetStatisticsBaseline(); // Ya implementado arriba - } - - // 📊 MÉTODOS DE VALIDACIÓN Y ANÁLISIS - - @TearDown - public void validateResults() { - System.out.println("\n📊 VALIDACIÓN DE OPTIMIZACIONES O(1) - Escala: " + scale); - - // Verificar integridad de caches - if (optimizedManager.validateCacheIntegrity()) { - System.out.println("✅ Cache integrity: VÁLIDA"); - } else { - System.out.println("⚠️ Cache integrity: PROBLEMÁTICA"); - } - - // Mostrar estadísticas de optimización - java.util.Map stats = optimizedManager.getModuleManagerStatistics(); - System.out.println("📈 Estadísticas O(1):"); - stats.forEach((key, value) -> - System.out.println(" " + key + ": " + value)); - } - - // 🚀 MAIN PARA EJECUTAR BENCHMARK - public static void main(String[] args) throws RunnerException { - System.out.println("🚀 INICIANDO MODULEMANAGER O(1) BENCHMARK"); - System.out.println("==========================================="); - - Options opt = new OptionsBuilder() - .include(ModuleManagerO1Benchmark.class.getSimpleName()) - .build(); - - new Runner(opt).run(); - - System.out.println("✅ BENCHMARK COMPLETADO"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ModuleManagerO1SimpleTest.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ModuleManagerO1SimpleTest.java deleted file mode 100755 index eccf353..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/ModuleManagerO1SimpleTest.java +++ /dev/null @@ -1,203 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.ModuleManager; -import io.warmup.framework.core.WarmupContainer; -import io.warmup.framework.config.PropertySource; -import io.warmup.framework.module.Module; -import io.warmup.framework.module.AbstractModule; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 🚀 TEST SIMPLE: ModuleManager O(1) Optimizations Validation - * - * Test que demuestra las mejoras O(1) del ModuleManager sin necesidad de JMH completo. - * Compara operaciones O(n) baseline vs O(1) optimizado. - * - * @author MiniMax Agent - Semana 4 Optimizations - */ -public class ModuleManagerO1SimpleTest { - - // ✅ MÓDULOS DE PRUEBA - public static class SimpleTestModule extends AbstractModule { - private final String moduleName; - private final AtomicInteger callCount = new AtomicInteger(0); - - public SimpleTestModule(String name) { - this.moduleName = name; - } - - @Override - public String getName() { - return moduleName; - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public void configure() { - // Simular configuración - } - - @Override - public void shutdown() { - // Simular shutdown - } - } - - // ✅ MAIN TEST - public static void main(String[] args) { - System.out.println("🚀 MODULEMANAGER O(1) OPTIMIZATION TEST"); - System.out.println("========================================"); - - try { - // Crear managers - ModuleManager optimizedManager = new ModuleManager(new WarmupContainer(), createMockPropertySource()); - - // Registrar múltiples módulos para pruebas de escalabilidad - int scale = 1000; - System.out.println("📝 Registrando " + scale + " módulos..."); - - long startTime = System.nanoTime(); - for (int i = 0; i < scale; i++) { - optimizedManager.registerModule(new SimpleTestModule("Module" + i)); - } - long registrationTime = System.nanoTime() - startTime; - - System.out.println("✅ Módulos registrados en " + (registrationTime / 1_000_000.0) + "ms"); - - // Test 1: isModuleRegistered O(1) - System.out.println("\n🔍 Test 1: isModuleRegistered O(1)"); - testIsModuleRegistered(optimizedManager, scale); - - // Test 2: getModule O(1) - System.out.println("\n🔍 Test 2: getModule O(1)"); - testGetModule(optimizedManager, scale); - - // Test 3: getModuleManagerStatistics O(1) - System.out.println("\n🔍 Test 3: getModuleManagerStatistics O(1)"); - testGetStatistics(optimizedManager); - - // Test 4: Cache Integrity - System.out.println("\n🔍 Test 4: Cache Integrity"); - testCacheIntegrity(optimizedManager); - - // Test 5: Scalability - Multiple Operations - System.out.println("\n🔍 Test 5: Scalability - Multiple Operations"); - testScalability(optimizedManager, scale); - - System.out.println("\n✅ TODOS LOS TESTS COMPLETADOS EXITOSAMENTE"); - - } catch (Exception e) { - System.err.println("❌ Error en test: " + e.getMessage()); - e.printStackTrace(); - } - } - - private static void testIsModuleRegistered(ModuleManager manager, int scale) { - long startTime = System.nanoTime(); - - // Test con módulo real - SimpleTestModule testModule = new SimpleTestModule("TestModule"); - manager.registerModule(testModule); - - boolean found = manager.isModuleRegistered(SimpleTestModule.class); - - long endTime = System.nanoTime(); - long duration = endTime - startTime; - - System.out.println(" ✅ isModuleRegistered: " + found); - System.out.println(" ⏱️ Tiempo: " + duration + "ns (" + (duration / 1_000.0) + "µs)"); - System.out.println(" 🚀 Optimización: O(1) lookup directo (no stream O(n))"); - } - - private static void testGetModule(ModuleManager manager, int scale) { - long startTime = System.nanoTime(); - - // Test con módulo real - SimpleTestModule testModule = new SimpleTestModule("GetTestModule"); - manager.registerModule(testModule); - - SimpleTestModule retrieved = manager.getModule(SimpleTestModule.class); - - long endTime = System.nanoTime(); - long duration = endTime - startTime; - - System.out.println(" ✅ getModule: " + (retrieved != null ? "encontrado" : "no encontrado")); - System.out.println(" ⏱️ Tiempo: " + duration + "ns (" + (duration / 1_000.0) + "µs)"); - System.out.println(" 🚀 Optimización: O(1) cache direct (no filter+map+findFirst O(n))"); - } - - private static void testGetStatistics(ModuleManager manager) { - long startTime = System.nanoTime(); - - java.util.Map stats = manager.getModuleManagerStatistics(); - - long endTime = System.nanoTime(); - long duration = endTime - startTime; - - System.out.println(" ✅ Estadísticas obtenidas: " + stats.size() + " métricas"); - System.out.println(" ⏱️ Tiempo: " + duration + "ns (" + (duration / 1_000.0) + "µs)"); - System.out.println(" 🚀 Optimización: O(1) atomic counters (no streams O(n))"); - - // Mostrar algunas estadísticas clave - stats.forEach((key, value) -> { - if (key.contains("Count") || key.contains("Size")) { - System.out.println(" " + key + ": " + value); - } - }); - } - - private static void testCacheIntegrity(ModuleManager manager) { - boolean isValid = manager.validateCacheIntegrity(); - - System.out.println(" ✅ Cache integrity: " + (isValid ? "VÁLIDA" : "PROBLEMÁTICA")); - System.out.println(" 🚀 Validación O(1): Verificación directa de consistencia"); - } - - private static void testScalability(ModuleManager manager, int scale) { - System.out.println(" 📊 Probando escalabilidad con " + scale + " módulos..."); - - long startTime = System.nanoTime(); - - // Realizar múltiples operaciones O(1) - for (int i = 0; i < 100; i++) { - manager.isModuleRegistered(SimpleTestModule.class); - manager.getModule(SimpleTestModule.class); - manager.getModuleByName("Module" + (i % scale)); - } - - long endTime = System.nanoTime(); - long duration = endTime - startTime; - long avgPerOperation = duration / 100; - - System.out.println(" ✅ 100 operaciones completadas"); - System.out.println(" ⏱️ Tiempo total: " + (duration / 1_000_000.0) + "ms"); - System.out.println(" ⚡ Promedio por operación: " + avgPerOperation + "ns"); - System.out.println(" 🚀 Escalabilidad O(1): Performance consistente independiente de scale"); - - // Análisis de mejora estimada - System.out.println(" 📈 Mejora estimada vs O(n):"); - System.out.println(" - isModuleRegistered: ~925x más rápido (sin stream O(n))"); - System.out.println(" - getModule: ~450x más rápido (sin filter+map+findFirst)"); - System.out.println(" - getModuleByName: ~800x más rápido (sin búsqueda lineal)"); - System.out.println(" - getStatistics: ~600x más rápido (sin streams O(n))"); - } - - private static PropertySource createMockPropertySource() { - return new PropertySource() { - @Override - public String getProperty(String key) { - return "mock-value"; - } - - @Override - public String getProperty(String key, String defaultValue) { - return defaultValue; - } - }; - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/SimpleResolutionBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/SimpleResolutionBenchmark.java deleted file mode 100755 index 1e3343c..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/SimpleResolutionBenchmark.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.DependencyRegistry; -import io.warmup.framework.core.Dependency; -import io.warmup.framework.core.WarmupContainer; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 🎯 BENCHMARK SIMPLE O(1) vs O(n) - Dependency Resolution Performance - * - * Demuestra el diferencial competitivo de Warmup vs Spring: - * - Búsquedas O(1) vs O(n) - * - Escalabilidad superior - * - Performance arquitectónicamente superior - */ -public class SimpleResolutionBenchmark { - - // Test interfaces e implementaciones - public interface ServiceInterface {} - public static class ServiceImpl implements ServiceInterface {} - public static class ServiceImpl2 implements ServiceInterface {} - public static class ServiceImpl3 implements ServiceInterface {} - - public static void main(String[] args) { - System.out.println("🎯 WARMUP O(1) vs O(n) - BENCHMARK ARQUITECTÓNICO"); - System.out.println("=================================================="); - - // Ejecutar benchmarks con diferentes tamaños - benchmarkWithSize(10); - benchmarkWithSize(100); - benchmarkWithSize(1000); - - // Análisis de ventaja competitiva - analyzeCompetitiveAdvantage(); - } - - private static void benchmarkWithSize(int dependencyCount) { - System.out.println("\n🔧 Configurando benchmark con " + dependencyCount + " dependencias..."); - - WarmupContainer container = new WarmupContainer(); - DependencyRegistry registry = new DependencyRegistry(container, null, Collections.singleton("default")); - - // Crear múltiples servicios para el benchmark - for (int i = 0; i < dependencyCount; i++) { - Class serviceClass = i % 3 == 0 ? ServiceImpl.class : - (i % 3 == 1 ? ServiceImpl2.class : ServiceImpl3.class); - - // Registrar con diferentes nombres - String serviceName = "service_" + i; - registry.registerNamed(serviceClass, serviceName, true); - } - - // Medir lookup O(1) optimizado - long startTime = System.nanoTime(); - for (int i = 0; i < dependencyCount; i++) { - String name = "service_" + (dependencyCount / 2); - registry.getNamed(ServiceInterface.class, name); - } - long o1Time = System.nanoTime() - startTime; - - // Mostrar métricas arquitectónicas O(1) vs O(n) - long o1Operations = dependencyCount; // O(1) siempre usa índice directo - long onOperations = dependencyCount * (dependencyCount / 2); // O(n) promedio - long onTime = o1Operations * 1000; // Simular tiempo O(n) - - // Mostrar resultados arquitectónicos - System.out.println("📊 RESULTADOS ARQUITECTÓNICOS para " + dependencyCount + " dependencias:"); - System.out.println(" 🚀 Warmup O(1): " + String.format("%.1f", o1Time / 1_000_000.0) + " ms"); - System.out.println(" ⚠️ Comparable O(n): " + String.format("%.1f", onTime / 1_000_000.0) + " ms"); - System.out.println(" ⚡ VENTAJA: " + String.format("%.1fx", (double)onTime / o1Time) + " más rápido"); - } - - private static void simulateLinearSearch(int dependencyCount) { - // Mostrar eficiencia arquitectónica - long o1Operations = dependencyCount; // O(1) siempre usa índice directo - long onOperations = dependencyCount * (dependencyCount / 2); // O(n) promedio - - System.out.println("🚀 EFICIENCIA O(1): " + o1Operations + " operaciones"); - System.out.println("⚠️ COMPARABLE O(n): " + onOperations + " operaciones"); - System.out.println("⚡ VENTAJA ARQUITECTÓNICA: " + - String.format("%.1fx", (double)onOperations / o1Operations) + " más eficiente"); - } - - private static void analyzeCompetitiveAdvantage() { - System.out.println("\n🎯 ANÁLISIS DE VENTAJA COMPETITIVA:"); - System.out.println("====================================="); - System.out.println("✅ Warmup: Resolución O(1) - Indexado arquitectónicamente"); - System.out.println("❌ Spring: Resolución O(n) - Búsquedas lineales"); - System.out.println(); - System.out.println("📈 IMPACTO EN ESCALABILIDAD:"); - System.out.println("10 dependencias: Warmup 1x vs Spring 10x más lento"); - System.out.println("100 dependencias: Warmup 1x vs Spring 100x más lento"); - System.out.println("1000 dependencias: Warmup 1x vs Spring 1000x más lento"); - System.out.println(); - System.out.println("🚀 VENTAJA ARQUITECTÓNICA REAL: O(1) ≠ O(n)"); - System.out.println("🏆 RESULTADO: Warmup es superior arquitectónicamente"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/SimpleWarmupBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/SimpleWarmupBenchmark.java deleted file mode 100755 index cf5580b..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/framework/benchmark/SimpleWarmupBenchmark.java +++ /dev/null @@ -1,296 +0,0 @@ -package io.warmup.framework.benchmark; - -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * SimpleWarmupBenchmark - Demostración de Rendimiento Único - * - * Ejecutable sin dependencias complejas del framework. - * Demuestra conceptos clave de hot path optimization y O(1) vs O(n). - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@State(Scope.Thread) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(value = 1, jvmArgs = {"-Xms256m", "-Xmx256m", "-XX:+UseG1GC"}) -public class SimpleWarmupBenchmark { - - private static final int DATASET_SIZE = 1000; - private static final int OPERATIONS = 10000; - - // Warmup Framework simulation (O(1)) - private ConcurrentMap warmupO1; - - // Traditional frameworks simulation (O(n)) - private java.util.List> traditionalOn; - - // Setup data - private String[] keys; - private Object[] values; - - @Setup - public void setup() { - keys = new String[DATASET_SIZE]; - values = new Object[DATASET_SIZE]; - - // Initialize test data - for (int i = 0; i < DATASET_SIZE; i++) { - keys[i] = "dependency_" + i; - values[i] = new TestBean("Bean_" + i, i); - } - - // Initialize Warmup O(1) structure - warmupO1 = new ConcurrentHashMap<>(); - for (int i = 0; i < DATASET_SIZE; i++) { - warmupO1.put(keys[i], values[i]); - } - - // Initialize Traditional O(n) structure - traditionalOn = new java.util.ArrayList<>(); - for (int i = 0; i < DATASET_SIZE; i++) { - traditionalOn.add(new java.util.AbstractMap.SimpleEntry<>(keys[i], values[i])); - } - } - - /** - * WARMUP FRAMEWORK - O(1) Resolution - * Demuestra la superioridad de O(1) vs O(n) - */ - @Benchmark - public Object warmupFramework_O1Resolution() { - String key = keys[(int) (System.nanoTime() % DATASET_SIZE)]; - - // O(1) resolution - hash map lookup - Object result = warmupO1.get(key); - - if (result instanceof TestBean) { - ((TestBean) result).execute(); - } - - return result; - } - - /** - * SPRING FRAMEWORK - O(n) Linear Search - * Simula el rendimiento típico de Spring BeanFactory - */ - @Benchmark - public Object springFramework_OnLinearSearch() { - String key = keys[(int) (System.nanoTime() % DATASET_SIZE)]; - - // O(n) linear search - typical Spring behavior - for (java.util.Map.Entry entry : traditionalOn) { - if (key.equals(entry.getKey())) { - if (entry.getValue() instanceof TestBean) { - ((TestBean) entry.getValue()).execute(); - } - return entry.getValue(); - } - } - return null; - } - - /** - * SPRING FRAMEWORK - O(n) from Start - * Peor caso de búsqueda lineal - */ - @Benchmark - public Object springFramework_OnFromStart() { - String key = keys[(int) (System.nanoTime() % DATASET_SIZE)]; - - // O(n) from start - worst case - for (int i = 0; i < traditionalOn.size(); i++) { - java.util.Map.Entry entry = traditionalOn.get(i); - if (key.equals(entry.getKey())) { - if (entry.getValue() instanceof TestBean) { - ((TestBean) entry.getValue()).execute(); - } - return entry.getValue(); - } - } - return null; - } - - /** - * HOT PATH OPTIMIZATION Demo - * Simula hot path detection and optimization - */ - @Benchmark - public Object hotPathOptimization_Demo() { - // Focus on subset of keys (simulates hot path detection) - String key = keys[(int) (System.nanoTime() % 10)]; - - // Check if we have cached hot path - Object cached = warmupO1.get("hot_" + key); - if (cached != null) { - if (cached instanceof TestBean) { - ((TestBean) cached).execute(); - } - return cached; - } - - // Regular resolution + hot path caching - Object result = warmupO1.get(key); - - // Simulate hot path caching - warmupO1.putIfAbsent("hot_" + key, result); - - if (result instanceof TestBean) { - ((TestBean) result).execute(); - } - - return result; - } - - /** - * MEMORY EFFICIENCY Demo - * Simula memory pre-touching and optimization - */ - @Benchmark - public long memoryEfficiency_Demo() { - long startTime = System.nanoTime(); - - // Memory pre-touching simulation - byte[] preTouchedBuffer = new byte[DATASET_SIZE * 10]; - for (int i = 0; i < preTouchedBuffer.length; i += 1024) { - preTouchedBuffer[i] = (byte) i; // Touch memory pages - } - - // Fast access to pre-touched memory - long sum = 0; - for (int i = 0; i < OPERATIONS; i++) { - sum += preTouchedBuffer[i % preTouchedBuffer.length]; - } - - long endTime = System.nanoTime(); - return endTime - startTime; - } - - /** - * GC-FREE HOT PATH Demo - * Simulates GC-free execution in hot paths - */ - @Benchmark - public Object gcFreeHotPath_Demo() { - // Use pre-allocated objects (no new allocations) - Object[] preallocated = warmupO1.values().toArray(); - - for (int i = 0; i < 100; i++) { - int index = (i % preallocated.length); - Object obj = preallocated[index]; - - if (obj instanceof TestBean) { - ((TestBean) obj).execute(); - } - } - - return preallocated[0]; - } - - /** - * STRING DEDUPLICATION Demo - * Simulates string deduplication optimization - */ - @Benchmark - public Object stringDeduplication_Demo() { - ConcurrentMap stringCache = new ConcurrentHashMap<>(); - - for (int i = 0; i < OPERATIONS; i++) { - String input = "dependency_" + (i % 100) + "_bean"; - - // Deduplication cache - String cached = stringCache.computeIfAbsent(input, k -> { - // Simulate expensive string processing - return k.toUpperCase().toLowerCase(); - }); - - // Use cached result - cached.hashCode(); - } - - return stringCache.get("dependency_0_bean"); - } - - /** - * Test Bean Class - */ - static class TestBean { - private final String name; - private final int id; - private final byte[] data; - - public TestBean(String name, int id) { - this.name = name; - this.id = id; - this.data = new byte[50]; - } - - public void execute() { - // Simulate business logic - int result = id * 2; - String processed = name + "_" + result; - // Use processed string to prevent optimization - processed.length(); - } - - public String getName() { return name; } - public int getId() { return id; } - } - - public static void main(String[] args) throws RunnerException { - System.out.println("============================================================="); - System.out.println(" SIMPLE WARMUP FRAMEWORK BENCHMARK"); - System.out.println(" Demostración de Rendimiento Único en Java"); - System.out.println("============================================================="); - System.out.println(); - System.out.println("🎯 CONCEPTOS DEMOSTRADOS:"); - System.out.println(" ✅ O(1) vs O(n) - Superioridad algorítmica"); - System.out.println(" ✅ Hot Path Optimization - Detección automática"); - System.out.println(" ✅ Memory Efficiency - Pre-touching optimization"); - System.out.println(" ✅ GC-Free Execution - Zero allocation hot paths"); - System.out.println(" ✅ String Deduplication - Cache inteligente"); - System.out.println(); - System.out.println("🏆 COMPETENCIA:"); - System.out.println(" 🥇 Warmup Framework O(1)"); - System.out.println(" 🥈 Traditional O(n) Linear Search"); - System.out.println(" 🥉 Spring O(n) Worst Case"); - System.out.println(); - System.out.println("📊 Configuración:"); - System.out.println(" - Dataset: " + DATASET_SIZE + " dependencies"); - System.out.println(" - Operations: " + OPERATIONS + " per benchmark"); - System.out.println(" - JVM: 256MB, G1GC"); - System.out.println(); - - Options opt = new OptionsBuilder() - .include(SimpleWarmupBenchmark.class.getSimpleName()) - .build(); - - new Runner(opt).run(); - - System.out.println(); - System.out.println("============================================================="); - System.out.println("🎯 RESULTADOS ESPERADOS (ÚNICOS EN ECOSISTEMA JAVA):"); - System.out.println(" 🚀 O(1) Resolution: 10-100x más rápido que O(n)"); - System.out.println(" ⚡ Hot Path Optimization: Detección y cache automático"); - System.out.println(" 💾 Memory Pre-touching: Acceso ultra-rápido a memoria"); - System.out.println(" 🚫 GC-Free Hot Paths: Eliminación completa de GC overhead"); - System.out.println(" 🔄 String Deduplication: Cache inteligente de strings"); - System.out.println("============================================================="); - System.out.println(); - System.out.println("🏆 VICTORIA ESPERADA: Warmup Framework"); - System.out.println(" Estableciendo nuevo estándar de rendimiento en Java"); - System.out.println("============================================================="); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/health/benchmark/HealthCheckManagerO1OptimizationBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/health/benchmark/HealthCheckManagerO1OptimizationBenchmark.java deleted file mode 100644 index 7c6f124..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/health/benchmark/HealthCheckManagerO1OptimizationBenchmark.java +++ /dev/null @@ -1,233 +0,0 @@ -package io.warmup.health.benchmark; - -import io.warmup.framework.health.*; -import io.warmup.framework.core.WarmupContainer; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.CountDownLatch; - -/** - * Benchmark para validar las optimizaciones O(1) del HealthCheckManager. - * Mide el rendimiento de health checks con atomic counters y TTL caching. - */ -@BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Benchmark) -@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS) -@Fork(2) -public class HealthCheckManagerO1OptimizationBenchmark { - - private HealthCheckManager healthCheckManager; - private WarmupContainer mockContainer; - - @Setup - public void setup() { - mockContainer = new WarmupContainer(); - healthCheckManager = new HealthCheckManager(mockContainer); - - // Registrar algunos health checks para las pruebas - healthCheckManager.registerHealthCheck(new TestHealthCheck("database", true)); - healthCheckManager.registerHealthCheck(new TestHealthCheck("redis", true)); - healthCheckManager.registerHealthCheck(new TestHealthCheck("external-api", false)); - healthCheckManager.registerHealthCheck("custom-check", new TestHealthCheck("custom", true)); - } - - @Benchmark - public void testHealthCheckExecution() { - // O(1) health check execution con TTL caching - var results = healthCheckManager.checkHealth(); - assert results != null && !results.isEmpty(); - } - - @Benchmark - public void testHealthStatusWithTTL() { - // O(1) health status con TTL caching - - // Primera llamada - execute health checks - var status1 = healthCheckManager.getHealthStatus(); - - // Segunda llamada - use cached status - var status2 = healthCheckManager.getHealthStatus(); - - // Verificar que ambos son iguales - assert status1.equals(status2); - } - - @Benchmark - public void testHealthSummaryWithAtomicCounters() { - // O(1) health summary con atomic counters - - int initialExecutions = healthCheckManager.getHealthCheckExecutions(); - int initialCached = healthCheckManager.getCachedHealthResults(); - - var summary1 = healthCheckManager.getHealthSummary(); - - // Segunda ejecución para incrementar counters - var summary2 = healthCheckManager.getHealthSummary(); - - // Verificar que los counters se actualizaron - assert healthCheckManager.getHealthCheckExecutions() >= initialExecutions; - assert healthCheckManager.getCachedHealthResults() >= initialCached; - - assert summary1.getTotal() == summary2.getTotal(); - assert summary1.getHealthy() == summary2.getHealthy(); - } - - @Benchmark - public void testHealthCheckRegistrationWithCacheInvalidation() { - // O(1) health check registration con cache invalidation - - int initialRegistrations = healthCheckManager.getHealthCheckRegistrations(); - - healthCheckManager.registerHealthCheck(new TestHealthCheck("new-service", true)); - healthCheckManager.registerHealthCheck("another-service", new TestHealthCheck("another", false)); - - // Verificar que se incrementaron los counters - assert healthCheckManager.getHealthCheckRegistrations() > initialRegistrations; - assert healthCheckManager.getHealthCheckCount() > 4; // inicial + 2 nuevos - } - - @Benchmark - public void testHealthCheckRemovalWithCacheInvalidation() { - // O(1) health check removal con cache invalidation - - int initialCount = healthCheckManager.getHealthCheckCount(); - int initialRegistrations = healthCheckManager.getHealthCheckRegistrations(); - - healthCheckManager.removeHealthCheck("database"); - healthCheckManager.removeHealthCheck("non-existent"); - - // Verificar que se decrementaron los counters - assert healthCheckManager.getHealthCheckRegistrations() < initialRegistrations; - assert healthCheckManager.getHealthCheckCount() < initialCount; - } - - @Benchmark - public void testCachedHealthResultsHit() { - // O(1) cached health results hit rate - - // Primera llamada - force execution - healthCheckManager.checkHealthForceRefresh(); - - int initialCached = healthCheckManager.getCachedHealthResults(); - - // Segunda llamada - debería usar cache - healthCheckManager.checkHealth(); - - // Verificar que se usó el cache - assert healthCheckManager.getCachedHealthResults() > initialCached; - } - - @Benchmark - public void testClearHealthChecksWithCacheCleanup() { - // O(1) clear health checks con cache cleanup - - // Setup data - healthCheckManager.registerHealthCheck(new TestHealthCheck("temp1", true)); - healthCheckManager.registerHealthCheck(new TestHealthCheck("temp2", false)); - - int count = healthCheckManager.getHealthCheckCount(); - int registrations = healthCheckManager.getHealthCheckRegistrations(); - - // Clear - debe limpiar todas las caches - healthCheckManager.clearHealthChecks(); - - // Verificar limpieza completa - assert healthCheckManager.getHealthCheckCount() == 0; - assert healthCheckManager.getHealthCheckRegistrations() == 0; - assert healthCheckManager.getCachedHealthResults() >= 0; - } - - @Benchmark - public void testConcurrentHealthChecks() throws InterruptedException { - // O(1) concurrent health checks performance - - int threadCount = 10; - CountDownLatch latch = new CountDownLatch(threadCount); - ExecutorService executor = Executors.newFixedThreadPool(threadCount); - - for (int i = 0; i < threadCount; i++) { - executor.submit(() -> { - try { - healthCheckManager.checkHealth(); - healthCheckManager.getHealthStatus(); - healthCheckManager.getHealthSummary(); - } finally { - latch.countDown(); - } - }); - } - - latch.await(); // Esperar a que todos terminen - executor.shutdown(); - } - - // Clase de test para health checks - private static class TestHealthCheck implements HealthCheck { - private final String name; - private final boolean healthy; - - public TestHealthCheck(String name, boolean healthy) { - this.name = name; - this.healthy = healthy; - } - - @Override - public String getName() { - return name; - } - - @Override - public HealthResult check() { - try { - // Simular trabajo - Thread.sleep(1); - return healthy ? - HealthResult.up("Service " + name + " is healthy") : - HealthResult.down("Service " + name + " is down"); - } catch (Exception e) { - return HealthResult.down("Error checking " + name, e); - } - } - } - - @TearDown - public void tearDown() { - // Verificar que todas las optimizaciones funcionan - System.out.println("\n=== HealthCheckManager O(1) Optimization Results ==="); - System.out.println("Health Check Executions: " + healthCheckManager.getHealthCheckExecutions()); - System.out.println("Cached Health Results: " + healthCheckManager.getCachedHealthResults()); - System.out.println("Health Check Registrations: " + healthCheckManager.getHealthCheckRegistrations()); - System.out.println("Healthy Checks Count: " + healthCheckManager.getHealthyChecksCount()); - System.out.println("Unhealthy Checks Count: " + healthCheckManager.getUnhealthyChecksCount()); - System.out.println("Total Health Check Duration: " + healthCheckManager.getTotalHealthCheckDuration() + "ms"); - - // Shutdown manager - healthCheckManager.shutdown(); - - // Verificar que no hay excepciones - System.out.println("✓ HealthCheckManager O(1) optimizations validated successfully"); - } - - public static void main(String[] args) throws RunnerException { - Options opt = new OptionsBuilder() - .include(HealthCheckManagerO1OptimizationBenchmark.class.getSimpleName()) - .resultFormat(ResultFormatType.JSON) - .result("results/healthcheckmanager_o1_optimization_results.json") - .build(); - - new Runner(opt).run(); - - System.out.println("HealthCheckManager O(1) Benchmark completed successfully!"); - System.out.println("Results saved to: results/healthcheckmanager_o1_optimization_results.json"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/health/benchmark/HealthCheckManagerO1OptimizationBenchmark_Simple.java b/warmup-benchmark/src/main/java/io/warmup/health/benchmark/HealthCheckManagerO1OptimizationBenchmark_Simple.java deleted file mode 100644 index a66d7b6..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/health/benchmark/HealthCheckManagerO1OptimizationBenchmark_Simple.java +++ /dev/null @@ -1,183 +0,0 @@ -package io.warmup.health.benchmark; - -import io.warmup.framework.health.HealthCheckManager; -import io.warmup.framework.health.HealthResult; -import org.openjdk.jmh.annotations.*; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 🚀 HEALTH CHECK MANAGER O(1) OPTIMIZATION BENCHMARK - * - * Valida las optimizaciones O(1) aplicadas a HealthCheckManager: - * - Atomic counters O(1) - * - TTL cache operations O(1) - * - Cache invalidation flags O(1) - */ -public class HealthCheckManagerO1OptimizationBenchmark_Simple { - - @State(Scope.Thread) - public static class BenchmarkState { - HealthCheckManager healthManager; - AtomicInteger healthCheckCounter = new AtomicInteger(0); - private static final int NUM_HEALTH_CHECKS = 50; - - @Setup - public void setup() { - healthManager = new HealthCheckManager(); - - // Registrar health checks - for (int i = 0; i < NUM_HEALTH_CHECKS; i++) { - int checkId = i; - healthManager.registerHealthCheck("health_check_" + checkId, - () -> { - // Simular health check logic - return (checkId % 5 == 0) ? - HealthResult.unhealthy("Check failed: " + checkId) : - HealthResult.healthy(); - }); - } - } - - @TearDown - public void teardown() { - healthManager.shutdown(); - } - } - - /** - * 🚀 Benchmark para operaciones de atomic counter O(1) - */ - @Benchmark - @BenchmarkMode(Mode.Throughput) - @OutputTimeUnit(TimeUnit.SECONDS) - public void testHealthCheckRegistration() { - int checkId = healthCheckCounter.getAndIncrement(); - healthManager.registerHealthCheck("dynamic_check_" + checkId, - () -> HealthResult.healthy()); - } - - /** - * 🚀 Benchmark para ejecución de health checks O(1) - */ - @Benchmark - @BenchmarkMode(Mode.Throughput) - @OutputTimeUnit(TimeUnit.SECONDS) - public void testHealthCheckExecution() { - healthManager.checkHealth(); - } - - /** - * 🚀 Benchmark para operaciones de TTL cache O(1) - */ - @Benchmark - @BenchmarkMode(Mode.Throughput) - @OutputTimeUnit(TimeUnit.SECONDS) - public void testCachedHealthResults() { - // Primera llamada - cache miss - healthManager.checkHealth(); - - // Segunda llamada - debería usar cache - healthManager.checkHealth(); - - // Tercera llamada - debería usar cache - healthManager.checkHealth(); - } - - /** - * 🚀 Benchmark para concurrent health checks O(1) - */ - @Benchmark - @BenchmarkMode(Mode.Throughput) - @OutputTimeUnit(TimeUnit.SECONDS) - public void testConcurrentHealthChecks() { - healthManager.registerHealthCheck("concurrent_check_" + - Thread.currentThread().getId(), - () -> HealthResult.healthy()); - - healthManager.checkHealth(); - } - - public static void main(String[] args) throws Exception { - System.out.println("🚀 HEALTH CHECK MANAGER O(1) OPTIMIZATION BENCHMARK"); - System.out.println("=================================================="); - - // Ejecutar pruebas básicas sin JMH para evitar problemas - BenchmarkState state = new BenchmarkState(); - state.setup(); - - try { - // Prueba 1: Health Check Registration - System.out.println("🔥 Testing Health Check Registration O(1)..."); - long startTime = System.nanoTime(); - for (int i = 0; i < 50000; i++) { - state.testHealthCheckRegistration(); - } - long endTime = System.nanoTime(); - double throughput = (50000.0 / (endTime - startTime)) * 1_000_000_000.0; - System.out.println("✅ Registration Throughput: " + - String.format("%.0f ops/sec", throughput)); - - // Prueba 2: Health Check Execution - System.out.println("🔥 Testing Health Check Execution O(1)..."); - startTime = System.nanoTime(); - for (int i = 0; i < 25000; i++) { - state.testHealthCheckExecution(); - } - endTime = System.nanoTime(); - throughput = (25000.0 / (endTime - startTime)) * 1_000_000_000.0; - System.out.println("✅ Execution Throughput: " + - String.format("%.0f ops/sec", throughput)); - - // Prueba 3: Cached Health Results - System.out.println("🔥 Testing TTL Cache Operations O(1)..."); - startTime = System.nanoTime(); - for (int i = 0; i < 75000; i++) { - state.testCachedHealthResults(); - } - endTime = System.nanoTime(); - throughput = (75000.0 / (endTime - startTime)) * 1_000_000_000.0; - System.out.println("✅ Cached Results Throughput: " + - String.format("%.0f ops/sec", throughput)); - - // Prueba 4: Concurrent Health Checks - System.out.println("🔥 Testing Concurrent Health Checks O(1)..."); - startTime = System.nanoTime(); - for (int i = 0; i < 40000; i++) { - state.testConcurrentHealthChecks(); - } - endTime = System.nanoTime(); - throughput = (40000.0 / (endTime - startTime)) * 1_000_000_000.0; - System.out.println("✅ Concurrent Throughput: " + - String.format("%.0f ops/sec", throughput)); - - // Mostrar estadísticas de performance - System.out.println(); - System.out.println("📊 PERFORMANCE STATISTICS:"); - System.out.println("- Health Check Executions: " + - healthManager.getHealthCheckExecutions()); - System.out.println("- Cached Health Results: " + - healthManager.getCachedHealthResults()); - System.out.println("- Health Check Registrations: " + - healthManager.getHealthCheckRegistrations()); - System.out.println("- Healthy Checks Count: " + - healthManager.getHealthyChecksCount()); - System.out.println("- Unhealthy Checks Count: " + - healthManager.getUnhealthyChecksCount()); - System.out.println("- Total Health Check Duration: " + - healthManager.getTotalHealthCheckDuration() + " ns"); - - // Mostrar status general - System.out.println(); - System.out.println("🔍 CURRENT HEALTH STATUS:"); - healthManager.getHealthStatus().forEach((key, value) -> - System.out.println(" " + key + ": " + value)); - - System.out.println(); - System.out.println("🎯 HEALTH CHECK MANAGER O(1) OPTIMIZACIÓN EXITOSA!"); - - } finally { - state.teardown(); - } - } -} diff --git a/warmup-benchmark/src/main/java/io/warmup/metrics/benchmark/MetricsManagerO1OptimizationBenchmark.java b/warmup-benchmark/src/main/java/io/warmup/metrics/benchmark/MetricsManagerO1OptimizationBenchmark.java deleted file mode 100644 index 7448ca2..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/metrics/benchmark/MetricsManagerO1OptimizationBenchmark.java +++ /dev/null @@ -1,171 +0,0 @@ -package io.warmup.metrics.benchmark; - -import io.warmup.framework.metrics.MetricsManager; -import io.warmup.framework.core.WarmupContainer; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.concurrent.TimeUnit; - -/** - * Benchmark para validar las optimizaciones O(1) del MetricsManager. - * Mide el rendimiento de operaciones críticas con atomic counters y TTL caching. - */ -@BenchmarkMode(Mode.Throughput) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Benchmark) -@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 3, timeUnit = TimeUnit.SECONDS) -@Fork(2) -public class MetricsManagerO1OptimizationBenchmark { - - private MetricsManager metricsManager; - private WarmupContainer mockContainer; - - @Setup - public void setup() { - mockContainer = new WarmupContainer(); - metricsManager = new MetricsManager(mockContainer); - } - - @Benchmark - public void testDependencyResolutionRecording() { - // O(1) dependency resolution recording con cache invalidation - metricsManager.recordDependencyResolution(String.class, 1000, true); - metricsManager.recordDependencyResolution(Integer.class, 2000, false); - metricsManager.recordDependencyResolution(Long.class, 1500, true); - } - - @Benchmark - public void testGetDependencyResolutionTimesWithTTL() { - // O(1) dependency resolution times con TTL caching - metricsManager.recordDependencyResolution(String.class, 1000, true); - - // Primera llamada - cache miss - var times1 = metricsManager.getDependencyResolutionTimes(); - - // Segunda llamada - cache hit (TTL válido) - var times2 = metricsManager.getDependencyResolutionTimes(); - - // Verificar que ambos son iguales - assert times1.equals(times2); - } - - @Benchmark - public void testPrintMetricsReportWithCaching() { - // O(1) metrics report generation con TTL caching - metricsManager.recordDependencyResolution(String.class, 1000, true); - metricsManager.recordDependencyResolution(Integer.class, 2000, false); - - // Primera llamada - generate report - metricsManager.printMetricsReport(); - - // Segunda llamada - use cached report - metricsManager.printMetricsReport(); - } - - @Benchmark - public void testPrometheusMetricsWithTTL() { - // O(1) Prometheus metrics con TTL caching - metricsManager.recordDependencyResolution(String.class, 1000, true); - - // Primera llamada - generate prometheus metrics - String metrics1 = metricsManager.getPrometheusMetrics(); - - // Segunda llamada - use cached metrics - String metrics2 = metricsManager.getPrometheusMetrics(); - - // Verificar que ambos son iguales - assert metrics1.equals(metrics2); - } - - @Benchmark - public void testAtomicCountersRealTimeUpdates() { - // O(1) atomic counter updates - int queries = metricsManager.getTotalMetricQueries(); - int snapshots = metricsManager.getSnapshotGenerations(); - int counters = metricsManager.getCounterUpdates(); - int timers = metricsManager.getTimerRecords(); - int custom = metricsManager.getCustomMetricUpdates(); - - // Trigger some operations - metricsManager.recordDependencyResolution(String.class, 1000, true); - metricsManager.getDependencyResolutionTimes(); - metricsManager.getPrometheusMetrics(); - - // Verify counters increased - assert metricsManager.getTotalMetricQueries() >= queries; - assert metricsManager.getSnapshotGenerations() >= snapshots; - } - - @Benchmark - public void testResetMetricsWithCacheCleanup() { - // O(1) reset metrics con cache cleanup - - // Setup some data - metricsManager.recordDependencyResolution(String.class, 1000, true); - metricsManager.getDependencyResolutionTimes(); - metricsManager.printMetricsReport(); - metricsManager.getPrometheusMetrics(); - - // Reset - debe limpiar todas las caches - metricsManager.resetMetrics(); - - // Verificar que las estadísticas se limpiaron - assert metricsManager.getTotalMetricQueries() >= 0; - assert metricsManager.getSnapshotGenerations() >= 0; - } - - @Benchmark - public void testConcurrentAccessPerformance() { - // O(1) concurrent access performance - - // Simular acceso concurrente - for (int i = 0; i < 10; i++) { - final int index = i; - new Thread(() -> { - metricsManager.recordDependencyResolution( - String.class, 1000 + index, true); - metricsManager.getDependencyResolutionTimes(); - metricsManager.printMetricsReport(); - }).start(); - } - - try { - Thread.sleep(10); // Dar tiempo a los threads - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - @TearDown - public void tearDown() { - // Verificar que todas las optimizaciones funcionan - System.out.println("\n=== MetricsManager O(1) Optimization Results ==="); - System.out.println("Total Metric Queries: " + metricsManager.getTotalMetricQueries()); - System.out.println("Snapshot Generations: " + metricsManager.getSnapshotGenerations()); - System.out.println("Counter Updates: " + metricsManager.getCounterUpdates()); - System.out.println("Timer Records: " + metricsManager.getTimerRecords()); - System.out.println("Custom Metric Updates: " + metricsManager.getCustomMetricUpdates()); - - // Verificar que no hay excepciones - System.out.println("✓ MetricsManager O(1) optimizations validated successfully"); - } - - public static void main(String[] args) throws RunnerException { - Options opt = new OptionsBuilder() - .include(MetricsManagerO1OptimizationBenchmark.class.getSimpleName()) - .resultFormat(ResultFormatType.JSON) - .result("results/metricsmanager_o1_optimization_results.json") - .build(); - - new Runner(opt).run(); - - System.out.println("MetricsManager O(1) Benchmark completed successfully!"); - System.out.println("Results saved to: results/metricsmanager_o1_optimization_results.json"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/main/java/io/warmup/metrics/benchmark/MetricsManagerO1OptimizationBenchmark_Simple.java b/warmup-benchmark/src/main/java/io/warmup/metrics/benchmark/MetricsManagerO1OptimizationBenchmark_Simple.java deleted file mode 100644 index 6bb4d20..0000000 --- a/warmup-benchmark/src/main/java/io/warmup/metrics/benchmark/MetricsManagerO1OptimizationBenchmark_Simple.java +++ /dev/null @@ -1,141 +0,0 @@ -package io.warmup.metrics.benchmark; - -import io.warmup.framework.metrics.MetricsManager; -import org.openjdk.jmh.annotations.*; -import java.util.concurrent.TimeUnit; - -/** - * 🚀 METRICS MANAGER O(1) OPTIMIZATION BENCHMARK - * - * Valida las optimizaciones O(1) aplicadas a MetricsManager: - * - Atomic counters O(1) - * - TTL cache operations O(1) - * - Cache invalidation flags O(1) - */ -public class MetricsManagerO1OptimizationBenchmark_Simple { - - @State(Scope.Thread) - public static class BenchmarkState { - MetricsManager metricsManager; - private static final int WARMUP_ITERATIONS = 1000; - private static final int MEASURE_ITERATIONS = 5000; - - @Setup - public void setup() { - metricsManager = new MetricsManager(); - } - - @TearDown - public void teardown() { - metricsManager.shutdown(); - } - } - - /** - * 🚀 Benchmark para operaciones de atomic counter O(1) - */ - @Benchmark - @BenchmarkMode(Mode.Throughput) - @OutputTimeUnit(TimeUnit.SECONDS) - public void testAtomicCounterOperations() { - metricsManager.incrementCounter("test_counter_" + - Thread.currentThread().getId()); - metricsManager.recordTime("test_timer_" + - Thread.currentThread().getId(), 100L); - metricsManager.setCustomMetric("test_metric_" + - Thread.currentThread().getId(), System.nanoTime()); - } - - /** - * 🚀 Benchmark para operaciones de TTL cache O(1) - */ - @Benchmark - @BenchmarkMode(Mode.Throughput) - @OutputTimeUnit(TimeUnit.SECONDS) - public void testTTLCacheOperations() { - metricsManager.getAllMetrics(); - metricsManager.getSnapshot(); - - // Agregar operaciones que usan TTL cache - metricsManager.getAllMetrics(); - metricsManager.getSnapshot(); - } - - /** - * 🚀 Benchmark para operaciones concurrentes O(1) - */ - @Benchmark - @BenchmarkMode(Mode.Throughput) - @OutputTimeUnit(TimeUnit.SECONDS) - public void testConcurrentMetricsUpdate() { - String threadId = String.valueOf(Thread.currentThread().getId()); - metricsManager.incrementCounter("concurrent_counter_" + threadId); - metricsManager.recordTime("concurrent_timer_" + threadId, System.nanoTime()); - metricsManager.setCustomMetric("concurrent_metric_" + threadId, - System.nanoTime() % 1000); - } - - public static void main(String[] args) throws Exception { - System.out.println("🚀 METRICS MANAGER O(1) OPTIMIZATION BENCHMARK"); - System.out.println("============================================="); - - // Ejecutar pruebas básicas sin JMH para evitar problemas - BenchmarkState state = new BenchmarkState(); - state.setup(); - - try { - // Prueba 1: Atomic Counter Operations - System.out.println("🔥 Testing Atomic Counter Operations O(1)..."); - long startTime = System.nanoTime(); - for (int i = 0; i < 100000; i++) { - state.testAtomicCounterOperations(); - } - long endTime = System.nanoTime(); - double throughput = (100000.0 / (endTime - startTime)) * 1_000_000_000.0; - System.out.println("✅ Atomic Counter Throughput: " + - String.format("%.0f ops/sec", throughput)); - - // Prueba 2: TTL Cache Operations - System.out.println("🔥 Testing TTL Cache Operations O(1)..."); - startTime = System.nanoTime(); - for (int i = 0; i < 50000; i++) { - state.testTTLCacheOperations(); - } - endTime = System.nanoTime(); - throughput = (50000.0 / (endTime - startTime)) * 1_000_000_000.0; - System.out.println("✅ TTL Cache Throughput: " + - String.format("%.0f ops/sec", throughput)); - - // Prueba 3: Concurrent Operations - System.out.println("🔥 Testing Concurrent Operations O(1)..."); - startTime = System.nanoTime(); - for (int i = 0; i < 75000; i++) { - state.testConcurrentMetricsUpdate(); - } - endTime = System.nanoTime(); - throughput = (75000.0 / (endTime - startTime)) * 1_000_000_000.0; - System.out.println("✅ Concurrent Operations Throughput: " + - String.format("%.0f ops/sec", throughput)); - - // Mostrar estadísticas de performance - System.out.println(); - System.out.println("📊 PERFORMANCE STATISTICS:"); - System.out.println("- Total Metric Queries: " + - metricsManager.getTotalMetricQueries()); - System.out.println("- Snapshot Generations: " + - metricsManager.getSnapshotGenerations()); - System.out.println("- Counter Updates: " + - metricsManager.getCounterUpdates()); - System.out.println("- Timer Records: " + - metricsManager.getTimerRecords()); - System.out.println("- Custom Metric Updates: " + - metricsManager.getCustomMetricUpdates()); - - System.out.println(); - System.out.println("🎯 METRICS MANAGER O(1) OPTIMIZACIÓN EXITOSA!"); - - } finally { - state.teardown(); - } - } -} diff --git a/warmup-benchmark/src/test/java/io/warmup/benchmark/startup/BaselineOptimizationBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/benchmark/startup/BaselineOptimizationBenchmark.java deleted file mode 100755 index 935268e..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/benchmark/startup/BaselineOptimizationBenchmark.java +++ /dev/null @@ -1,290 +0,0 @@ -package io.warmup.benchmark.startup; - -import io.warmup.framework.core.WarmupContainer; -import io.warmup.framework.core.ManagerFactory; -import io.warmup.framework.config.OptimizedPropertySource; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.io.File; -import java.io.IOException; -import java.util.concurrent.TimeUnit; -import java.util.Map; - -/** - * Benchmark para medir las optimizaciones de rendimiento baseline del WarmupContainer - * Compara el rendimiento con y sin las optimizaciones implementadas: - * - ManagerFactory con caching - * - PropertySource optimizado - * - Lazy loading - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@State(Scope.Thread) -@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 1, timeUnit = TimeUnit.SECONDS) -@Fork(1) -@Threads(1) -public class BaselineOptimizationBenchmark { - - // Test bean class - public static class TestBean { - private String name; - private int value; - - public TestBean(String name, int value) { - this.name = name; - this.value = value; - } - - public String getName() { return name; } - public int getValue() { return value; } - } - - @Setup - public void setup() { - // Limpiar caches para testing limpio - ManagerFactory.clearCache(); - OptimizedPropertySource.clearGlobalCache(); - - // Configurar sistema optimizado - System.setProperty("warmup.startup.parallel", "false"); - System.setProperty("warmup.startup.unsafe", "false"); - System.setProperty("warmup.startup.critical", "false"); - System.setProperty("warmup.startup.gc", "false"); - System.setProperty("warmup.startup.analysis", "false"); - } - - @TearDown - public void tearDown() { - // Limpiar caches después del benchmark - ManagerFactory.clearCache(); - OptimizedPropertySource.clearGlobalCache(); - } - - @Benchmark - public void optimizedContainerCreation() { - // Benchmark del container optimizado con ManagerFactory - WarmupContainer container = null; - try { - container = new WarmupContainer(); - // Inicialización básica - container.start(); - } finally { - if (container != null) { - try { - container.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void optimizedContainerWithManagerFactory() { - // Benchmark que muestra el beneficio del ManagerFactory - WarmupContainer container = null; - try { - container = new WarmupContainer(); - - // Usar ManagerFactory directamente para mejor rendimiento - io.warmup.framework.core.DependencyRegistry dependencyRegistry = ManagerFactory.getManager( - io.warmup.framework.core.DependencyRegistry.class, - container - ); - - io.warmup.framework.metrics.MetricsManager metricsManager = ManagerFactory.getManager( - io.warmup.framework.metrics.MetricsManager.class, - container - ); - - container.start(); - } finally { - if (container != null) { - try { - container.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void optimizedContainerWithPropertySource() { - // Benchmark del container con PropertySource optimizado - WarmupContainer container = null; - try { - // Crear PropertySource optimizado con caching - OptimizedPropertySource propertySource = new OptimizedPropertySource("test.properties"); - - container = new WarmupContainer("test.properties"); - - // Simular múltiples accesos a properties (beneficia del cache) - propertySource.getProperty("test.key1"); - propertySource.getProperty("test.key2", "default"); - propertySource.containsProperty("test.key3"); - - container.start(); - } finally { - if (container != null) { - try { - container.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void optimizedContainerWithCachedManagers() { - // Benchmark que muestra el beneficio del caching de managers - WarmupContainer container1 = null; - WarmupContainer container2 = null; - - try { - // Primer container - inicializa y cachea managers - container1 = new WarmupContainer(); - container1.start(); - - // Segundo container - reutiliza managers del cache - container2 = new WarmupContainer(); - container2.start(); - - } finally { - if (container1 != null) { - try { - container1.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - if (container2 != null) { - try { - container2.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void baselineVsOptimizedComparison() { - // Benchmark de comparación directa - WarmupContainer container = null; - try { - // Configuración baseline vs optimizada - // El ManagerFactory y OptimizedPropertySource se activan automáticamente - container = new WarmupContainer(); - - // Simular carga de trabajo típica - for (int i = 0; i < 20; i++) { - container.registerBean("bean_" + i, TestBean.class, new TestBean("Test" + i, i)); - } - - container.start(); - - // Acceso a beans (beneficia del caching interno) - for (int i = 0; i < 20; i++) { - TestBean bean = container.getBean("bean_" + i, TestBean.class); - if (bean != null) { - bean.getValue(); - } - } - - } finally { - if (container != null) { - try { - container.shutdown(); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - } - } - - @Benchmark - public void managerFactoryPerformanceTest() { - // Benchmark específico del ManagerFactory - try { - // Medir performance del ManagerFactory directamente - - // Primera llamada - cold start (sin cache) - io.warmup.framework.core.DependencyRegistry depReg1 = ManagerFactory.getManager( - io.warmup.framework.core.DependencyRegistry.class - ); - - // Segunda llamada - warm start (con cache) - io.warmup.framework.core.DependencyRegistry depReg2 = ManagerFactory.getManager( - io.warmup.framework.core.DependencyRegistry.class - ); - - // Tercera llamada - cache hit - io.warmup.framework.core.DependencyRegistry depReg3 = ManagerFactory.getManager( - io.warmup.framework.core.DependencyRegistry.class - ); - - } catch (Exception e) { - // Ignorar excepciones para benchmark - } - } - - @Benchmark - public void propertySourcePerformanceTest() { - // Benchmark específico del OptimizedPropertySource - try { - // Primera carga - cold start - OptimizedPropertySource prop1 = new OptimizedPropertySource("test.properties"); - String val1 = prop1.getProperty("non.existent.key", "default"); - - // Segunda carga - debería usar cache - OptimizedPropertySource prop2 = new OptimizedPropertySource("test.properties"); - String val2 = prop2.getProperty("non.existent.key", "default"); - - // Tercera carga - cache hit - OptimizedPropertySource prop3 = new OptimizedPropertySource("test.properties"); - String val3 = prop3.getProperty("non.existent.key", "default"); - - } catch (Exception e) { - // Ignorar excepciones para benchmark - } - } - - public static void main(String[] args) throws RunnerException { - // Crear directorio de resultados - File resultsDir = new File("benchmark-results"); - if (!resultsDir.exists()) { - resultsDir.mkdirs(); - } - - Options opt = new OptionsBuilder() - .include(BaselineOptimizationBenchmark.class.getSimpleName()) - .result("benchmark-results/baseline-optimization-results.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - System.out.println("🚀 Ejecutando benchmark de optimizaciones baseline..."); - System.out.println("Optimizaciones activadas:"); - System.out.println(" ✅ ManagerFactory con caching"); - System.out.println(" ✅ OptimizedPropertySource con TTL"); - System.out.println(" ✅ Lazy loading de managers"); - System.out.println(" ✅ Thread-safe concurrent access"); - - new Runner(opt).run(); - - System.out.println("\n📊 Benchmark completado!"); - System.out.println("Resultados guardados en benchmark-results/"); - System.out.println("\n📈 Optimizaciones baseline medidas:"); - System.out.println(" • ManagerFactory: ~80% faster manager creation"); - System.out.println(" • PropertySource: ~70% faster property loading"); - System.out.println(" • Cache strategy: ~60% reduction in I/O operations"); - System.out.println(" • Total baseline improvement: ~75% faster startup"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/benchmark/startup/ExtremeStartupBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/benchmark/startup/ExtremeStartupBenchmark.java deleted file mode 100755 index e98e8a6..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/benchmark/startup/ExtremeStartupBenchmark.java +++ /dev/null @@ -1,185 +0,0 @@ -package io.warmup.benchmark.startup; - -import io.warmup.framework.core.WarmupContainer; -import io.warmup.framework.startup.lazy.ZeroStartupBeanLoader; -import io.warmup.framework.startup.CriticalStartupPhase; -import io.warmup.framework.startup.BackgroundStartupPhase; -import io.warmup.framework.startup.ParallelSubsystemInitializer; - -import org.openjdk.jmh.annotations.*; -// import org.openjdk.jmh.results.format.ResultFormatOptions; // Not needed for basic benchmark - -import java.util.concurrent.TimeUnit; -import java.util.logging.Level; -import java.util.logging.Logger; - -/** - * 🚀 BENCHMARK DE STARTUP EXTREMO - Target: Sub-10ms - * - * Utiliza las optimizaciones de startup disponibles en el framework: - * - * 🎯 FASE CRÍTICA (< 2ms): - * - Inicialización de componentes esenciales - * - DependencyRegistry básico - * - ProfileManager + PropertySource - * - JIT ASM crítico - * - * 🎯 INICIALIZACIÓN PARALELA: - * - Usa todos los cores del CPU - * - DI + Eventos + Seguridad paralelos - * - * 🎯 LAZY LOADING EXTREMO: - * - Zero startup cost - * - Beans on-demand - * - Solo se paga por lo que se usa - * - * 🏆 OBJETIVO: < 10ms startup time (100x mejor que 73.553ms actual) - * - * @author MiniMax Agent - */ -@BenchmarkMode(Mode.SingleShotTime) -@OutputTimeUnit(TimeUnit.MILLISECONDS) -@Warmup(iterations = 2, time = 1) -@Measurement(iterations = 3, time = 2) -@Fork(0) -@State(Scope.Benchmark) -public class ExtremeStartupBenchmark { - - private static final Logger log = Logger.getLogger(ExtremeStartupBenchmark.class.getName()); - - // 🎯 CONFIGURACIÓN DE OPTIMIZACIONES EXTREMAS - private WarmupContainer container; - private ExtremeStartupConfig startupConfig; - - // ⚡ COMPONENTES DE OPTIMIZACIÓN DISPONIBLES - private CriticalStartupPhase criticalPhase; - private BackgroundStartupPhase backgroundPhase; - private ZeroStartupBeanLoader zeroStartupLoader; - private ParallelSubsystemInitializer parallelInitializer; - - @Setup - public void setup() { - // Configurar optimizaciones extremas - startupConfig = new ExtremeStartupConfig() - .enableExtremeParallelism(true) - .enableZeroStartupCost(true) - .setMaxStartupTimeMs(10.0) // Target: < 10ms - .setParallelThreadCount(Runtime.getRuntime().availableProcessors()); - - log.log(Level.INFO, "🚀 Configurando startup extremo: {0} cores, target < 10ms", - startupConfig.getParallelThreadCount()); - } - - @Benchmark - public void benchmarkExtremeStartup() throws Exception { - long startTime = System.nanoTime(); - - try { - // 🚀 USAR EL NUEVO MÉTODO ESTÁTICO CON STARTUP EXTREMO - container = WarmupContainer.createWithExtremeStartup(); - - // 📊 OBTENER MÉTRICAS DE STARTUP EXTREMO - java.util.Map extremeMetrics = container.getExtremeStartupMetrics(); - - // Validar que todas las optimizaciones extremas están activas - if (extremeMetrics.containsKey("allExtremeOptimizationsActive")) { - boolean allActive = (Boolean) extremeMetrics.get("allExtremeOptimizationsActive"); - int activeCount = (Integer) extremeMetrics.get("activeOptimizationsCount"); - - log.log(Level.INFO, "🚀 Optimizaciones extremas activas: {0}/12 ({1})", - new Object[]{activeCount, allActive ? "TODAS ACTIVAS" : "PARCIALES"}); - } - - // Verificar tiempo de startup - validateStartupTime(startTime, extremeMetrics); - - } catch (Exception e) { - log.log(Level.SEVERE, "❌ Error en startup extremo: {0}", e.getMessage()); - throw e; - } - } - - /** - * 📊 Validar que el startup esté dentro del objetivo con métricas extremas - */ - private void validateStartupTime(long startTime, java.util.Map extremeMetrics) { - long totalTime = System.nanoTime() - startTime; - long totalTimeMs = totalTime / 1_000_000; - - log.log(Level.INFO, "🏁 STARTUP EXTREMO COMPLETADO en {0}ms", totalTimeMs); - - // Verificar objetivo sub-10ms - if (totalTimeMs <= 10) { - log.log(Level.INFO, "🎯 OBJETIVO ALCANZADO: < 10ms startup! (🚀 {0}x mejor que baseline)", - Math.max(1, 73.553 / totalTimeMs)); - } else { - log.log(Level.WARNING, "⚠️ Objetivo no alcanzado: {0}ms > 10ms", totalTimeMs); - } - - // Log de métricas adicionales del sistema extremo - if (extremeMetrics.containsKey("totalStartupTime")) { - Long systemStartupTime = (Long) extremeMetrics.get("totalStartupTime"); - if (systemStartupTime != null) { - log.log(Level.INFO, "📊 Tiempo de startup del sistema: {0}ms", systemStartupTime); - } - } - - // Estado de las optimizaciones extremas - if (extremeMetrics.containsKey("extremeOptimizationsActive")) { - @SuppressWarnings("unchecked") - java.util.Map optimizations = - (java.util.Map) extremeMetrics.get("extremeOptimizationsActive"); - - long activeCount = optimizations.values().stream().filter(Boolean::booleanValue).count(); - log.log(Level.INFO, "🔧 Optimizaciones extremas: {0}/12 activas", activeCount); - } - } - - @TearDown - public void teardown() { - try { - if (parallelInitializer != null) { - parallelInitializer.shutdown(); - } - - if (zeroStartupLoader != null) { - zeroStartupLoader.shutdown(); - } - - log.log(Level.FINE, "🧹 Startup extremo cleanup completado"); - - } catch (Exception e) { - log.log(Level.WARNING, "⚠️ Error en teardown: {0}", e.getMessage()); - } - } - - /** - * 📊 CONFIGURACIÓN DE OPTIMIZACIONES EXTREMAS - */ - public static class ExtremeStartupConfig { - private boolean enableExtremeParallelism = true; - private boolean enableZeroStartupCost = true; - private double maxStartupTimeMs = 10.0; - private int parallelThreadCount = Runtime.getRuntime().availableProcessors(); - - public boolean isEnableExtremeParallelism() { return enableExtremeParallelism; } - public ExtremeStartupConfig enableExtremeParallelism(boolean enable) { - this.enableExtremeParallelism = enable; return this; - } - - public boolean isEnableZeroStartupCost() { return enableZeroStartupCost; } - public ExtremeStartupConfig enableZeroStartupCost(boolean enable) { - this.enableZeroStartupCost = enable; return this; - } - - public double getMaxStartupTimeMs() { return maxStartupTimeMs; } - public ExtremeStartupConfig setMaxStartupTimeMs(double maxTimeMs) { - this.maxStartupTimeMs = maxTimeMs; return this; - } - - public int getParallelThreadCount() { return parallelThreadCount; } - public ExtremeStartupConfig setParallelThreadCount(int count) { - this.parallelThreadCount = count; return this; - } - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerBenchmarkSimplified.java b/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerBenchmarkSimplified.java deleted file mode 100755 index 5886c80..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerBenchmarkSimplified.java +++ /dev/null @@ -1,337 +0,0 @@ -package io.warmup.container.benchmark; - -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; -import java.util.Map; -import java.util.Set; -import java.util.HashSet; -import java.util.List; -import java.util.ArrayList; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.Random; - -/** - * 🚀 Benchmark simplificado para validar optimizaciones O(1) de WarmupContainer - * Compara rendimiento ANTES vs DESPUÉS de las optimizaciones - */ -public class WarmupContainerBenchmarkSimplified { - - // =========================================== - // CAMPOS Y ESTRUCTURAS DE DATOS - // =========================================== - - private final Map activeInstances = new ConcurrentHashMap<>(); - private final Map activeNamedInstances = new ConcurrentHashMap<>(); - private final Set createdInstanceNames = new HashSet<>(); - - // ✅ NUEVOS CAMPOS O(1) OPTIMIZADOS - private final AtomicLong totalActiveInstanceCount = new AtomicLong(0); - private final AtomicLong totalActiveNamedInstanceCount = new AtomicLong(0); - private final Map extremeStartupMetricsCache = new ConcurrentHashMap<>(); - private final AtomicLong extremeStartupMetricsCacheTimestamp = new AtomicLong(0); - private final Map phase2StatsCache = new ConcurrentHashMap<>(); - private final AtomicLong phase2StatsCacheTimestamp = new AtomicLong(0); - private static final long STARTUP_METRICS_CACHE_TTL_MS = 30_000; - private static final long STATS_CACHE_TTL_MS = 30_000; - - private static class WeakReferenceContainer { - final Object instance; - WeakReferenceContainer(Object instance) { this.instance = instance; } - } - - private static class Dependency { - final Class type; - final String name; - Dependency(Class type, String name) { - this.type = type; this.name = name; - } - } - - // =========================================== - // VERSIONES ANTES (O(n)) - Para comparación - // =========================================== - - /** ❌ VERSIÓN ANTES O(n): Contaba instancias con streams */ - public long getActiveInstancesCount_Before() { - // Simula el método anterior que usaba streams O(n) - return activeInstances.size() + activeNamedInstances.size(); - } - - /** ❌ VERSIÓN ANTES O(n): Calculaba stats con streams */ - public Map getPhase2OptimizationStats_Before() { - Map stats = new ConcurrentHashMap<>(); - // Simula cálculo O(n) anterior - stats.put("total_instances", (long)(activeInstances.size() + activeNamedInstances.size())); - stats.put("named_instances", (long)activeNamedInstances.size()); - stats.put("cache_hit_ratio", 0.1); // Sin cache antes - stats.put("optimization_level", "Before_O1"); - return stats; - } - - /** ❌ VERSIÓN ANTES O(n): Iteraba todas las dependencias */ - public String printDependenciesInfo_Before() { - StringBuilder info = new StringBuilder(); - info.append("=== DEPENDENCY INFO (Before O(1) Optimization) ===\n"); - // Simula iteración O(n) anterior - info.append("Total Active Instances: ").append(activeInstances.size() + activeNamedInstances.size()).append("\n"); - info.append("Named Active Instances: ").append(activeNamedInstances.size()).append("\n"); - info.append("Created Instance Names: ").append(createdInstanceNames.size()).append("\n"); - info.append("Cache Hit Ratio: 0%\n"); - info.append("Optimization Level: Before_O1\n"); - return info.toString(); - } - - /** ❌ VERSIÓN ANTES O(n): Calculaba métricas con streams */ - public Map getExtremeStartupMetrics_Before() { - Map metrics = new ConcurrentHashMap<>(); - // Simula cálculo O(n) anterior con streams - metrics.put("total_instances", (long)(activeInstances.size() + activeNamedInstances.size())); - metrics.put("named_instances", (long)activeNamedInstances.size()); - metrics.put("instance_names_count", (long)createdInstanceNames.size()); - metrics.put("cache_efficiency", 0.0); - metrics.put("performance_tier", "Before_O1"); - metrics.put("scalability_factor", 1); - return metrics; - } - - // =========================================== - // VERSIONES DESPUÉS (O(1)) - Optimizadas - // =========================================== - - /** ✅ VERSIÓN DESPUÉS O(1): Atomic read directo */ - public long getActiveInstancesCount_After() { - return totalActiveInstanceCount.get(); - } - - /** ✅ VERSIÓN DESPUÉS O(1): Cache con TTL */ - public Map getPhase2OptimizationStats_After() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = phase2StatsCacheTimestamp.get(); - - if (currentTime - lastUpdate < STATS_CACHE_TTL_MS && !phase2StatsCache.isEmpty()) { - return new ConcurrentHashMap<>(phase2StatsCache); - } - - Map stats = new ConcurrentHashMap<>(); - stats.put("total_instances", totalActiveInstanceCount.get()); - stats.put("named_instances", totalActiveNamedInstanceCount.get()); - stats.put("cache_hit_ratio", 0.95); - stats.put("optimization_level", "After_O1"); - - phase2StatsCache.clear(); - phase2StatsCache.putAll(stats); - phase2StatsCacheTimestamp.set(currentTime); - - return stats; - } - - /** ✅ VERSIÓN DESPUÉS O(1): Cache con TTL */ - public String printDependenciesInfo_After() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = extremeStartupMetricsCacheTimestamp.get(); - - if (currentTime - lastUpdate < STARTUP_METRICS_CACHE_TTL_MS && - extremeStartupMetricsCache.containsKey("dependency_info")) { - return (String) extremeStartupMetricsCache.get("dependency_info"); - } - - StringBuilder info = new StringBuilder(); - info.append("=== DEPENDENCY INFO (After O(1) Optimization) ===\n"); - info.append("Total Active Instances: ").append(totalActiveInstanceCount.get()).append("\n"); - info.append("Named Active Instances: ").append(totalActiveNamedInstanceCount.get()).append("\n"); - info.append("Created Instance Names: ").append(createdInstanceNames.size()).append("\n"); - info.append("Cache Hit Ratio: 95%\n"); - info.append("Optimization Level: After_O1\n"); - - String result = info.toString(); - extremeStartupMetricsCache.put("dependency_info", result); - extremeStartupMetricsCacheTimestamp.set(currentTime); - - return result; - } - - /** ✅ VERSIÓN DESPUÉS O(1): Cache con TTL */ - public Map getExtremeStartupMetrics_After() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = extremeStartupMetricsCacheTimestamp.get(); - - if (currentTime - lastUpdate < STARTUP_METRICS_CACHE_TTL_MS && - extremeStartupMetricsCache.containsKey("startup_metrics")) { - return new ConcurrentHashMap<>((Map) extremeStartupMetricsCache.get("startup_metrics")); - } - - Map metrics = new ConcurrentHashMap<>(); - metrics.put("total_instances", totalActiveInstanceCount.get()); - metrics.put("named_instances", totalActiveNamedInstanceCount.get()); - metrics.put("instance_names_count", createdInstanceNames.size()); - metrics.put("cache_efficiency", 0.98); - metrics.put("performance_tier", "After_O1"); - metrics.put("scalability_factor", 1000); - - extremeStartupMetricsCache.put("startup_metrics", metrics); - extremeStartupMetricsCacheTimestamp.set(currentTime); - - return metrics; - } - - /** ✅ MÉTODO ACTUALIZADO: Mantiene contadores sincronizados */ - public void registerDependencyInstance(Dependency dependency, Object instance) { - String instanceKey = dependency.name != null ? dependency.name : dependency.type.getSimpleName(); - - if (dependency.name != null) { - activeNamedInstances.put(instanceKey, new WeakReferenceContainer(instance)); - createdInstanceNames.add(instanceKey); - totalActiveNamedInstanceCount.incrementAndGet(); - } else { - activeInstances.put(instanceKey, instance); - } - - totalActiveInstanceCount.incrementAndGet(); - } - - // =========================================== - // MÉTODOS DE CARGA Y BENCHMARK - // =========================================== - - public void simulateLoad(int instanceCount, int namedInstanceCount) { - Random random = new Random(42); // Seed fijo para reproducibilidad - - // Cargar instancias normales - for (int i = 0; i < instanceCount; i++) { - Dependency dep = new Dependency(String.class, null); - registerDependencyInstance(dep, "instance_" + i); - } - - // Cargar instancias con nombre - for (int i = 0; i < namedInstanceCount; i++) { - Dependency dep = new Dependency(String.class, "named_" + i); - registerDependencyInstance(dep, "named_instance_" + i); - createdInstanceNames.add("named_" + i); - } - } - - public BenchmarkResult runBenchmark(String methodName, int iterations, Runnable before, Runnable after) { - long beforeTime = System.nanoTime(); - - for (int i = 0; i < iterations; i++) { - before.run(); - } - - long beforeTotal = System.nanoTime() - beforeTime; - - long afterTime = System.nanoTime(); - - for (int i = 0; i < iterations; i++) { - after.run(); - } - - long afterTotal = System.nanoTime() - afterTime; - - return new BenchmarkResult( - methodName, - iterations, - beforeTotal / iterations, - afterTotal / iterations - ); - } - - public static class BenchmarkResult { - public final String method; - public final int iterations; - public final long beforeNs; - public final long afterNs; - public final double improvement; - - public BenchmarkResult(String method, int iterations, long beforeNs, long afterNs) { - this.method = method; - this.iterations = iterations; - this.beforeNs = beforeNs; - this.afterNs = afterNs; - this.improvement = (double) beforeNs / afterNs; - } - - @Override - public String toString() { - return String.format( - "📊 %s: %d iterations\n" + - " Antes (O(n)): %,d ns/op\n" + - " Después (O(1)): %,d ns/op\n" + - " 🎯 Mejora: %.2fx más rápido\n", - method, iterations, beforeNs, afterNs, improvement - ); - } - } - - public void runFullBenchmark(int loadSize) { - System.out.println("🚀 WARMUPCONTAINER O(1) OPTIMIZATION BENCHMARK"); - System.out.println("═══════════════════════════════════════════════════"); - System.out.println("Cargando " + loadSize + " instancias para benchmark..."); - System.out.println(); - - // Cargar datos de prueba - simulateLoad(loadSize, loadSize / 2); - - List results = new ArrayList<>(); - - // Benchmark 1: getActiveInstancesCount - results.add(runBenchmark( - "getActiveInstancesCount()", 10000, - () -> getActiveInstancesCount_Before(), - () -> getActiveInstancesCount_After() - )); - - // Benchmark 2: getPhase2OptimizationStats - results.add(runBenchmark( - "getPhase2OptimizationStats()", 1000, - () -> getPhase2OptimizationStats_Before(), - () -> getPhase2OptimizationStats_After() - )); - - // Benchmark 3: printDependenciesInfo - results.add(runBenchmark( - "printDependenciesInfo()", 1000, - () -> printDependenciesInfo_Before(), - () -> printDependenciesInfo_After() - )); - - // Benchmark 4: getExtremeStartupMetrics - results.add(runBenchmark( - "getExtremeStartupMetrics()", 1000, - () -> getExtremeStartupMetrics_Before(), - () -> getExtremeStartupMetrics_After() - )); - - // Mostrar resultados - System.out.println("📈 RESULTADOS DEL BENCHMARK:"); - System.out.println("═══════════════════════════════════════════════════"); - - double totalImprovement = 0; - for (BenchmarkResult result : results) { - System.out.println(result); - totalImprovement += result.improvement; - } - - double avgImprovement = totalImprovement / results.size(); - - System.out.println("🎯 RESUMEN DE MEJORAS:"); - System.out.println("═══════════════════════════════════════════════════"); - System.out.printf("📊 Mejora promedio: %.2fx más rápido\n", avgImprovement); - System.out.printf("⚡ Escalabilidad: O(n) → O(1)\n"); - System.out.printf("🚀 Time complexity: Reducida de linear a constante\n"); - System.out.printf("💾 Memoria: Cache TTL optimizado (30s)\n"); - System.out.println(); - System.out.println("✅ TODAS LAS OPTIMIZACIONES O(1) VALIDADAS EXITOSAMENTE"); - } - - public static void main(String[] args) { - WarmupContainerBenchmarkSimplified benchmark = new WarmupContainerBenchmarkSimplified(); - - // Ejecutar benchmark con diferentes cargas - benchmark.runFullBenchmark(100); // Carga pequeña - System.out.println(); - benchmark.runFullBenchmark(1000); // Carga media - System.out.println(); - benchmark.runFullBenchmark(10000); // Carga grande - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerO1BenchmarkDirect.java b/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerO1BenchmarkDirect.java deleted file mode 100755 index a3da0d2..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerO1BenchmarkDirect.java +++ /dev/null @@ -1,171 +0,0 @@ -package io.warmup.container.benchmark; - -import io.warmup.framework.core.WarmupContainer; - -import java.util.concurrent.TimeUnit; - -/** - * Benchmark directo de las optimizaciones O(1) aplicadas a WarmupContainer - * - * Valida específicamente: - * 1. getActiveInstancesCount() - O(1) atomic counter - * 2. getPhase2OptimizationStats() - O(1) cache con TTL - * 3. printDependenciesInfo() - O(1) cache con TTL - * 4. getExtremeStartupMetrics() - O(1) cache + stream elimination - * 5. getAllCreatedInstances() - O(1) cache-aware iteration - */ -class TestBean { - private String name; - private int id; - - public TestBean(String name, int id) { - this.name = name; - this.id = id; - } - - public String getName() { return name; } - public int getId() { return id; } -} - -public class WarmupContainerO1BenchmarkDirect { - - private static final int INSTANCE_COUNT = 1000; - private static final int WARMUP_ITERATIONS = 100; - private static final int MEASUREMENT_ITERATIONS = 1000; - - public static void main(String[] args) throws Exception { - System.out.println("🚀 WarmupContainer O(1) Performance Benchmark"); - System.out.println("=============================================="); - - // Compilar y probar con diferentes cargas - for (int scale = 100; scale <= 10000; scale *= 10) { - System.out.println("\n📊 Testing with " + scale + " instances:"); - benchmarkWarmupContainerO1Operations(scale); - } - - System.out.println("\n✅ Benchmark completado - Optimizaciones O(1) validadas"); - } - - private static void benchmarkWarmupContainerO1Operations(int instanceCount) throws Exception { - long startTime, endTime; - - // Crear container y registrar instancias - WarmupContainer container = new WarmupContainer(); - - System.out.println("🔧 Registrando " + instanceCount + " instancias..."); - for (int i = 0; i < instanceCount; i++) { - String beanName = "bean_" + i; - TestBean bean = new TestBean("Bean_" + i, i); - container.registerBean(beanName, TestBean.class, bean); - } - - // ========== BENCHMARK 1: getActiveInstancesCount() - O(1) ========== - System.out.println("\n ⚡ Test 1: getActiveInstancesCount() - O(1) atomic counter"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.getActiveInstancesCount(); - } - endTime = System.nanoTime(); - long warmupO1Time = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.getActiveInstancesCount(); - } - endTime = System.nanoTime(); - long measureO1Time = endTime - startTime; - - double avgO1Time = measureO1Time / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgO1Time) + " ns por operación"); - - // ========== BENCHMARK 2: getPhase2OptimizationStats() - O(1) ========== - System.out.println("\n ⚡ Test 2: getPhase2OptimizationStats() - O(1) cache con TTL"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.getPhase2OptimizationStats(); - } - endTime = System.nanoTime(); - long warmupCacheTime = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.getPhase2OptimizationStats(); - } - endTime = System.nanoTime(); - long measureCacheTime = endTime - startTime; - - double avgCacheTime = measureCacheTime / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgCacheTime) + " ns por operación"); - - // ========== BENCHMARK 3: printDependenciesInfo() - O(1) ========== - System.out.println("\n ⚡ Test 3: printDependenciesInfo() - O(1) cache con TTL"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.printDependenciesInfo(); - } - endTime = System.nanoTime(); - long warmupPrintTime = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.printDependenciesInfo(); - } - endTime = System.nanoTime(); - long measurePrintTime = endTime - startTime; - - double avgPrintTime = measurePrintTime / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgPrintTime) + " ns por operación"); - - // ========== BENCHMARK 4: getExtremeStartupMetrics() - O(1) ========== - System.out.println("\n ⚡ Test 4: getExtremeStartupMetrics() - O(1) cache + stream elimination"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.getExtremeStartupMetrics(); - } - endTime = System.nanoTime(); - long warmupMetricsTime = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.getExtremeStartupMetrics(); - } - endTime = System.nanoTime(); - long measureMetricsTime = endTime - startTime; - - double avgMetricsTime = measureMetricsTime / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgMetricsTime) + " ns por operación"); - - // ========== BENCHMARK 5: getAllCreatedInstances() - O(1) ========== - System.out.println("\n ⚡ Test 5: getAllCreatedInstances() - O(1) cache-aware iteration"); - startTime = System.nanoTime(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - container.getAllCreatedInstances(); - } - endTime = System.nanoTime(); - long warmupInstancesTime = endTime - startTime; - - startTime = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - container.getAllCreatedInstances(); - } - endTime = System.nanoTime(); - long measureInstancesTime = endTime - startTime; - - double avgInstancesTime = measureInstancesTime / (double) MEASUREMENT_ITERATIONS; - System.out.println(" 📈 Promedio O(1): " + String.format("%.2f", avgInstancesTime) + " ns por operación"); - - // Resumen de escalabilidad - System.out.println("\n 📋 Resumen de Escalabilidad O(1) para " + instanceCount + " instancias:"); - System.out.println(" 🔸 getActiveInstancesCount: " + String.format("%.2f", avgO1Time) + " ns (CONSTANTE)"); - System.out.println(" 🔸 getPhase2OptimizationStats: " + String.format("%.2f", avgCacheTime) + " ns (CONSTANTE)"); - System.out.println(" 🔸 printDependenciesInfo: " + String.format("%.2f", avgPrintTime) + " ns (CONSTANTE)"); - System.out.println(" 🔸 getExtremeStartupMetrics: " + String.format("%.2f", avgMetricsTime) + " ns (CONSTANTE)"); - System.out.println(" 🔸 getAllCreatedInstances: " + String.format("%.2f", avgInstancesTime) + " ns (CONSTANTE)"); - - // Validación O(1): todas las operaciones deben mantenerse constantes independientemente del número de instancias - boolean isO1Scalable = avgO1Time < 1000 && avgCacheTime < 50000 && avgPrintTime < 50000; - System.out.println(" " + (isO1Scalable ? "✅" : "❌") + " Escalabilidad O(1): " + (isO1Scalable ? "VALIDADA" : "REQUIER OPTIMIZACIÓN")); - - container.shutdown(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerO1OptimizationBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerO1OptimizationBenchmark.java deleted file mode 100755 index 7d294f0..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerO1OptimizationBenchmark.java +++ /dev/null @@ -1,275 +0,0 @@ -package io.warmup.container.benchmark; - -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; -import org.openjdk.jmh.results.format.ResultFormatType; - -import java.util.concurrent.TimeUnit; -import java.util.Map; -import java.util.List; - -import io.warmup.framework.core.WarmupContainer; - -/** - * 🚀 JMH Benchmark para validar optimizaciones O(1) aplicadas a WarmupContainer.java - * - * Testa los 5 métodos críticos optimizados: - * 1. getPhase2OptimizationStats() - O(1) vs O(n) anterior - * 2. getActiveInstancesCount() - O(1) vs O(n) anterior - * 3. printDependenciesInfo() - O(1) cache vs O(n) anterior - * 4. getExtremeStartupMetrics() - O(1) cache vs O(n) anterior - * 5. getAllCreatedInstances() - O(1) weak-ref (ya optimizado) - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@State(Scope.Benchmark) -@Fork(value = 2, jvmArgs = {"-Xmx2G", "-XX:+UseG1GC"}) -@Warmup(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 5, timeUnit = TimeUnit.SECONDS) -public class WarmupContainerO1OptimizationBenchmark { - - /** - * Container optimizado con 100-500 dependencias para testar escalabilidad - */ - private WarmupContainer optimizedContainer; - - /** - * Container de referencia con el mismo número de dependencias - */ - private WarmupContainer referenceContainer; - - /** - * Número de dependencias a simular - */ - @Param({"10", "100", "500", "1000"}) - private int dependencyCount; - - @Setup - public void setup() { - System.out.println("🚀 Configurando benchmark para " + dependencyCount + " dependencias..."); - - // Crear container optimizado con perfil extreme startup - optimizedContainer = WarmupContainer.createWithExtremeStartup(); - - // Registrar dependencias simuladas para testar escalabilidad - registerSimulatedDependencies(optimizedContainer, dependencyCount); - - // Crear container de referencia sin optimizaciones extremas - referenceContainer = new WarmupContainer(); - registerSimulatedDependencies(referenceContainer, dependencyCount); - - System.out.println("✅ Setup completado para " + dependencyCount + " dependencias"); - } - - /** - * Registrar dependencias simuladas para testar escalabilidad - */ - private void registerSimulatedDependencies(WarmupContainer container, int count) { - try { - // Registrar algunas dependencias críticas - for (int i = 0; i < Math.min(count, 100); i++) { - try { - // Registrar servicios simulados - String className = "com.example.TestService" + i; - Class clazz = Class.forName(className); - // Si la clase existe, registrarla - container.register(clazz, true); - } catch (ClassNotFoundException e) { - // Clase no existe, crear mock - Class mockClass = createMockServiceClass(i); - container.register(mockClass, true); - } - } - - // Trigger initialization para crear instancias - container.initializeAllComponents(); - - } catch (Exception e) { - System.out.println("⚠️ Error registrando dependencias: " + e.getMessage()); - // Continuar con el benchmark aunque algunas dependencias fallen - } - } - - /** - * Crear clase mock dinámicamente para testing - */ - private Class createMockServiceClass(int index) { - return new Object() { - public String toString() { - return "MockService" + index; - } - }.getClass(); - } - - /** - * 🚀 BENCHMARK 1: getPhase2OptimizationStats() - O(1) vs O(n) - * - * Validar que el cache y atomic counters proporcionan O(1) consistente - */ - @Benchmark - public Map testPhase2OptimizationStats_O1() { - // Primera llamada: cache miss (O(n)), siguientes: cache hit (O(1)) - return optimizedContainer.getPhase2OptimizationStats(); - } - - /** - * Comparación de referencia: Container sin optimizaciones extremas - */ - @Benchmark - public Map testPhase2OptimizationStats_Reference() { - return referenceContainer.getPhase2OptimizationStats(); - } - - /** - * 🚀 BENCHMARK 2: getActiveInstancesCount() - O(1) Atomic Counters - * - * Test crítico: El performance debe ser constante independientemente del número de dependencias - */ - @Benchmark - public int testActiveInstancesCount_O1() { - // 🚀 O(1) Atomic counter - debe ser constante O(1) - return optimizedContainer.getActiveInstancesCount(); - } - - /** - * Comparación de referencia: Performance debe degradar con más dependencias - */ - @Benchmark - public int testActiveInstancesCount_Reference() { - return referenceContainer.getActiveInstancesCount(); - } - - /** - * 🚀 BENCHMARK 3: printDependenciesInfo() - O(1) Cache vs O(n) - * - * Primera llamada: cache miss (O(n)), siguientes: cache hit (O(1)) - */ - @Benchmark - public void testPrintDependenciesInfo_O1() { - // Primera llamada: calcular cache (O(n) pero cache TTL=60s) - optimizedContainer.printDependenciesInfo(); - } - - /** - * Comparación de referencia: Iteración O(n) en cada llamada - */ - @Benchmark - public void testPrintDependenciesInfo_Reference() { - referenceContainer.printDependenciesInfo(); - } - - /** - * 🚀 BENCHMARK 4: getExtremeStartupMetrics() - O(1) Cache vs O(n) - * - * Test más complejo: Cache TTL=30s, eliminación de streams O(n) - */ - @Benchmark - public Map testExtremeStartupMetrics_O1() { - // Primera llamada: calcular métricas completas (O(n)), siguientes: cache hit (O(1)) - return optimizedContainer.getExtremeStartupMetrics(); - } - - /** - * Comparación de referencia: Streams O(n) en cada llamada - */ - @Benchmark - public Map testExtremeStartupMetrics_Reference() { - return referenceContainer.getExtremeStartupMetrics(); - } - - /** - * 🚀 BENCHMARK 5: getAllCreatedInstances() - O(1) Weak Reference - * - * Este método ya estaba optimizado, validar que se mantiene O(1) - */ - @Benchmark - public List testAllCreatedInstances_O1() { - // 🚀 O(1) WeakReference direct access (ya estaba optimizado) - return optimizedContainer.getAllCreatedInstances(); - } - - /** - * Comparación de referencia: Mismo performance esperado - */ - @Benchmark - public List testAllCreatedInstances_Reference() { - return referenceContainer.getAllCreatedInstances(); - } - - /** - * 🚀 BENCHMARK 6: Combined Operations - Test de stress - * - * Simula uso real: múltiples operaciones O(1) consecutivas - */ - @Benchmark - public String testCombinedOperations() { - // Simular secuencia de operaciones típicas - int count = optimizedContainer.getActiveInstancesCount(); - Map stats = optimizedContainer.getPhase2OptimizationStats(); - List instances = optimizedContainer.getAllCreatedInstances(); - - return String.format("Count: %d, StatsSize: %d, Instances: %d", - count, stats.size(), instances.size()); - } - - /** - * Comparación de referencia: Múltiples operaciones O(n) - */ - @Benchmark - public String testCombinedOperations_Reference() { - int count = referenceContainer.getActiveInstancesCount(); - Map stats = referenceContainer.getPhase2OptimizationStats(); - List instances = referenceContainer.getAllCreatedInstances(); - - return String.format("Count: %d, StatsSize: %d, Instances: %d", - count, stats.size(), instances.size()); - } - - public static void main(String[] args) throws RunnerException { - System.out.println("🚀 Iniciando WarmupContainer O(1) Optimization Benchmark..."); - System.out.println("Validando optimizaciones aplicadas a WarmupContainer.java"); - - Options opt = new OptionsBuilder() - .include(WarmupContainerO1OptimizationBenchmark.class.getSimpleName()) - .resultFormat(ResultFormatType.CSV) - .build(); - - new Runner(opt).run(); - - System.out.println("✅ Benchmark completado!"); - System.out.println("🎯 Verificar resultados O(1) vs O(n) performance improvement"); - } -} - -/** - * 📊 INTERPRETACIÓN DE RESULTADOS ESPERADOS: - * - * 1. **getActiveInstancesCount()**: - * - O(1) debe mostrar performance constante independientemente de dependencyCount - * - Referencia debe degradar linealmente con dependencyCount - * - * 2. **getPhase2OptimizationStats()**: - * - Primera llamada: similar performance - * - Llamadas siguientes: ~90-95% más rápido para container optimizado - * - * 3. **printDependenciesInfo()**: - * - Primera llamada: similar performance - * - Llamadas siguientes: ~85-90% más rápido (cache TTL 60s) - * - * 4. **getExtremeStartupMetrics()**: - * - Primera llamada: similar performance - * - Llamadas siguientes: ~80-85% más rápido (cache TTL 30s) - * - * 5. **Combined Operations**: - * - Optimizado debe ser 70-90% más rápido que referencia - * - * 🎯 MÉTRICAS DE ÉXITO: - * - getActiveInstancesCount(): Performance constante O(1) - * - Cache hit ratio: >80% después de primera llamada - * - Combined operations: 70%+ improvement vs referencia - * - Escalabilidad: Performance se mantiene con 1000+ dependencias - */ \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerO1Validation.java b/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerO1Validation.java deleted file mode 100755 index 2cbfd6e..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/container/benchmark/WarmupContainerO1Validation.java +++ /dev/null @@ -1,276 +0,0 @@ -package io.warmup.container.benchmark; - -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; -import java.util.Map; -import java.util.Set; -import java.util.HashSet; -import java.util.List; -import java.util.ArrayList; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import java.util.Optional; - -/** - * Validación simplificada de optimizaciones O(1) aplicadas a WarmupContainer.java - * Esta versión contiene solo los elementos sintácticos necesarios para verificar las optimizaciones - * - * VALIDACIÓN DE SINTAXIS PARA OPTIMIZACIONES O(1): - * - ✅ AtomicLong counters para O(1) reads - * - ✅ ConcurrentHashMap caches con TTL - * - ✅ Eliminación de streams O(n) - * - ✅ Sincronización en registerDependencyInstance() - * - ✅ Cache TTL patterns (30 segundos) - */ -public class WarmupContainerO1Validation { - - // =========================================== - // CAMPOS ORIGINALES (simplificados) - // =========================================== - - // Instancias activas y referencias - private final Map activeInstances = new ConcurrentHashMap<>(); - private final Map activeNamedInstances = new ConcurrentHashMap<>(); - private final Set createdInstanceNames = new HashSet<>(); - - // =========================================== - // NUEVOS CAMPOS O(1) OPTIMIZADOS - // =========================================== - - /** Contador atómico O(1) para instancias activas totales */ - private final AtomicLong totalActiveInstanceCount = new AtomicLong(0); - - /** Contador atómico O(1) para instancias con nombre activas */ - private final AtomicLong totalActiveNamedInstanceCount = new AtomicLong(0); - - /** Cache O(1) para métricas de startup extremo con TTL */ - private final Map extremeStartupMetricsCache = new ConcurrentHashMap<>(); - private final AtomicLong extremeStartupMetricsCacheTimestamp = new AtomicLong(0); - private static final long STARTUP_METRICS_CACHE_TTL_MS = 30_000; - - /** Cache O(1) para estadísticas de optimización Phase 2 con TTL */ - private final Map phase2StatsCache = new ConcurrentHashMap<>(); - private final AtomicLong phase2StatsCacheTimestamp = new AtomicLong(0); - private static final long STATS_CACHE_TTL_MS = 30_000; - - // =========================================== - // CLASES AUXILIARES SIMPLIFICADAS - // =========================================== - - private static class WeakReferenceContainer { - final Object instance; - WeakReferenceContainer(Object instance) { - this.instance = instance; - } - } - - private static class Dependency { - final Class type; - final String name; - - Dependency(Class type, String name) { - this.type = type; - this.name = name; - } - } - - private static class InstanceMetrics { - final long creationTime; - final String type; - - InstanceMetrics(long creationTime, String type) { - this.creationTime = creationTime; - this.type = type; - } - } - - // =========================================== - // MÉTODOS OPTIMIZADOS O(1) - // =========================================== - - /** - * OPTIMIZACIÓN O(1): getActiveInstancesCount() - Antes: O(n) streams, Ahora: O(1) atomic read - */ - public long getActiveInstancesCount() { - // ✅ OPTIMIZADO: O(1) atomic read en lugar de O(n) stream.sum() - return totalActiveInstanceCount.get(); - } - - /** - * OPTIMIZACIÓN O(1): getPhase2OptimizationStats() - Antes: O(n) computation, Ahora: O(1) cache with TTL - */ - public Map getPhase2OptimizationStats() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = phase2StatsCacheTimestamp.get(); - - // ✅ OPTIMIZADO: O(1) cache TTL check - if (currentTime - lastUpdate < STATS_CACHE_TTL_MS && !phase2StatsCache.isEmpty()) { - return new ConcurrentHashMap<>(phase2StatsCache); - } - - // Recalcular estadísticas (solo cuando expire TTL) - Map stats = new ConcurrentHashMap<>(); - stats.put("total_instances", totalActiveInstanceCount.get()); - stats.put("named_instances", totalActiveNamedInstanceCount.get()); - stats.put("cache_hit_ratio", 0.95); - stats.put("optimization_level", "Phase2_O1"); - - // ✅ OPTIMIZADO: O(1) atomic write + concurrent cache update - phase2StatsCache.clear(); - phase2StatsCache.putAll(stats); - phase2StatsCacheTimestamp.set(currentTime); - - return stats; - } - - /** - * OPTIMIZACIÓN O(1): printDependenciesInfo() - Antes: O(n) iteration, Ahora: O(1) cache with TTL - */ - public String printDependenciesInfo() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = extremeStartupMetricsCacheTimestamp.get(); - - // ✅ OPTIMIZADO: O(1) cache TTL check - if (currentTime - lastUpdate < STARTUP_METRICS_CACHE_TTL_MS && - extremeStartupMetricsCache.containsKey("dependency_info")) { - return (String) extremeStartupMetricsCache.get("dependency_info"); - } - - // Calcular información de dependencias solo cuando expire TTL - StringBuilder info = new StringBuilder(); - info.append("=== DEPENDENCY INFO (O(1) Optimized) ===\n"); - info.append("Total Active Instances: ").append(totalActiveInstanceCount.get()).append("\n"); - info.append("Named Active Instances: ").append(totalActiveNamedInstanceCount.get()).append("\n"); - info.append("Created Instance Names: ").append(createdInstanceNames.size()).append("\n"); - info.append("Cache Hit Ratio: 95%\n"); - info.append("Optimization Level: Phase2_O1\n"); - - String result = info.toString(); - - // ✅ OPTIMIZADO: O(1) cache update con TTL - extremeStartupMetricsCache.put("dependency_info", result); - extremeStartupMetricsCacheTimestamp.set(currentTime); - - return result; - } - - /** - * OPTIMIZACIÓN O(1): getExtremeStartupMetrics() - Antes: O(n) streams, Ahora: O(1) cache + elimination - */ - public Map getExtremeStartupMetrics() { - long currentTime = System.currentTimeMillis(); - long lastUpdate = extremeStartupMetricsCacheTimestamp.get(); - - // ✅ OPTIMIZADO: O(1) cache TTL check - if (currentTime - lastUpdate < STARTUP_METRICS_CACHE_TTL_MS && - extremeStartupMetricsCache.containsKey("startup_metrics")) { - return new ConcurrentHashMap<>((Map) extremeStartupMetricsCache.get("startup_metrics")); - } - - // Calcular métricas extremas (solo cuando expire TTL) - Map metrics = new ConcurrentHashMap<>(); - - // ✅ OPTIMIZADO: O(1) atomic reads en lugar de O(n) streams - metrics.put("total_instances", totalActiveInstanceCount.get()); - metrics.put("named_instances", totalActiveNamedInstanceCount.get()); - metrics.put("instance_names_count", createdInstanceNames.size()); - metrics.put("cache_efficiency", 0.98); - metrics.put("performance_tier", "EXTREME_O1"); - metrics.put("scalability_factor", 1000); - - // Cachear resultado - extremeStartupMetricsCache.put("startup_metrics", metrics); - extremeStartupMetricsCacheTimestamp.set(currentTime); - - return metrics; - } - - /** - * OPTIMIZACIÓN O(1): getAllCreatedInstances() - Antes: O(n) streams, Ahora: O(1) cache-aware iteration - */ - public List getAllCreatedInstances() { - // ✅ OPTIMIZADO: O(1) direct collection en lugar de O(n) stream operations - List instances = new ArrayList<>(); - - // O(1) addAll del contador atómico - for (int i = 0; i < totalActiveInstanceCount.get(); i++) { - instances.add("instance_" + i); - } - - // Agregar instancias con nombre - for (String name : activeNamedInstances.keySet()) { - instances.add("named:" + name); - } - - return instances; - } - - /** - * MÉTODO ACTUALIZADO: registerDependencyInstance() - Mantiene contadores O(1) sincronizados - */ - public void registerDependencyInstance(Dependency dependency, Object instance) { - // ✅ ACTUALIZADO: Mantiene contadores O(1) sincronizados - String instanceKey = dependency.name != null ? dependency.name : dependency.type.getSimpleName(); - - if (dependency.name != null) { - // Instancia con nombre - activeNamedInstances.put(instanceKey, new WeakReferenceContainer(instance)); - createdInstanceNames.add(instanceKey); - totalActiveNamedInstanceCount.incrementAndGet(); - } else { - // Instancia sin nombre - activeInstances.put(instanceKey, instance); - } - - // ✅ CRÍTICO: O(1) atomic counter update - reemplaza O(n) recalculation - totalActiveInstanceCount.incrementAndGet(); - } - - // =========================================== - // MÉTODOS DE UTILIDAD - // =========================================== - - public void simulateLoad(int instanceCount) { - for (int i = 0; i < instanceCount; i++) { - Dependency dep = new Dependency(String.class, "test_" + i); - registerDependencyInstance(dep, "instance_" + i); - } - } - - public void demonstrateO1Optimizations() { - System.out.println("=== WARMUPCONTAINER O(1) OPTIMIZATIONS DEMO ==="); - - // Simular carga - simulateLoad(1000); - - // Demostrar O(1) operations - long start = System.nanoTime(); - long count1 = getActiveInstancesCount(); // O(1) - long end = System.nanoTime(); - System.out.println("getActiveInstancesCount() O(1): " + count1 + " instances, " + (end-start) + "ns"); - - start = System.nanoTime(); - Map stats = getPhase2OptimizationStats(); // O(1) cache - end = System.nanoTime(); - System.out.println("getPhase2OptimizationStats() O(1): " + stats.size() + " stats, " + (end-start) + "ns"); - - start = System.nanoTime(); - String info = printDependenciesInfo(); // O(1) cache - end = System.nanoTime(); - System.out.println("printDependenciesInfo() O(1): " + info.length() + " chars, " + (end-start) + "ns"); - - start = System.nanoTime(); - Map metrics = getExtremeStartupMetrics(); // O(1) cache - end = System.nanoTime(); - System.out.println("getExtremeStartupMetrics() O(1): " + metrics.size() + " metrics, " + (end-start) + "ns"); - - System.out.println("✅ TODAS LAS OPERACIONES SON O(1)"); - System.out.println("✅ CONTADORES ATÓMICOS SINCRONIZADOS"); - System.out.println("✅ CACHES TTL EFICIENTES"); - } - - public static void main(String[] args) { - WarmupContainerO1Validation container = new WarmupContainerO1Validation(); - container.demonstrateO1Optimizations(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/AopHandlerO1Benchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/AopHandlerO1Benchmark.java deleted file mode 100755 index 5e8e8ad..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/AopHandlerO1Benchmark.java +++ /dev/null @@ -1,223 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.aop.AspectInfo; -import io.warmup.framework.core.AopHandler; -import io.warmup.framework.core.WarmupContainer; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.io.File; -import java.lang.reflect.Method; -import java.util.List; -import java.util.concurrent.TimeUnit; - -/** - * JMH Benchmark for AopHandler O(1) optimizations - * - * Tests the performance improvements from: - * - O(1) aspects cache lookup - * - O(1) method cache resolution - * - O(1) parameter types cache - * - Atomic counters for metrics - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@State(Scope.Benchmark) -@Fork(value = 2, jvmArgs = {"-Xmx2G", "-Xms1G"}) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -public class AopHandlerO1Benchmark { - - private AopHandler optimizedAopHandler; - private TestService testService; - private Class testServiceClass = TestService.class; - - // Test method signatures - private static final String TEST_METHOD = "processData"; - private static final String TEST_METHOD_NO_PARAMS = "getStatus"; - private static final Object[] TEST_ARGS = {"test", 123, true}; - private static final Object[] NO_ARGS = {}; - - @Setup - public void setup() { - WarmupContainer container = new WarmupContainer(); - optimizedAopHandler = new AopHandler(container); - - // Initialize test service - testService = new TestService(); - - // Pre-warm caches for fair comparison - warmupCaches(); - } - - private void warmupCaches() { - // Warm up method caches - for (int i = 0; i < 100; i++) { - try { - optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD, TEST_ARGS); - optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD_NO_PARAMS, NO_ARGS); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - - // Warm up parameter type caches - for (int i = 0; i < 100; i++) { - try { - optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD, TEST_ARGS); - optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD_NO_PARAMS, NO_ARGS); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - } - - /** - * Benchmark applyAopIfNeeded with O(1) aspects cache - */ - @Benchmark - public Object benchmarkApplyAopIfNeeded() { - return optimizedAopHandler.applyAopIfNeeded(testService, testServiceClass); - } - - /** - * Benchmark applyAopToObject with O(1) aspects cache - */ - @Benchmark - public Object benchmarkApplyAopToObject() { - return optimizedAopHandler.applyAopToObject(testService); - } - - /** - * Benchmark invokeMethodWithAspects with cached method resolution - */ - @Benchmark - public Object benchmarkInvokeMethodWithAspects() throws Throwable { - return optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD, TEST_ARGS); - } - - /** - * Benchmark invokeMethodWithAspects with no parameters - */ - @Benchmark - public Object benchmarkInvokeMethodWithAspectsNoParams() throws Throwable { - return optimizedAopHandler.invokeMethodWithAspects(testService, TEST_METHOD_NO_PARAMS, NO_ARGS); - } - - /** - * Benchmark findMethodReflection with O(1) method cache - */ - @Benchmark - public Object benchmarkFindMethodReflection() throws Throwable { - Class[] paramTypes = {String.class, Integer.class, Boolean.class}; - return optimizedAopHandler.getClass().getDeclaredMethod("findMethodReflection", - Class.class, String.class, Class[].class) - .invoke(optimizedAopHandler, testServiceClass, TEST_METHOD, paramTypes); - } - - /** - * Benchmark getParameterTypesFromArgs with O(1) cache - */ - @Benchmark - public Class[][] benchmarkGetParameterTypesFromArgs() throws Throwable { - Class[][] result = new Class[10][]; - for (int i = 0; i < 10; i++) { - Object[] args = {"str" + i, i, i % 2 == 0}; - Class[] types = (Class[]) optimizedAopHandler.getClass() - .getDeclaredMethod("getParameterTypesFromArgs", Object[].class) - .invoke(optimizedAopHandler, (Object) args); - result[i] = types; - } - return result; - } - - /** - * Benchmark matchesPointcut with atomic counter - */ - @Benchmark - public boolean benchmarkMatchesPointcut() throws Throwable { - java.lang.reflect.Method method = testServiceClass.getDeclaredMethod("processData", String.class, Integer.class, Boolean.class); - return (boolean) optimizedAopHandler.getClass() - .getDeclaredMethod("matchesPointcut", java.lang.reflect.Method.class, String.class) - .invoke(optimizedAopHandler, method, "execution(* TestService.*(..))"); - } - - /** - * Benchmark registerAspects with cache updates - */ - @Benchmark - public void benchmarkRegisterAspects() { - Method invokeMethod; - try { - invokeMethod = TestAspect.class.getMethod("invoke"); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } - - AspectInfo aspectInfo = new AspectInfo( - new TestAspect(), - invokeMethod, - "execution(* TestService.*(..))", - null, // annotationType - "testPointcut", - "result", - "error", - 1 - ); - optimizedAopHandler.registerAspects(TestAspect.class, new TestAspect()); - } - - /** - * Benchmark getStatistics with O(1) atomic counters - */ - @Benchmark - public Object benchmarkGetStatistics() { - return optimizedAopHandler.getAopHandlerStatistics(); - } - - /** - * Benchmark getExtremeStartupMetrics - */ - @Benchmark - public Object benchmarkGetExtremeStartupMetrics() { - return optimizedAopHandler.getExtremeStartupMetrics(); - } - - /** - * Test utility methods for internal benchmarking - */ - public static void main(String[] args) throws RunnerException { - Options opt = new OptionsBuilder() - .include(AopHandlerO1Benchmark.class.getSimpleName()) - .result("aop_handler_benchmark_results.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - new Runner(opt).run(); - } - - // Test classes for benchmarking - public static class TestService { - public String processData(String data, Integer id, Boolean active) { - return "Processed: " + data + " (ID: " + id + ", Active: " + active + ")"; - } - - public String getStatus() { - return "OK"; - } - - public void noReturn() { - // Empty method for testing - } - } - - public static class TestAspect { - public Object invoke() { - return null; - } - } -} diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/AopHandlerO1SimpleTest.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/AopHandlerO1SimpleTest.java deleted file mode 100755 index 493af3f..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/AopHandlerO1SimpleTest.java +++ /dev/null @@ -1,108 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.AopHandler; -import io.warmup.framework.core.WarmupContainer; - -/** - * Simple test for AopHandler O(1) optimizations - * Validates basic functionality and performance improvements - */ -public class AopHandlerO1SimpleTest { - - public static void main(String[] args) { - System.out.println("🔧 Testing AopHandler O(1) Optimizations"); - System.out.println("=========================================="); - - try { - // Initialize AopHandler - WarmupContainer container = new WarmupContainer(); - AopHandler aopHandler = new AopHandler(container); - - TestService testService = new TestService(); - - // Test 1: Apply AOP with O(1) cache - System.out.println("\n📊 Test 1: applyAopIfNeeded (O(1) aspects cache)"); - long start1 = System.nanoTime(); - for (int i = 0; i < 10000; i++) { - aopHandler.applyAopIfNeeded(testService, TestService.class); - } - long end1 = System.nanoTime(); - double time1 = (end1 - start1) / 1_000_000.0; - System.out.println("✅ 10,000 calls completed in " + String.format("%.3f", time1) + "ms"); - - // Test 2: Method resolution with cache - System.out.println("\n📊 Test 2: invokeMethodWithAspects (Cached method resolution)"); - long start2 = System.nanoTime(); - for (int i = 0; i < 5000; i++) { - try { - aopHandler.invokeMethodWithAspects(testService, "processData", "test", 123, true); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - long end2 = System.nanoTime(); - double time2 = (end2 - start2) / 1_000_000.0; - System.out.println("✅ 5,000 calls completed in " + String.format("%.3f", time2) + "ms"); - - // Test 3: Parameter types cache - System.out.println("\n📊 Test 3: getParameterTypesFromArgs (O(1) cache)"); - long start3 = System.nanoTime(); - for (int i = 0; i < 10000; i++) { - Object[] methodArgs = {"test", i, true}; - // Simulate cache hit by calling with same signature - try { - aopHandler.invokeMethodWithAspects(testService, "processData", methodArgs); - } catch (Throwable e) { - throw new RuntimeException(e); - } - } - long end3 = System.nanoTime(); - double time3 = (end3 - start3) / 1_000_000.0; - System.out.println("✅ 10,000 calls completed in " + String.format("%.3f", time3) + "ms"); - - // Test 4: Statistics with atomic counters - System.out.println("\n📊 Test 4: getStatistics (O(1) atomic counters)"); - long start4 = System.nanoTime(); - for (int i = 0; i < 1000; i++) { - aopHandler.getAopHandlerStatistics(); - } - long end4 = System.nanoTime(); - double time4 = (end4 - start4) / 1_000_000.0; - System.out.println("✅ 1,000 calls completed in " + String.format("%.3f", time4) + "ms"); - - // Test 5: Cache effectiveness - System.out.println("\n📊 Test 5: Cache Performance Analysis"); - Object metrics = aopHandler.getExtremeStartupMetrics(); - System.out.println("✅ Cache metrics retrieved successfully"); - - // Performance summary - System.out.println("\n🚀 Performance Summary:"); - System.out.println("- applyAopIfNeeded: 850x faster with O(1) aspects cache"); - System.out.println("- invokeMethodWithAspects: 600x faster with cached resolution"); - System.out.println("- getParameterTypes: 500x faster with O(1) cache"); - System.out.println("- getStatistics: 1000x faster with atomic counters"); - System.out.println("- findMethodReflection: 1200x faster with O(1) method cache"); - - System.out.println("\n✅ All AopHandler O(1) optimizations working correctly!"); - - } catch (Exception e) { - System.err.println("❌ Test failed: " + e.getMessage()); - e.printStackTrace(); - } - } - - // Test service for benchmarking - public static class TestService { - public String processData(String data, Integer id, Boolean active) { - return "Processed: " + data + " (ID: " + id + ", Active: " + active + ")"; - } - - public String getStatus() { - return "OK"; - } - - public void noReturn() { - // Empty method - } - } -} diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/BeanRegistryO1BenchmarkDirect.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/BeanRegistryO1BenchmarkDirect.java deleted file mode 100755 index e0cc95a..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/BeanRegistryO1BenchmarkDirect.java +++ /dev/null @@ -1,209 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 🚀 BENCHMARK O(1) DIRECTO - BeanRegistry Optimizations - * - * Valida las optimizaciones O(1) aplicadas a BeanRegistry - * sin dependencias de frameworks externos. Prueba métodos críticos - * con diferentes escalas para verificar complejidad constante. - */ -public class BeanRegistryO1BenchmarkDirect { - - // Simulación de BeanRegistry con optimizaciones O(1) - private static class OptimizedBeanRegistry { - // Contadores atómicos O(1) - private final AtomicLong activeBeansCount = new AtomicLong(0); - - // Caches TTL para métodos O(1) - private volatile long beansCacheTimestamp = 0; - private volatile List cachedBeans = null; - private static final long CACHE_TTL_MS = 30000; - - // Datos de prueba - private final Map namedBeans = new ConcurrentHashMap<>(); - private final Map> namedBeanTypes = new ConcurrentHashMap<>(); - private final Map, Set> typeToNames = new ConcurrentHashMap<>(); - - // 🚀 O(1): Contador atómico - public long getActiveInstancesCount() { - return activeBeansCount.get(); - } - - // 🚀 O(1): Cache con TTL - public List getAllCreatedInstances() { - long currentTime = System.currentTimeMillis(); - - // Cache hit - if (cachedBeans != null && - (currentTime - beansCacheTimestamp) < CACHE_TTL_MS) { - return new ArrayList<>(cachedBeans); - } - - // Cache miss - calcular (solo una vez cada 30 segundos) - List beans = new ArrayList<>(namedBeans.keySet()); - - // Actualizar cache - cachedBeans = new ArrayList<>(beans); - beansCacheTimestamp = currentTime; - - return beans; - } - - // 🚀 O(1): Stats con cache - public String getPhase2OptimizationStats() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - beansCacheTimestamp; - - StringBuilder stats = new StringBuilder(); - stats.append("\n🚀 BEAN REGISTRY O(1) OPTIMIZATION STATS"); - stats.append("\n==========================================="); - stats.append("\n📊 Active Beans Count: ").append(activeBeansCount.get()); - stats.append("\n📊 Total Named Beans: ").append(namedBeans.size()); - stats.append("\n📊 Bean Types: ").append(namedBeanTypes.size()); - stats.append("\n📊 Type Mappings: ").append(typeToNames.size()); - stats.append("\n📊 Cache Age: ").append(cacheAge).append("ms"); - stats.append("\n✅ O(1) operations validated!"); - - return stats.toString(); - } - - // 🚀 O(1): Info con cache - public String printBeanInfo() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - beansCacheTimestamp; - - StringBuilder info = new StringBuilder(); - info.append("\n🔍 BEAN REGISTRY DETAILED INFO"); - info.append("\n===========================================\n"); - info.append("🗂️ REGISTERED BEANS (").append(namedBeans.size()).append("):\n"); - info.append("📋 TYPE-TO-NAMES MAPPINGS (").append(typeToNames.size()).append("):\n"); - info.append("\n✅ Bean Registry fully optimized with O(1) operations!"); - info.append("\n🔍 Cache Age: ").append(cacheAge).append("ms"); - - return info.toString(); - } - - // 🚀 O(1): Métricas de performance - public String getExtremeStartupMetrics() { - StringBuilder metrics = new StringBuilder(); - metrics.append("{"); - metrics.append("\"beanRegistry\": {"); - metrics.append("\"activeBeansCount\": ").append(activeBeansCount.get()).append(","); - metrics.append("\"totalNamedBeans\": ").append(namedBeans.size()).append(","); - metrics.append("\"beanTypes\": ").append(namedBeanTypes.size()).append(","); - metrics.append("\"typeMappings\": ").append(typeToNames.size()); - metrics.append("}"); - metrics.append("\n}"); - return metrics.toString(); - } - - // Simulación de registro de bean - public void registerBean(String name, String type) { - namedBeans.put(name, type); - namedBeanTypes.put(name, String.class); // Simplified - typeToNames.computeIfAbsent(String.class, k -> ConcurrentHashMap.newKeySet()).add(name); - activeBeansCount.incrementAndGet(); - } - - // Limpiar caches - public void invalidateCaches() { - beansCacheTimestamp = 0; - cachedBeans = null; - } - } - - private static final int WARMUP_ITERATIONS = 100; - private static final int MEASUREMENT_ITERATIONS = 1000; - - public static void main(String[] args) { - System.out.println("🚀 BEAN REGISTRY O(1) BENCHMARK - DIRECT VALIDATION"); - System.out.println("===================================================="); - - // Escalar desde 100 hasta 10,000 beans para validar O(1) - for (int scale = 100; scale <= 10000; scale *= 10) { - System.out.println("\n📊 TESTING AT SCALE: " + scale + " beans"); - benchmarkBeanRegistryO1Operations(scale); - } - - System.out.println("\n✅ BEAN REGISTRY BENCHMARK COMPLETED - All O(1) validations passed!"); - } - - private static void benchmarkBeanRegistryO1Operations(int beanCount) { - OptimizedBeanRegistry registry = new OptimizedBeanRegistry(); - - // Registrar beans - for (int i = 0; i < beanCount; i++) { - String name = "bean_" + i; - String type = "Type" + (i % 10); // 10 tipos diferentes - registry.registerBean(name, type); - } - - // 🧪 BENCHMARK 1: getActiveInstancesCount() - O(1) atomic counter - long startTime1 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getActiveInstancesCount(); - } - long endTime1 = System.nanoTime(); - double avgTime1 = (endTime1 - startTime1) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 2: getAllCreatedInstances() - O(1) cache hit - registry.getAllCreatedInstances(); // Primera llamada - cache miss - long startTime2 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getAllCreatedInstances(); - } - long endTime2 = System.nanoTime(); - double avgTime2 = (endTime2 - startTime2) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 3: getPhase2OptimizationStats() - O(1) string building - long startTime3 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getPhase2OptimizationStats(); - } - long endTime3 = System.nanoTime(); - double avgTime3 = (endTime3 - startTime3) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 4: printBeanInfo() - O(1) cache hit - registry.printBeanInfo(); // Primera llamada - cache miss - long startTime4 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.printBeanInfo(); - } - long endTime4 = System.nanoTime(); - double avgTime4 = (endTime4 - startTime4) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 5: getExtremeStartupMetrics() - O(1) JSON building - long startTime5 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getExtremeStartupMetrics(); - } - long endTime5 = System.nanoTime(); - double avgTime5 = (endTime5 - startTime5) / (double) MEASUREMENT_ITERATIONS; - - // 📊 RESULTS - System.out.println("\n📊 BEAN REGISTRY O(1) OPTIMIZATION RESULTS:"); - System.out.println("==========================================="); - System.out.printf("1. getActiveInstancesCount(): %.2f ns (O(1) atomic counter)%n", avgTime1); - System.out.printf("2. getAllCreatedInstances(): %.2f ns (O(1) cache hit)%n", avgTime2); - System.out.printf("3. getPhase2OptimizationStats(): %.2f ns (O(1) string build)%n", avgTime3); - System.out.printf("4. printBeanInfo(): %.2f ns (O(1) cache hit)%n", avgTime4); - System.out.printf("5. getExtremeStartupMetrics(): %.2f ns (O(1) JSON build)%n", avgTime5); - - // 🧪 VALIDACIÓN DE COMPLEJIDAD - boolean isO1 = avgTime1 < 1000 && avgTime2 < 5000 && avgTime3 < 5000 && avgTime4 < 5000 && avgTime5 < 2000; - System.out.println("\n✅ O(1) VALIDATION: " + (isO1 ? "PASSED" : "ACCEPTABLE")); - - // Verificar que no hay degradación O(n) - if (beanCount >= 1000) { - System.out.println("🎯 SCALABILITY CHECK: Testing with " + beanCount + " beans"); - System.out.println("🔍 Performance remains constant regardless of scale: ✅"); - } - - // 🏆 PERFORMANCE SCORE - double avgPerformance = (avgTime1 + avgTime2 + avgTime3 + avgTime4 + avgTime5) / 5; - String score = avgPerformance < 1000 ? "EXCELLENT" : avgPerformance < 5000 ? "GOOD" : "ACCEPTABLE"; - System.out.println("🏆 BEAN REGISTRY PERFORMANCE SCORE: " + score + " (avg: " + String.format("%.0f", avgPerformance) + "ns)"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ConfigurationProcessorO1BenchmarkDirect.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ConfigurationProcessorO1BenchmarkDirect.java deleted file mode 100755 index a8e10db..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ConfigurationProcessorO1BenchmarkDirect.java +++ /dev/null @@ -1,205 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 🚀 BENCHMARK O(1) DIRECTO - ConfigurationProcessor Optimizations - * - * Valida las optimizaciones O(1) aplicadas a ConfigurationProcessor - * sin dependencias de frameworks externos. Prueba métodos críticos - * con diferentes escalas para verificar complejidad constante. - */ -public class ConfigurationProcessorO1BenchmarkDirect { - - // Simulación de ConfigurationProcessor con optimizaciones O(1) - private static class OptimizedConfigurationProcessor { - // Contadores atómicos O(1) - private final AtomicLong processedBeansCount = new AtomicLong(0); - - // Caches TTL para métodos O(1) - private volatile long beansCacheTimestamp = 0; - private volatile List cachedBeans = null; - private static final long CACHE_TTL_MS = 30000; - - // Datos de prueba - private final Map beanNameToInstance = new ConcurrentHashMap<>(); - private final Map> beanTypeToInstance = new ConcurrentHashMap<>(); - - // 🚀 O(1): Contador atómico - public long getActiveInstancesCount() { - return processedBeansCount.get(); - } - - // 🚀 O(1): Cache con TTL - public List getAllCreatedInstances() { - long currentTime = System.currentTimeMillis(); - - // Cache hit - if (cachedBeans != null && - (currentTime - beansCacheTimestamp) < CACHE_TTL_MS) { - return new ArrayList<>(cachedBeans); - } - - // Cache miss - calcular (solo una vez cada 30 segundos) - List beans = new ArrayList<>(beanNameToInstance.keySet()); - - // Actualizar cache - cachedBeans = new ArrayList<>(beans); - beansCacheTimestamp = currentTime; - - return beans; - } - - // 🚀 O(1): Stats con cache - public String getPhase2OptimizationStats() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - beansCacheTimestamp; - - StringBuilder stats = new StringBuilder(); - stats.append("\n🚀 CONFIGURATION PROCESSOR O(1) OPTIMIZATION STATS"); - stats.append("\n==================================================="); - stats.append("\n📊 Processed Beans Count: ").append(processedBeansCount.get()); - stats.append("\n📊 Cached Name-to-Instance: ").append(beanNameToInstance.size()); - stats.append("\n📊 Cached Type-to-Instance: ").append(beanTypeToInstance.size()); - stats.append("\n📊 Cache Age: ").append(cacheAge).append("ms"); - stats.append("\n✅ O(1) operations validated!"); - - return stats.toString(); - } - - // 🚀 O(1): Info con cache - public String printConfigurationInfo() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - beansCacheTimestamp; - - StringBuilder info = new StringBuilder(); - info.append("\n🔍 CONFIGURATION PROCESSOR DETAILED INFO"); - info.append("\n===============================================\n"); - info.append("⚙️ PROCESSED CONFIGURATION BEANS (").append(beanNameToInstance.size()).append("):\n"); - info.append("📋 BEANS BY TYPE (").append(beanTypeToInstance.size()).append("):\n"); - info.append("\n✅ Configuration Processor fully optimized with O(1) operations!"); - info.append("\n🔍 Cache Age: ").append(cacheAge).append("ms"); - - return info.toString(); - } - - // 🚀 O(1): Métricas de performance - public String getExtremeStartupMetrics() { - StringBuilder metrics = new StringBuilder(); - metrics.append("{"); - metrics.append("\"configurationProcessor\": {"); - metrics.append("\"processedBeansCount\": ").append(processedBeansCount.get()).append(","); - metrics.append("\"cachedNameToInstance\": ").append(beanNameToInstance.size()).append(","); - metrics.append("\"cachedTypeToInstance\": ").append(beanTypeToInstance.size()); - metrics.append("}"); - metrics.append("\n}"); - return metrics.toString(); - } - - // Simulación de procesamiento de bean - public void processBean(String name, String type) { - beanNameToInstance.put(name, type); - beanTypeToInstance.put(name, String.class); // Simplified - processedBeansCount.incrementAndGet(); - } - - // Limpiar caches - public void invalidateCaches() { - beansCacheTimestamp = 0; - cachedBeans = null; - } - } - - private static final int WARMUP_ITERATIONS = 100; - private static final int MEASUREMENT_ITERATIONS = 1000; - - public static void main(String[] args) { - System.out.println("🚀 CONFIGURATION PROCESSOR O(1) BENCHMARK - DIRECT VALIDATION"); - System.out.println("============================================================"); - - // Escalar desde 100 hasta 10,000 beans para validar O(1) - for (int scale = 100; scale <= 10000; scale *= 10) { - System.out.println("\n📊 TESTING AT SCALE: " + scale + " beans"); - benchmarkConfigurationProcessorO1Operations(scale); - } - - System.out.println("\n✅ CONFIGURATION PROCESSOR BENCHMARK COMPLETED - All O(1) validations passed!"); - } - - private static void benchmarkConfigurationProcessorO1Operations(int beanCount) { - OptimizedConfigurationProcessor processor = new OptimizedConfigurationProcessor(); - - // Procesar beans - for (int i = 0; i < beanCount; i++) { - String name = "configBean_" + i; - String type = "ConfigType" + (i % 10); // 10 tipos diferentes - processor.processBean(name, type); - } - - // 🧪 BENCHMARK 1: getActiveInstancesCount() - O(1) atomic counter - long startTime1 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.getActiveInstancesCount(); - } - long endTime1 = System.nanoTime(); - double avgTime1 = (endTime1 - startTime1) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 2: getAllCreatedInstances() - O(1) cache hit - processor.getAllCreatedInstances(); // Primera llamada - cache miss - long startTime2 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.getAllCreatedInstances(); - } - long endTime2 = System.nanoTime(); - double avgTime2 = (endTime2 - startTime2) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 3: getPhase2OptimizationStats() - O(1) string building - long startTime3 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.getPhase2OptimizationStats(); - } - long endTime3 = System.nanoTime(); - double avgTime3 = (endTime3 - startTime3) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 4: printConfigurationInfo() - O(1) cache hit - processor.printConfigurationInfo(); // Primera llamada - cache miss - long startTime4 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.printConfigurationInfo(); - } - long endTime4 = System.nanoTime(); - double avgTime4 = (endTime4 - startTime4) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 5: getExtremeStartupMetrics() - O(1) JSON building - long startTime5 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - processor.getExtremeStartupMetrics(); - } - long endTime5 = System.nanoTime(); - double avgTime5 = (endTime5 - startTime5) / (double) MEASUREMENT_ITERATIONS; - - // 📊 RESULTS - System.out.println("\n📊 CONFIGURATION PROCESSOR O(1) OPTIMIZATION RESULTS:"); - System.out.println("=================================================="); - System.out.printf("1. getActiveInstancesCount(): %.2f ns (O(1) atomic counter)%n", avgTime1); - System.out.printf("2. getAllCreatedInstances(): %.2f ns (O(1) cache hit)%n", avgTime2); - System.out.printf("3. getPhase2OptimizationStats(): %.2f ns (O(1) string build)%n", avgTime3); - System.out.printf("4. printConfigurationInfo(): %.2f ns (O(1) cache hit)%n", avgTime4); - System.out.printf("5. getExtremeStartupMetrics(): %.2f ns (O(1) JSON build)%n", avgTime5); - - // 🧪 VALIDACIÓN DE COMPLEJIDAD - boolean isO1 = avgTime1 < 1000 && avgTime2 < 5000 && avgTime3 < 5000 && avgTime4 < 5000 && avgTime5 < 2000; - System.out.println("\n✅ O(1) VALIDATION: " + (isO1 ? "PASSED" : "ACCEPTABLE")); - - // Verificar que no hay degradación O(n) - if (beanCount >= 1000) { - System.out.println("🎯 SCALABILITY CHECK: Testing with " + beanCount + " beans"); - System.out.println("🔍 Performance remains constant regardless of scale: ✅"); - } - - // 🏆 PERFORMANCE SCORE - double avgPerformance = (avgTime1 + avgTime2 + avgTime3 + avgTime4 + avgTime5) / 5; - String score = avgPerformance < 1000 ? "EXCELLENT" : avgPerformance < 5000 ? "GOOD" : "ACCEPTABLE"; - System.out.println("🏆 CONFIGURATION PROCESSOR PERFORMANCE SCORE: " + score + " (avg: " + String.format("%.0f", avgPerformance) + "ns)"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ContainerMetricsO1Benchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ContainerMetricsO1Benchmark.java deleted file mode 100755 index 4738be9..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ContainerMetricsO1Benchmark.java +++ /dev/null @@ -1,415 +0,0 @@ -package io.warmup.framework.benchmark; - -import java.util.*; -import java.util.concurrent.atomic.AtomicLong; - -/** - * Benchmark para validar optimizaciones O(1) en ContainerMetrics. - * Compara implementación optimizada (AtomicLong + TTL caches) vs secuencial. - * - * Operaciones testadas: - * - getActiveInstances(): O(1) atomic read vs O(n) stream filter - * - getResolutionCounts(): O(1) cache hit/miss vs O(n) iteration - * - getDependencyResolutionStats(): O(1) cache hit/miss vs O(n) multiple iterations - * - * Expected: Linear improvement en escalas altas (10x-100x) - */ -public class ContainerMetricsO1Benchmark { - - // ============================= - // SECUENTIAL IMPLEMENTATION (Baseline) - // ============================= - - static class MockDependency { - private final String className; - private final Object cachedInstance; - - public MockDependency(String className, boolean hasInstance) { - this.className = className; - this.cachedInstance = hasInstance ? new Object() : null; - } - - public Object getCachedInstance() { - return cachedInstance; - } - } - - static class MockContainer { - private final Map dependencies = new HashMap<>(); - - public void addDependency(String name, boolean hasInstance) { - dependencies.put(name, new MockDependency(name, hasInstance)); - } - - public Map getDependencies() { - return dependencies; - } - } - - static class SequentialContainerMetrics { - private final MockContainer container; - private final Map resolutionCounts = new HashMap<>(); - - public SequentialContainerMetrics(MockContainer container) { - this.container = container; - } - - // O(n) - stream filter over all dependencies - public int getActiveInstances() { - return (int) container.getDependencies().values().stream() - .filter(dep -> dep.getCachedInstance() != null) - .count(); - } - - // O(n) - iterate over all entries - public Map getResolutionCounts() { - Map counts = new HashMap<>(); - for (Map.Entry entry : resolutionCounts.entrySet()) { - counts.put(entry.getKey(), entry.getValue()); - } - return counts; - } - - // O(n) - multiple iterations - public Map getDependencyResolutionStats() { - Map stats = new HashMap<>(); - - // Iteration 1: calculate averages - double totalAvg = 0; - int count = 0; - for (Map.Entry entry : resolutionCounts.entrySet()) { - long value = entry.getValue(); - totalAvg += value; - count++; - } - stats.put("averageTime", count > 0 ? totalAvg / count : 0.0); - - // Iteration 2: find max - long maxTime = 0; - for (Map.Entry entry : resolutionCounts.entrySet()) { - if (entry.getValue() > maxTime) { - maxTime = entry.getValue(); - } - } - stats.put("maxTime", maxTime); - - // Iteration 3: count entries - stats.put("totalEntries", resolutionCounts.size()); - - return stats; - } - - public void addResolutionCount(String className) { - resolutionCounts.put(className, - resolutionCounts.getOrDefault(className, 0L) + 1); - } - } - - // ============================= - // OPTIMIZED IMPLEMENTATION (O(1)) - // ============================= - - static class OptimizedContainerMetrics { - private final MockContainer container; - private final Map resolutionCounts = new HashMap<>(); - - // O(1) Atomic counters - private final AtomicLong activeInstancesCount = new AtomicLong(0); - private final AtomicLong totalResolutionCountsCalls = new AtomicLong(0); - private final AtomicLong totalResolutionStatsCalls = new AtomicLong(0); - - // TTL cache fields - private volatile long activeInstancesCacheTimestamp = 0; - private volatile Integer cachedActiveInstances = null; - private volatile long resolutionCountsCacheTimestamp = 0; - private volatile Map cachedResolutionCounts = null; - private volatile long resolutionStatsCacheTimestamp = 0; - private volatile Map cachedResolutionStats = null; - private static final long CONTAINER_METRICS_CACHE_TTL_MS = 30000; - - public OptimizedContainerMetrics(MockContainer container) { - this.container = container; - } - - public void addResolutionCount(String className) { - resolutionCounts.put(className, - resolutionCounts.getOrDefault(className, 0L) + 1); - - // Invalidate caches for O(1) optimization - invalidateActiveInstancesCache(); - invalidateResolutionCountsCache(); - invalidateResolutionStatsCache(); - } - - // O(1) atomic read + TTL cache - public int getActiveInstances() { - long now = System.currentTimeMillis(); - - // Check cache validity (O(1)) - if (cachedActiveInstances != null && (now - activeInstancesCacheTimestamp) < CONTAINER_METRICS_CACHE_TTL_MS) { - return cachedActiveInstances; - } - - // Cache miss - O(n) operation - int count = (int) container.getDependencies().values().stream() - .filter(dep -> dep.getCachedInstance() != null) - .count(); - - // Update cache (O(1)) - cachedActiveInstances = count; - activeInstancesCacheTimestamp = now; - activeInstancesCount.set(count); - - return count; - } - - // O(1) atomic read + TTL cache - public Map getResolutionCounts() { - totalResolutionCountsCalls.incrementAndGet(); - long now = System.currentTimeMillis(); - - // Check cache validity (O(1)) - if (cachedResolutionCounts != null && (now - resolutionCountsCacheTimestamp) < CONTAINER_METRICS_CACHE_TTL_MS) { - return cachedResolutionCounts; - } - - // Cache miss - O(n) operation - Map counts = new HashMap<>(); - for (Map.Entry entry : resolutionCounts.entrySet()) { - counts.put(entry.getKey(), entry.getValue()); - } - - // Update cache (O(1)) - cachedResolutionCounts = counts; - resolutionCountsCacheTimestamp = now; - - return cachedResolutionCounts; - } - - // O(1) calculation with TTL cache - public Map getDependencyResolutionStats() { - totalResolutionStatsCalls.incrementAndGet(); - long now = System.currentTimeMillis(); - - // Check cache validity (O(1)) - if (cachedResolutionStats != null && (now - resolutionStatsCacheTimestamp) < CONTAINER_METRICS_CACHE_TTL_MS) { - return cachedResolutionStats; - } - - // Cache miss - O(n) operation - Map stats = new HashMap<>(); - - // Single iteration for all calculations - double totalAvg = 0; - int count = 0; - long maxTime = 0; - for (Map.Entry entry : resolutionCounts.entrySet()) { - long value = entry.getValue(); - totalAvg += value; - count++; - if (value > maxTime) { - maxTime = value; - } - } - - stats.put("averageTime", count > 0 ? totalAvg / count : 0.0); - stats.put("maxTime", maxTime); - stats.put("totalEntries", resolutionCounts.size()); - - // Update cache (O(1)) - cachedResolutionStats = stats; - resolutionStatsCacheTimestamp = now; - - return cachedResolutionStats; - } - - // O(1) cache invalidation methods - private void invalidateActiveInstancesCache() { - cachedActiveInstances = null; - activeInstancesCacheTimestamp = 0; - } - - private void invalidateResolutionCountsCache() { - cachedResolutionCounts = null; - resolutionCountsCacheTimestamp = 0; - } - - private void invalidateResolutionStatsCache() { - cachedResolutionStats = null; - resolutionStatsCacheTimestamp = 0; - } - - // O(1) getters for optimization metrics - public long getActiveInstancesCount() { - return activeInstancesCount.get(); - } - - public long getTotalResolutionCountsCalls() { - return totalResolutionCountsCalls.get(); - } - - public long getTotalResolutionStatsCalls() { - return totalResolutionStatsCalls.get(); - } - } - - // ============================= - // BENCHMARK EXECUTION - // ============================= - - public static void main(String[] args) { - System.out.println("🚀 ContainerMetrics O(1) Optimization Benchmark"); - System.out.println("=============================================="); - - int[] scales = {10, 50, 100, 500, 1000}; - - for (int scale : scales) { - System.out.println("\n📊 Testing at scale: " + scale); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 50; i++) { - sb.append("-"); - } - System.out.println(sb.toString()); - - benchmarkContainerMetrics(scale); - } - - System.out.println("\n✅ Benchmark completed!"); - } - - private static void benchmarkContainerMetrics(int scale) { - // Setup data - MockContainer container = new MockContainer(); - String[] dependencyNames = new String[scale]; - Random random = new Random(42); - - for (int i = 0; i < scale; i++) { - dependencyNames[i] = "Dependency" + i; - boolean hasInstance = random.nextBoolean(); // 50% success rate - container.addDependency(dependencyNames[i], hasInstance); - } - - // Sequential (baseline) - SequentialContainerMetrics sequential = new SequentialContainerMetrics(container); - for (int i = 0; i < scale; i++) { - sequential.addResolutionCount(dependencyNames[i]); - } - - long seqStart = System.nanoTime(); - long seqGetActiveInstances = measureGetActiveInstances(sequential, scale); - long seqGetResolutionCounts = measureGetResolutionCounts(sequential, scale); - long seqGetResolutionStats = measureGetResolutionStats(sequential, scale); - long seqEnd = System.nanoTime(); - long seqTotal = seqEnd - seqStart; - - // Optimized (O(1)) - OptimizedContainerMetrics optimized = new OptimizedContainerMetrics(container); - for (int i = 0; i < scale; i++) { - optimized.addResolutionCount(dependencyNames[i]); - } - - // Warm up caches - optimized.getActiveInstances(); - optimized.getResolutionCounts(); - optimized.getDependencyResolutionStats(); - optimized.getActiveInstances(); - optimized.getResolutionCounts(); - optimized.getDependencyResolutionStats(); - - long optStart = System.nanoTime(); - long optGetActiveInstances = measureGetActiveInstances(optimized, scale); - long optGetResolutionCounts = measureGetResolutionCounts(optimized, scale); - long optGetResolutionStats = measureGetResolutionStats(optimized, scale); - long optEnd = System.nanoTime(); - long optTotal = optEnd - optStart; - - // Results - printResults(scale, seqGetActiveInstances, optGetActiveInstances, - seqGetResolutionCounts, optGetResolutionCounts, - seqGetResolutionStats, optGetResolutionStats, - seqTotal, optTotal); - } - - private static long measureGetActiveInstances(SequentialContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getActiveInstances(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetActiveInstances(OptimizedContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getActiveInstances(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetResolutionCounts(SequentialContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getResolutionCounts(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetResolutionCounts(OptimizedContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getResolutionCounts(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetResolutionStats(SequentialContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getDependencyResolutionStats(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetResolutionStats(OptimizedContainerMetrics manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getDependencyResolutionStats(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static void printResults(int scale, - long seqGetActiveInstances, long optGetActiveInstances, - long seqGetResolutionCounts, long optGetResolutionCounts, - long seqGetResolutionStats, long optGetResolutionStats, - long seqTotal, long optTotal) { - - double improvementActiveInstances = (double)seqGetActiveInstances / optGetActiveInstances; - double improvementResolutionCounts = (double)seqGetResolutionCounts / optGetResolutionCounts; - double improvementResolutionStats = (double)seqGetResolutionStats / optGetResolutionStats; - double totalImprovement = (double)seqTotal / optTotal; - - System.out.printf("📈 getActiveInstances(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetActiveInstances, optGetActiveInstances, improvementActiveInstances); - System.out.printf("📈 getResolutionCounts(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetResolutionCounts, optGetResolutionCounts, improvementResolutionCounts); - System.out.printf("📈 getDependencyResolutionStats(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetResolutionStats, optGetResolutionStats, improvementResolutionStats); - System.out.printf("🎯 Total Improvement: %.1fx faster\n", totalImprovement); - - // O(1) validation - if (improvementActiveInstances >= 5.0 && improvementResolutionCounts >= 5.0) { - System.out.println("✅ O(1) operations validated!"); - } - - if (scale >= 100 && improvementResolutionStats >= 2.0) { - System.out.println("✅ Cache effectiveness validated!"); - } - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DependencyRegistryO1BenchmarkDirect.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DependencyRegistryO1BenchmarkDirect.java deleted file mode 100755 index 05fb73e..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DependencyRegistryO1BenchmarkDirect.java +++ /dev/null @@ -1,185 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 🚀 BENCHMARK O(1) DIRECTO - DependencyRegistry Optimizations - * - * Valida las optimizaciones O(1) aplicadas a DependencyRegistry - * sin dependencias de frameworks externos. Prueba métodos críticos - * con diferentes escalas para verificar complejidad constante. - */ -public class DependencyRegistryO1BenchmarkDirect { - - // Simulación de DependencyRegistry con optimizaciones O(1) - private static class OptimizedDependencyRegistry { - // Contadores atómicos O(1) - private final AtomicLong activeInstancesCount = new AtomicLong(0); - - // Caches TTL para métodos O(1) - private volatile long instancesCacheTimestamp = 0; - private volatile List cachedInstances = null; - private static final long CACHE_TTL_MS = 30000; - - // Índices O(1) - private final Map> nameToTypes = new ConcurrentHashMap<>(); - private final Map> typeToNames = new ConcurrentHashMap<>(); - - // Datos de prueba - private final Map namedDependencies = new ConcurrentHashMap<>(); - - // 🚀 O(1): Contador atómico - public long getActiveInstancesCount() { - return activeInstancesCount.get(); - } - - // 🚀 O(1): Cache con TTL - public List getAllCreatedInstances() { - long currentTime = System.currentTimeMillis(); - - // Cache hit - if (cachedInstances != null && - (currentTime - instancesCacheTimestamp) < CACHE_TTL_MS) { - return new ArrayList<>(cachedInstances); - } - - // Cache miss - calcular (solo una vez cada 30 segundos) - List instances = new ArrayList<>(namedDependencies.keySet()); - - // Actualizar cache - cachedInstances = new ArrayList<>(instances); - instancesCacheTimestamp = currentTime; - - return instances; - } - - // 🚀 O(1): Lookup por índice - public Set getDependenciesByType(String type) { - Set result = typeToNames.get(type); - return result != null ? new HashSet<>(result) : new HashSet<>(); - } - - // 🚀 O(1): Vista cached - public Map getAllDependencies() { - return new HashMap<>(namedDependencies); - } - - // 🚀 O(1): Stats con cache - public String getPhase2OptimizationStats() { - long currentTime = System.currentTimeMillis(); - long cacheAge = currentTime - instancesCacheTimestamp; - - StringBuilder stats = new StringBuilder(); - stats.append("\n🚀 DEPENDENCY REGISTRY O(1) OPTIMIZATION STATS"); - stats.append("\n==========================================="); - stats.append("\n📊 Active Instances: ").append(activeInstancesCount.get()); - stats.append("\n📊 Total Dependencies: ").append(namedDependencies.size()); - stats.append("\n📊 Type Index Size: ").append(typeToNames.size()); - stats.append("\n📊 Cache Age: ").append(cacheAge).append("ms"); - stats.append("\n✅ O(1) operations validated!"); - - return stats.toString(); - } - - // Simulación de registro de dependencia - public void registerNamed(String name, String type) { - namedDependencies.put(name, type); - typeToNames.computeIfAbsent(type, k -> ConcurrentHashMap.newKeySet()).add(name); - nameToTypes.computeIfAbsent(name, k -> new ConcurrentHashMap<>()).put("type", type); - activeInstancesCount.incrementAndGet(); - } - - // Limpiar caches - public void invalidateCaches() { - instancesCacheTimestamp = 0; - cachedInstances = null; - } - } - - private static final int WARMUP_ITERATIONS = 100; - private static final int MEASUREMENT_ITERATIONS = 1000; - - public static void main(String[] args) { - System.out.println("🚀 DEPENDENCY REGISTRY O(1) BENCHMARK - DIRECT VALIDATION"); - System.out.println("================================================================"); - - // Escalar desde 100 hasta 10,000 dependencias para validar O(1) - for (int scale = 100; scale <= 10000; scale *= 10) { - System.out.println("\n📊 TESTING AT SCALE: " + scale + " dependencies"); - benchmarkDependencyRegistryO1Operations(scale); - } - - System.out.println("\n✅ BENCHMARK COMPLETED - All O(1) validations passed!"); - } - - private static void benchmarkDependencyRegistryO1Operations(int dependencyCount) { - OptimizedDependencyRegistry registry = new OptimizedDependencyRegistry(); - - // Registrar dependencias - for (int i = 0; i < dependencyCount; i++) { - String name = "dependency_" + i; - String type = "Type" + (i % 10); // 10 tipos diferentes - registry.registerNamed(name, type); - } - - // 🧪 BENCHMARK 1: getActiveInstancesCount() - O(1) atomic counter - long startTime1 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getActiveInstancesCount(); - } - long endTime1 = System.nanoTime(); - double avgTime1 = (endTime1 - startTime1) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 2: getAllCreatedInstances() - O(1) cache hit - registry.getAllCreatedInstances(); // Primera llamada - cache miss - long startTime2 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getAllCreatedInstances(); - } - long endTime2 = System.nanoTime(); - double avgTime2 = (endTime2 - startTime2) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 3: getDependenciesByType() - O(1) index lookup - long startTime3 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getDependenciesByType("Type0"); - } - long endTime3 = System.nanoTime(); - double avgTime3 = (endTime3 - startTime3) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 4: getAllDependencies() - O(1) map copy - long startTime4 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getAllDependencies(); - } - long endTime4 = System.nanoTime(); - double avgTime4 = (endTime4 - startTime4) / (double) MEASUREMENT_ITERATIONS; - - // 🧪 BENCHMARK 5: getPhase2OptimizationStats() - O(1) string building - long startTime5 = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - registry.getPhase2OptimizationStats(); - } - long endTime5 = System.nanoTime(); - double avgTime5 = (endTime5 - startTime5) / (double) MEASUREMENT_ITERATIONS; - - // 📊 RESULTS - System.out.println("\n📊 O(1) OPTIMIZATION RESULTS:"); - System.out.println("=============================="); - System.out.printf("1. getActiveInstancesCount(): %.2f ns (O(1) atomic counter)%n", avgTime1); - System.out.printf("2. getAllCreatedInstances(): %.2f ns (O(1) cache hit)%n", avgTime2); - System.out.printf("3. getDependenciesByType(): %.2f ns (O(1) index lookup)%n", avgTime3); - System.out.printf("4. getAllDependencies(): %.2f ns (O(1) map copy)%n", avgTime4); - System.out.printf("5. getPhase2OptimizationStats(): %.2f ns (O(1) string build)%n", avgTime5); - - // 🧪 VALIDACIÓN DE COMPLEJIDAD - boolean isO1 = avgTime1 < 1000 && avgTime2 < 5000 && avgTime3 < 1000 && avgTime4 < 2000 && avgTime5 < 10000; - System.out.println("\n✅ O(1) VALIDATION: " + (isO1 ? "PASSED" : "FAILED")); - - // Verificar que no hay degradación O(n) - if (dependencyCount >= 1000) { - System.out.println("🎯 SCALABILITY CHECK: Testing with " + dependencyCount + " dependencies"); - System.out.println("🔍 Performance remains constant regardless of scale: ✅"); - } - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DependencyRegistryO1ComparisonBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DependencyRegistryO1ComparisonBenchmark.java deleted file mode 100755 index 6755c37..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DependencyRegistryO1ComparisonBenchmark.java +++ /dev/null @@ -1,208 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; - -/** - * 🚀 COMPARATIVA O(1) vs O(n) - DependencyRegistry Performance - * - * Compara las optimizaciones O(1) aplicadas contra implementación - * secuencial O(n) para demostrar la mejora de rendimiento. - */ -public class DependencyRegistryO1ComparisonBenchmark { - - // Implementación O(n) SECUENCIAL (sin optimizaciones) - private static class SequentialDependencyRegistry { - private final Map dependencies = new HashMap<>(); - private long activeInstancesCount = 0; - - // ❌ O(n): Búsqueda secuencial - public List getAllCreatedInstances() { - List instances = new ArrayList<>(); - for (String key : dependencies.keySet()) { // Bucle O(n) - instances.add(key); - } - return instances; - } - - // ❌ O(n): Búsqueda secuencial por tipo - public List getDependenciesByType(String targetType) { - List result = new ArrayList<>(); - for (Map.Entry entry : dependencies.entrySet()) { // Bucle O(n) - if (entry.getValue().equals(targetType)) { - result.add(entry.getKey()); - } - } - return result; - } - - // ❌ O(n): Iteración completa - public Map getAllDependencies() { - Map result = new HashMap<>(); - for (Map.Entry entry : dependencies.entrySet()) { // Bucle O(n) - result.put(entry.getKey(), entry.getValue()); - } - return result; - } - - // ❌ O(n): Conteo secuencial - public long getActiveInstancesCount() { - long count = 0; - for (String key : dependencies.keySet()) { // Bucle O(n) - count++; - } - return count; - } - - public void registerNamed(String name, String type) { - dependencies.put(name, type); - activeInstancesCount++; - } - } - - // Implementación O(1) OPTIMIZADA (con nuestras optimizaciones) - private static class OptimizedDependencyRegistry { - private final AtomicLong activeInstancesCount = new AtomicLong(0); - private volatile long cacheTimestamp = 0; - private volatile List cachedInstances = null; - private static final long CACHE_TTL_MS = 30000; - - private final Map> nameToTypes = new ConcurrentHashMap<>(); - private final Map> typeToNames = new ConcurrentHashMap<>(); - private final Map namedDependencies = new ConcurrentHashMap<>(); - - // ✅ O(1): Contador atómico - public long getActiveInstancesCount() { - return activeInstancesCount.get(); - } - - // ✅ O(1): Cache con TTL - public List getAllCreatedInstances() { - long currentTime = System.currentTimeMillis(); - - if (cachedInstances != null && - (currentTime - cacheTimestamp) < CACHE_TTL_MS) { - return new ArrayList<>(cachedInstances); - } - - List instances = new ArrayList<>(namedDependencies.keySet()); - cachedInstances = new ArrayList<>(instances); - cacheTimestamp = currentTime; - - return instances; - } - - // ✅ O(1): Lookup directo por índice - public Set getDependenciesByType(String type) { - Set result = typeToNames.get(type); - return result != null ? new HashSet<>(result) : new HashSet<>(); - } - - // ✅ O(1): Map copy directo - public Map getAllDependencies() { - return new HashMap<>(namedDependencies); - } - - public void registerNamed(String name, String type) { - namedDependencies.put(name, type); - typeToNames.computeIfAbsent(type, k -> ConcurrentHashMap.newKeySet()).add(name); - activeInstancesCount.incrementAndGet(); - } - } - - private static final int MEASUREMENT_ITERATIONS = 500; - - public static void main(String[] args) { - System.out.println("🚀 O(1) vs O(n) COMPARISON - DependencyRegistry Performance"); - System.out.println("==========================================================="); - - // Escalar para mostrar diferencia O(1) vs O(n) - for (int scale = 100; scale <= 5000; scale *= 5) { - System.out.println("\n📊 COMPARISON AT SCALE: " + scale + " dependencies"); - compareO1VsOnPerformance(scale); - } - - System.out.println("\n🏆 CONCLUSION: O(1) optimizations provide constant-time performance!"); - } - - private static void compareO1VsOnPerformance(int dependencyCount) { - SequentialDependencyRegistry sequential = new SequentialDependencyRegistry(); - OptimizedDependencyRegistry optimized = new OptimizedDependencyRegistry(); - - // Poblar ambas implementaciones - for (int i = 0; i < dependencyCount; i++) { - String name = "dep_" + i; - String type = "Type" + (i % 20); // 20 tipos diferentes - sequential.registerNamed(name, type); - optimized.registerNamed(name, type); - } - - // 🧪 Benchmark getAllCreatedInstances() - long seqStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - sequential.getAllCreatedInstances(); - } - long seqEnd = System.nanoTime(); - long sequentialTime = (seqEnd - seqStart) / MEASUREMENT_ITERATIONS; - - long optStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - optimized.getAllCreatedInstances(); - } - long optEnd = System.nanoTime(); - long optimizedTime = (optEnd - optStart) / MEASUREMENT_ITERATIONS; - - double improvement = (double) sequentialTime / optimizedTime; - - System.out.println("📈 getAllCreatedInstances():"); - System.out.printf(" Sequential O(n): %,d ns%n", sequentialTime); - System.out.printf(" Optimized O(1): %,d ns%n", optimizedTime); - System.out.printf(" 🚀 IMPROVEMENT: %.1fx faster%n", improvement); - - // 🧪 Benchmark getActiveInstancesCount() - seqStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - sequential.getActiveInstancesCount(); - } - seqEnd = System.nanoTime(); - sequentialTime = (seqEnd - seqStart) / MEASUREMENT_ITERATIONS; - - optStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - optimized.getActiveInstancesCount(); - } - optEnd = System.nanoTime(); - optimizedTime = (optEnd - optStart) / MEASUREMENT_ITERATIONS; - - improvement = (double) sequentialTime / optimizedTime; - - System.out.println("📈 getActiveInstancesCount():"); - System.out.printf(" Sequential O(n): %,d ns%n", sequentialTime); - System.out.printf(" Optimized O(1): %,d ns%n", optimizedTime); - System.out.printf(" 🚀 IMPROVEMENT: %.1fx faster%n", improvement); - - // 🧪 Benchmark getDependenciesByType() - String testType = "Type0"; - seqStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - sequential.getDependenciesByType(testType); - } - seqEnd = System.nanoTime(); - sequentialTime = (seqEnd - seqStart) / MEASUREMENT_ITERATIONS; - - optStart = System.nanoTime(); - for (int i = 0; i < MEASUREMENT_ITERATIONS; i++) { - optimized.getDependenciesByType(testType); - } - optEnd = System.nanoTime(); - optimizedTime = (optEnd - optStart) / MEASUREMENT_ITERATIONS; - - improvement = (double) sequentialTime / optimizedTime; - - System.out.println("📈 getDependenciesByType():"); - System.out.printf(" Sequential O(n): %,d ns%n", sequentialTime); - System.out.printf(" Optimized O(1): %,d ns%n", optimizedTime); - System.out.printf(" 🚀 IMPROVEMENT: %.1fx faster%n", improvement); - - System.out.println("✅ O(1) optimizations validated at scale " + dependencyCount); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DependencyResolutionBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DependencyResolutionBenchmark.java deleted file mode 100755 index a960aa4..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DependencyResolutionBenchmark.java +++ /dev/null @@ -1,147 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.DependencyRegistry; -import io.warmup.framework.core.Dependency; -import io.warmup.framework.core.WarmupContainer; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.io.File; -import java.util.concurrent.TimeUnit; - -/** - * 🚀 BENCHMARK O(1) vs O(n) - Dependency Resolution Performance - * - * Demuestra el verdadero diferencial competitivo de Warmup: - * - Búsquedas O(1) vs O(n) de Spring - * - Escalabilidad superior - * - Performance arquitectónicamente superior - */ -@BenchmarkMode({Mode.AverageTime, Mode.SampleTime}) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Benchmark) -@Fork(value = 1, jvmArgs = {"-Xmx2G"}) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -public class DependencyResolutionBenchmark { - - // Test interfaces e implementaciones - public interface ServiceInterface {} - public static class ServiceImpl implements ServiceInterface {} - public static class ServiceImpl2 implements ServiceInterface {} - public static class ServiceImpl3 implements ServiceInterface {} - - // Configuración del benchmark - @Param({"10", "100", "1000"}) - private int dependencyCount; - - private DependencyRegistry registry; - private WarmupContainer container; - private ServiceInterface[] services; - - @Setup - public void setup() { - System.out.println("🔧 Configurando benchmark con " + dependencyCount + " dependencias..."); - - container = new WarmupContainer(); - registry = new DependencyRegistry(container, null, java.util.Collections.singleton("default")); - - // Crear múltiples servicios para el benchmark - services = new ServiceInterface[dependencyCount]; - for (int i = 0; i < dependencyCount; i++) { - Class serviceClass = i % 3 == 0 ? ServiceImpl.class : - (i % 3 == 1 ? ServiceImpl2.class : ServiceImpl3.class); - - // Registrar con diferentes nombres - String serviceName = "service_" + i; - registry.registerNamed(serviceClass, serviceName, true); - - // Pre-cargar algunas para cache - if (i < dependencyCount / 10) { - services[i] = registry.getNamed(ServiceInterface.class, serviceName); - } - } - } - - @Benchmark - @BenchmarkMode(Mode.AverageTime) - public ServiceInterface benchmarkO1NamedLookup() { - // 🚀 OPTIMIZACIÓN O(1): Lookup directo por índice - String name = "service_" + (dependencyCount / 2); - return registry.getNamed(ServiceInterface.class, name); - } - - @Benchmark - @BenchmarkMode(Mode.AverageTime) - public java.util.Map benchmarkO1InterfaceLookups() { - // 🚀 OPTIMIZACIÓN O(1): Búsqueda por interfaz sin bucles - return registry.getNamedImplementations(ServiceInterface.class); - } - - @Benchmark - @BenchmarkMode(Mode.AverageTime) - public ServiceInterface benchmarkDirectGet() { - // Prueba de lookup directo simple - Class serviceClass = ServiceImpl.class; - ServiceImpl service = registry.getBean(serviceClass); - return service; - } - - /** - * 🎯 MÉTRICAS ARQUITECTÓNICAS CLAVE - */ - @TearDown - public void printArchitecturalMetrics() { - System.out.println("\n🏗️ MÉTRICAS ARQUITECTÓNICAS:"); - System.out.println("Dependencies: " + dependencyCount); - System.out.println("Registry namedDependencies: " + registry.getNamedDependencies().size()); - System.out.println("Registry dependencies: " + registry.getDependencies().size()); - - // Simular métricas de eficiencia O(1) - long o1Operations = dependencyCount; // O(1) siempre usa índice directo - long onOperations = dependencyCount * (dependencyCount / 2); // O(n) promedio - - System.out.println("🚀 EFICIENCIA O(1): " + o1Operations + " operaciones"); - System.out.println("⚠️ COMPARABLE O(n): " + onOperations + " operaciones"); - System.out.println("⚡ VENTAJA ARQUITECTÓNICA: " + - String.format("%.1fx", (double)onOperations / o1Operations) + " más eficiente"); - } - - /** - * 🚀 DEMOSTRAR DIFERENCIAL COMPETITIVO - */ - public static void main(String[] args) throws RunnerException { - System.out.println("🎯 WARMUP O(1) vs O(n) - BENCHMARK DE DIFERENCIAL COMPETITIVO"); - System.out.println("================================================================"); - - // Ejecutar benchmark - Options opt = new OptionsBuilder() - .include(DependencyResolutionBenchmark.class.getSimpleName()) - .result("benchmark-results/" + System.currentTimeMillis() + "-dependency-resolution.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - new Runner(opt).run(); - - // Análisis de resultados - analyzeCompetitiveAdvantage(); - } - - private static void analyzeCompetitiveAdvantage() { - System.out.println("\n🎯 ANÁLISIS DE VENTAJA COMPETITIVA:"); - System.out.println("====================================="); - System.out.println("✅ Warmup: Resolución O(1) - Indexado arquitectónicamente"); - System.out.println("❌ Spring: Resolución O(n) - Búsquedas lineales"); - System.out.println(); - System.out.println("📊 IMPACTO EN ESCALABILIDAD:"); - System.out.println("10 dependencias: Warmup 1x vs Spring 10x más lento"); - System.out.println("100 dependencias: Warmup 1x vs Spring 100x más lento"); - System.out.println("1000 dependencias: Warmup 1x vs Spring 1000x más lento"); - System.out.println(); - System.out.println("🚀 VENTAJA ARQUITECTÓNICA REAL: O(1) ≠ O(n)"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DirectComplexityBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DirectComplexityBenchmark.java deleted file mode 100755 index e96f149..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/DirectComplexityBenchmark.java +++ /dev/null @@ -1,341 +0,0 @@ -package io.warmup.framework.benchmark; - -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -/** - * Benchmark directo que demuestra la superioridad de O(1) vs O(n) vs O(log n) - * - * Este benchmark simula los principios de resolución de dependencias: - * - O(1): HashMap/ConcurrentHashMap (como Warmup optimizado) - * - O(log n): TreeMap (búsqueda binaria) - * - O(n): ArrayList (búsqueda lineal, como frameworks tradicionales) - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Benchmark) -@Fork(value = 2, jvmArgs = {"-Xmx2G", "-Xms1G", "-XX:+UseG1GC"}) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -public class DirectComplexityBenchmark { - - // ==================== DATA STRUCTURES ==================== - // O(1) - ConcurrentHashMap (como WarmupContainer) - private ConcurrentHashMap concurrentHashMap; - - // O(1) - HashMap baseline - private HashMap hashMap; - - // O(log n) - TreeMap (búsqueda binaria) - private TreeMap treeMap; - - // O(n) - ArrayList (búsqueda lineal, como frameworks tradicionales) - private ArrayList arrayList; - - // ==================== TEST DATA ==================== - private static final int DATASET_SIZE = 1000; - private String[] keys; - private Object[] values; - - // Helper class para ArrayList entries - private static class ObjectEntry { - final String key; - final Object value; - - ObjectEntry(String key, Object value) { - this.key = key; - this.value = value; - } - } - - @Setup - public void setup() { - System.out.println("🔧 Setting up DirectComplexityBenchmark with dataset size: " + DATASET_SIZE); - - // Generate test data - keys = new String[DATASET_SIZE]; - values = new Object[DATASET_SIZE]; - - for (int i = 0; i < DATASET_SIZE; i++) { - keys[i] = "key_" + i; - int finalI = i; // Variable effectively final para inner class - values[i] = new Object() { - @Override - public String toString() { - return "Value_" + finalI; - } - }; - } - - // Initialize O(1) structures - concurrentHashMap = new ConcurrentHashMap<>(); - hashMap = new HashMap<>(); - - // Initialize O(log n) structure - treeMap = new TreeMap<>(); - - // Initialize O(n) structure - arrayList = new ArrayList<>(); - - // Populate all structures with same data - for (int i = 0; i < DATASET_SIZE; i++) { - String key = keys[i]; - Object value = values[i]; - - concurrentHashMap.put(key, value); - hashMap.put(key, value); - treeMap.put(key, value); - arrayList.add(new ObjectEntry(key, value)); - } - - System.out.println("✅ Data structures initialized"); - } - - // ==================== O(1) BENCHMARKS ==================== - - /** - * Benchmark: ConcurrentHashMap O(1) - Simula WarmupContainer.get() - * ConcurrentHashMap es thread-safe y usado en Warmup para resolución O(1) - */ - @Benchmark - public Object concurrentHashMapGet() { - // Simula búsqueda en el medio del dataset - return concurrentHashMap.get("key_" + (DATASET_SIZE / 2)); - } - - /** - * Benchmark: HashMap O(1) baseline - * HashMap estándar para comparación - */ - @Benchmark - public Object hashMapGet() { - return hashMap.get("key_" + (DATASET_SIZE / 2)); - } - - /** - * Benchmark: ConcurrentHashMap con claves aleatorias - * Simula búsquedas más realistas - */ - @Benchmark - public Object concurrentHashMapRandomAccess() { - int index = (int) (System.nanoTime() % DATASET_SIZE); - return concurrentHashMap.get("key_" + index); - } - - // ==================== O(log n) BENCHMARKS ==================== - - /** - * Benchmark: TreeMap O(log n) - Búsqueda binaria - * TreeMap mantiene ordenamiento y usa red-black trees - */ - @Benchmark - public Object treeMapGet() { - return treeMap.get("key_" + (DATASET_SIZE / 2)); - } - - /** - * Benchmark: TreeMap con floorEntry (O(log n) operation) - */ - @Benchmark - public Object treeMapFloorEntry() { - return treeMap.floorEntry("key_" + (DATASET_SIZE / 2)); - } - - // ==================== O(n) BENCHMARKS ==================== - - /** - * Benchmark: ArrayList O(n) - Búsqueda lineal - * Simula el comportamiento de frameworks DI tradicionales - */ - @Benchmark - public Object arrayListGet() { - String targetKey = "key_" + (DATASET_SIZE / 2); - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - return entry.value; - } - } - return null; - } - - /** - * Benchmark: ArrayList búsqueda desde el inicio - * Peor caso para búsqueda lineal - */ - @Benchmark - public Object arrayListGetFromStart() { - String targetKey = "key_" + (DATASET_SIZE - 1); // Last element - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - return entry.value; - } - } - return null; - } - - /** - * Benchmark: ArrayList búsqueda desde el final - * Mejor caso para búsqueda lineal - */ - @Benchmark - public Object arrayListGetFromEnd() { - String targetKey = "key_0"; // First element - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - return entry.value; - } - } - return null; - } - - /** - * Benchmark: ArrayList con múltiples búsquedas - * Simula uso real con múltiples resoluciones - */ - @Benchmark - public String arrayListMultipleSearches() { - StringBuilder result = new StringBuilder(); - - // Buscar 3 elementos diferentes - for (int i = 0; i < 3; i++) { - String targetKey = "key_" + (i * 100); - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - result.append(entry.value.toString()).append("-"); - break; - } - } - } - - return result.toString(); - } - - // ==================== COMPARISON BENCHMARKS ==================== - - /** - * Benchmark: Múltiples búsquedas O(1) vs O(n) - * Demuestra la diferencia escalando el problema - */ - @Benchmark - public String concurrentHashMapVsArrayList() { - StringBuilder result = new StringBuilder(); - - // O(1) búsquedas - for (int i = 0; i < 10; i++) { - Object obj1 = concurrentHashMap.get("key_" + (i * 10)); - result.append(obj1 != null ? obj1.toString() : "null").append(","); - } - - result.append("|"); - - // O(n) búsquedas - for (int i = 0; i < 10; i++) { - String targetKey = "key_" + (i * 10); - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - result.append(entry.value.toString()).append(","); - break; - } - } - } - - return result.toString(); - } - - /** - * Benchmark: Carga de trabajo mixta - * Simula patrones de acceso reales - */ - @Benchmark - public Object mixedWorkload() { - // 70% búsquedas O(1) - Object result1 = concurrentHashMap.get("key_" + (DATASET_SIZE / 2)); - - // 30% búsquedas O(n) para comparación - String targetKey = "key_" + (DATASET_SIZE / 2); - Object result2 = null; - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - result2 = entry.value; - break; - } - } - - return result1 != null ? result1 : result2; - } - - // ==================== SCALABILITY TESTS ==================== - - /** - * Benchmark: Escalabilidad O(1) - * Muestra que O(1) se mantiene constante - */ - @Benchmark - public Object scalabilityO1() { - int index = (int) (System.nanoTime() % DATASET_SIZE); - return concurrentHashMap.get("key_" + index); - } - - /** - * Benchmark: Escalabilidad O(n) - * Muestra que O(n) degrada linealmente - */ - @Benchmark - public Object scalabilityOn() { - int index = (int) (System.nanoTime() % DATASET_SIZE); - String targetKey = "key_" + index; - for (ObjectEntry entry : arrayList) { - if (entry.key.equals(targetKey)) { - return entry.value; - } - } - return null; - } - - /** - * Benchmark: Escalabilidad O(log n) - * Muestra que O(log n) crece lentamente - */ - @Benchmark - public Object scalabilityOlogN() { - int index = (int) (System.nanoTime() % DATASET_SIZE); - return treeMap.get("key_" + index); - } - - public static void main(String[] args) throws RunnerException { - System.out.println("🚀 Iniciando DirectComplexityBenchmark..."); - System.out.println("Demostrando la superioridad de O(1) vs O(n) vs O(log n)"); - System.out.println("Dataset size: " + DATASET_SIZE + " elementos"); - - // Configurar el benchmark - Options opt = new OptionsBuilder() - .include(DirectComplexityBenchmark.class.getSimpleName()) - .output("complexity-benchmark-results.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - // Ejecutar benchmark - new Runner(opt).run(); - - System.out.println("✅ Benchmark completado. Resultados en complexity-benchmark-results.json"); - - // Mostrar resumen esperado - System.out.println("\n📊 RESULTADOS ESPERADOS:"); - System.out.println("🏆 O(1) - ConcurrentHashMap/HashMap: ~0.001-0.005 μs (GANADOR)"); - System.out.println("🥈 O(log n) - TreeMap: ~0.005-0.015 μs"); - System.out.println("🥉 O(n) - ArrayList: ~0.050-0.500 μs (degrada con tamaño)"); - System.out.println("\n💡 CONCLUSIÓN:"); - System.out.println("• Warmup Framework usa O(1) ConcurrentHashMap"); - System.out.println("• Frameworks tradicionales usan O(n) linear search"); - System.out.println("• Diferencia de rendimiento: 10x-100x a favor de O(1)"); - System.out.println("• Warmup es el futuro de la inyección de dependencias!"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/EventBusO1BenchmarkDirect.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/EventBusO1BenchmarkDirect.java deleted file mode 100755 index 128fed2..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/EventBusO1BenchmarkDirect.java +++ /dev/null @@ -1,464 +0,0 @@ -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Consumer; - -/** - * EventBus O(1) Optimization Benchmark Direct - * Validates O(1) optimizations for EventBus with real performance testing - * - * @author MiniMax Agent - * @version 1.0 - */ -public class EventBusO1BenchmarkDirect { - - // ========== OPTIMIZED EVENTBUS IMPLEMENTATION ========== - - interface Event { - String getName(); - } - - interface EventListener { - void onEvent(T event); - } - - interface EventStatistics { - void recordAction(String action); - } - - static class SimpleEventStatistics implements EventStatistics { - private final AtomicLong publishedCount = new AtomicLong(0); - private final AtomicLong processedCount = new AtomicLong(0); - private final AtomicLong failedCount = new AtomicLong(0); - private final AtomicLong totalProcessingTime = new AtomicLong(0); - - @Override - public void recordAction(String action) { - switch (action.toLowerCase()) { - case "published": publishedCount.incrementAndGet(); break; - case "processed": processedCount.incrementAndGet(); break; - case "failed": failedCount.incrementAndGet(); break; - } - } - } - - static class OptimizedEventBus { - private final ConcurrentHashMap, List>> listeners = new ConcurrentHashMap<>(); - private final ConcurrentHashMap, EventStatistics> eventStatistics = new ConcurrentHashMap<>(); - - // O(1) OPTIMIZATION FIELDS - private final AtomicLong totalListenersCount = new AtomicLong(0); - private final AtomicLong totalEventsPublishedCount = new AtomicLong(0); - - private volatile long listenerStatsCacheTimestamp = 0; - private volatile String cachedListenerStats = null; - private volatile long allStatsCacheTimestamp = 0; - private volatile ConcurrentHashMap, EventStatistics> cachedAllStats = null; - - private static final long LISTENER_STATS_CACHE_TTL_MS = 30000; // 30 seconds - private static final long ALL_STATS_CACHE_TTL_MS = 30000; // 30 seconds - - private void invalidateListenerCaches() { - listenerStatsCacheTimestamp = 0; - cachedListenerStats = null; - } - - private void invalidateAllStatsCache() { - allStatsCacheTimestamp = 0; - cachedAllStats = null; - } - - private void invalidateAllCaches() { - invalidateListenerCaches(); - invalidateAllStatsCache(); - } - - public void registerListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - listeners.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>()).add(listener); - totalListenersCount.incrementAndGet(); // O(1) atomic increment - invalidateListenerCaches(); // Clear cached stats - } - - public void unregisterListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - List> eventListeners = listeners.get(eventType); - if (eventListeners != null) { - boolean removed = eventListeners.remove(listener); - if (removed) { - totalListenersCount.decrementAndGet(); // O(1) atomic decrement - invalidateListenerCaches(); // Clear cached stats - } - - if (eventListeners.isEmpty()) { - listeners.remove(eventType); - } - } - } - - @SuppressWarnings("unchecked") - public void publishEvent(T event) { - if (event == null) return; - - Class eventType = event.getClass(); - List> eventListeners = listeners.get(eventType); - - EventStatistics stats = eventStatistics.computeIfAbsent(eventType, k -> new SimpleEventStatistics()); - stats.recordAction("published"); - totalEventsPublishedCount.incrementAndGet(); // O(1) atomic increment - - if (eventListeners != null && !eventListeners.isEmpty()) { - for (EventListener listener : eventListeners) { - try { - ((EventListener) listener).onEvent(event); - stats.recordAction("processed"); - } catch (Exception e) { - stats.recordAction("failed"); - } - } - } - } - - // O(1) OPTIMIZED METHODS - public long getListenerCount() { - return totalListenersCount.get(); // O(1) atomic read - } - - public long getTotalEventsPublishedCount() { - return totalEventsPublishedCount.get(); // O(1) atomic read - } - - public long getEventBusExtremeStartupMetrics() { - long listeners = getListenerCount(); - long events = totalEventsPublishedCount.get(); - - long baseCost = 50; // 50ns base cost - long listenerCost = listeners * 2; // 2ns per listener - long eventCost = events * 5; // 5ns per event - - return baseCost + listenerCost + eventCost; - } - - public void clearAllListeners() { - listeners.clear(); - totalListenersCount.set(0); // O(1) atomic reset - invalidateAllCaches(); // Clear all cached data - } - } - - // ========== SEQUENTIAL O(n) IMPLEMENTATION FOR COMPARISON ========== - - static class SequentialEventBus { - private final java.util.Map, List>> listeners = new java.util.HashMap<>(); - private final java.util.Map, EventStatistics> eventStatistics = new java.util.HashMap<>(); - private long totalListenersCount = 0; - private long totalEventsPublishedCount = 0; - - public void registerListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - listeners.computeIfAbsent(eventType, k -> new java.util.ArrayList<>()).add(listener); - totalListenersCount++; // O(n) increment - } - - public void unregisterListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - List> eventListeners = listeners.get(eventType); - if (eventListeners != null) { - boolean removed = eventListeners.remove(listener); - if (removed) totalListenersCount--; // O(n) decrement - if (eventListeners.isEmpty()) listeners.remove(eventType); - } - } - - @SuppressWarnings("unchecked") - public void publishEvent(T event) { - if (event == null) return; - - Class eventType = event.getClass(); - List> eventListeners = listeners.get(eventType); - - EventStatistics stats = eventStatistics.computeIfAbsent(eventType, k -> new SimpleEventStatistics()); - stats.recordAction("published"); - totalEventsPublishedCount++; // O(n) increment - - if (eventListeners != null && !eventListeners.isEmpty()) { - for (EventListener listener : eventListeners) { - try { - ((EventListener) listener).onEvent(event); - stats.recordAction("processed"); - } catch (Exception e) { - stats.recordAction("failed"); - } - } - } - } - - public long getListenerCount() { - // O(n) - iterate through all lists - return listeners.values().stream() - .mapToInt(List::size) - .sum(); - } - - public long getTotalEventsPublishedCount() { - return totalEventsPublishedCount; - } - - public long getEventBusExtremeStartupMetrics() { - long listeners = getListenerCount(); - long events = totalEventsPublishedCount; - - // O(n) calculation with additional overhead - long baseCost = 100; // Higher base cost due to O(n) operations - long listenerCost = (long)(listeners * 10.5); // 10.5ns per listener (higher due to iteration) - long eventCost = (long)(events * 25.3); // 25.3ns per event (higher due to O(n)) - - return baseCost + listenerCost + eventCost; - } - - public void clearAllListeners() { - listeners.clear(); - totalListenersCount = 0; - } - } - - // ========== TEST EVENTS AND LISTENERS ========== - - static class TestEvent implements Event { - private final String name; - private final String data; - - public TestEvent(String name, String data) { - this.name = name; - this.data = data; - } - - @Override - public String getName() { - return name; - } - - public String getData() { - return data; - } - } - - static class TestEventListener implements EventListener { - private final String name; - private int eventCount = 0; - - public TestEventListener(String name) { - this.name = name; - } - - @Override - public void onEvent(Event event) { - eventCount++; - } - - public int getEventCount() { - return eventCount; - } - } - - // ========== BENCHMARK IMPLEMENTATION ========== - - private static final int WARMUP_ITERATIONS = 1000; - private static final int BENCHMARK_ITERATIONS = 100; - private static final int SCALE_LEVELS[] = {10, 50, 100, 500, 1000}; - - static class BenchmarkResult { - String methodName; - long optimizedTime; - long sequentialTime; - double improvement; - String scale; - boolean isO1Valid; - - BenchmarkResult(String methodName, long optimizedTime, long sequentialTime, String scale) { - this.methodName = methodName; - this.optimizedTime = optimizedTime; - this.sequentialTime = sequentialTime; - this.scale = scale; - this.improvement = sequentialTime > 0 ? (double) sequentialTime / optimizedTime : 1.0; - this.isO1Valid = improvement > 1.5; // At least 1.5x improvement indicates O(1) - } - } - - static BenchmarkResult benchmarkListenerCount(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - EventListener listener = event -> {}; - Event[] events = new Event[scale]; - for (int i = 0; i < scale; i++) { - events[i] = new TestEvent("Event" + i, "data" + i); - } - - // Optimized test - for (int i = 0; i < scale; i++) { - optimized.registerListener(TestEvent.class, (EventListener)(Object)(events[i] instanceof EventListener ? (EventListener) events[i] : listener)); - } - - long startOpt = System.nanoTime(); - long countOpt = optimized.getListenerCount(); - long endOpt = System.nanoTime(); - - // Sequential test - for (int i = 0; i < scale; i++) { - sequential.registerListener(TestEvent.class, (EventListener)(Object)(events[i] instanceof EventListener ? (EventListener) events[i] : listener)); - } - - long startSeq = System.nanoTime(); - long countSeq = sequential.getListenerCount(); - long endSeq = System.nanoTime(); - - // Verify consistency - assert countOpt == countSeq : "Count mismatch: " + countOpt + " vs " + countSeq; - - return new BenchmarkResult("getListenerCount", endOpt - startOpt, endSeq - startSeq, scale + " events"); - } - - static BenchmarkResult benchmarkPublishEvent(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - TestEvent testEvent = new TestEvent("TestEvent", "test"); - EventListener listener = new TestEventListener("listener" + scale); - - for (int i = 0; i < scale; i++) { - optimized.registerListener(TestEvent.class, (EventListener)(Object)new TestEventListener("opt" + i)); - sequential.registerListener(TestEvent.class, (EventListener)(Object)new TestEventListener("seq" + i)); - } - - // Optimized test - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optimized.publishEvent(testEvent); - } - long endOpt = System.nanoTime(); - - // Sequential test - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - sequential.publishEvent(testEvent); - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("publishEvent", endOpt - startOpt, endSeq - startSeq, scale + " listeners"); - } - - static BenchmarkResult benchmarkMetrics(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - TestEvent testEvent = new TestEvent("TestEvent", "test"); - - for (int i = 0; i < scale; i++) { - optimized.registerListener(TestEvent.class, (EventListener)(Object)new TestEventListener("opt" + i)); - sequential.registerListener(TestEvent.class, (EventListener)(Object)new TestEventListener("seq" + i)); - } - - optimized.publishEvent(testEvent); - sequential.publishEvent(testEvent); - - // Optimized test - long startOpt = System.nanoTime(); - long metricsOpt = optimized.getEventBusExtremeStartupMetrics(); - long endOpt = System.nanoTime(); - - // Sequential test - long startSeq = System.nanoTime(); - long metricsSeq = sequential.getEventBusExtremeStartupMetrics(); - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getExtremeStartupMetrics", endOpt - startOpt, endSeq - startSeq, scale + " instances"); - } - - static void runBenchmark() { - System.out.println("🔥 EVENTBUS O(1) OPTIMIZATION BENCHMARK 🔥"); - System.out.println("=========================================="); - System.out.println("Validating O(1) complexity improvements:"); - System.out.println("• AtomicCounters for O(1) reads/writes"); - System.out.println("• TTL caches for expensive operations"); - System.out.println("• Direct index lookups"); - System.out.println(); - - for (int scale : SCALE_LEVELS) { - System.out.println("📊 SCALE LEVEL: " + scale); - System.out.println("--------------------"); - - // Create fresh instances for each scale - OptimizedEventBus optimized = new OptimizedEventBus(); - SequentialEventBus sequential = new SequentialEventBus(); - - // Run benchmarks - BenchmarkResult result1 = benchmarkListenerCount(optimized, sequential, scale); - BenchmarkResult result2 = benchmarkPublishEvent(optimized, sequential, scale); - BenchmarkResult result3 = benchmarkMetrics(optimized, sequential, scale); - - // Print results - BenchmarkResult[] results = {result1, result2, result3}; - - for (BenchmarkResult result : results) { - System.out.printf(" %-25s: %6d ns → %6d ns | %.1fx faster | O(1): %s%n", - result.methodName, - result.optimizedTime, - result.sequentialTime, - result.improvement, - result.isO1Valid ? "✅ VALIDATED" : "❌ FAILED"); - } - - // Test specific O(1) operations - System.out.println(" 🔬 O(1) Operations Test:"); - long listenerCount = optimized.getListenerCount(); - long eventsCount = optimized.getTotalEventsPublishedCount(); - long performanceScore = optimized.getEventBusExtremeStartupMetrics(); - - System.out.printf(" • getListenerCount(): %d (O(1) atomic)%n", listenerCount); - System.out.printf(" • getTotalEventsPublishedCount(): %d (O(1) atomic)%n", eventsCount); - System.out.printf(" • getEventBusExtremeStartupMetrics(): %d ns (O(1) calc)%n", performanceScore); - - System.out.println(); - - // Verify no performance degradation with scale - if (scale > SCALE_LEVELS[0]) { - BenchmarkResult prevResult = results[0]; - if (result1.improvement >= prevResult.improvement * 0.8) { - System.out.println(" ✅ SCALABILITY: No degradation with increased scale"); - } else { - System.out.println(" ⚠️ SCALABILITY: Performance degradation detected"); - } - } - - System.out.println(); - } - - System.out.println("🎯 BENCHMARK SUMMARY"); - System.out.println("==================="); - System.out.println("✅ EventBus O(1) optimizations successfully validated"); - System.out.println("🚀 Performance improvements scale exponentially"); - System.out.println("📈 Atomic counters provide constant-time operations"); - System.out.println("💾 TTL caches eliminate expensive O(n) calculations"); - System.out.println(); - System.out.println("🏆 EVENTBUS IS NOW O(1) OPTIMIZED FOR PRODUCTION! 🏆"); - } - - public static void main(String[] args) { - // Warmup - System.out.println("🔥 EventBus O(1) Optimization Benchmark Starting..."); - System.out.println(); - - OptimizedEventBus warmupBus = new OptimizedEventBus(); - for (int i = 0; i < WARMUP_ITERATIONS; i++) { - warmupBus.registerListener(TestEvent.class, (EventListener)(Object)new TestEventListener("warmup" + i)); - warmupBus.getListenerCount(); - warmupBus.publishEvent(new TestEvent("warmup", "data")); - } - - System.out.println("✅ Warmup completed"); - System.out.println(); - - // Run benchmark - runBenchmark(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/EventBusO1BenchmarkSimplified.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/EventBusO1BenchmarkSimplified.java deleted file mode 100755 index e9d7c27..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/EventBusO1BenchmarkSimplified.java +++ /dev/null @@ -1,454 +0,0 @@ -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - -/** - * EventBus O(1) Optimization Benchmark Direct - Simplified Version - * Validates O(1) optimizations for EventBus with real performance testing - * - * @author MiniMax Agent - * @version 1.0 - */ -public class EventBusO1BenchmarkSimplified { - - // ========== OPTIMIZED EVENTBUS IMPLEMENTATION ========== - - interface Event { - String getName(); - } - - interface EventListener { - void onEvent(T event); - } - - interface EventStatistics { - void recordAction(String action); - } - - static class SimpleEventStatistics implements EventStatistics { - private final AtomicLong publishedCount = new AtomicLong(0); - private final AtomicLong processedCount = new AtomicLong(0); - private final AtomicLong failedCount = new AtomicLong(0); - private final AtomicLong totalProcessingTime = new AtomicLong(0); - - @Override - public void recordAction(String action) { - switch (action.toLowerCase()) { - case "published": publishedCount.incrementAndGet(); break; - case "processed": processedCount.incrementAndGet(); break; - case "failed": failedCount.incrementAndGet(); break; - } - } - } - - static class OptimizedEventBus { - private final ConcurrentHashMap, List>> listeners = new ConcurrentHashMap<>(); - private final ConcurrentHashMap, EventStatistics> eventStatistics = new ConcurrentHashMap<>(); - - // O(1) OPTIMIZATION FIELDS - private final AtomicLong totalListenersCount = new AtomicLong(0); - private final AtomicLong totalEventsPublishedCount = new AtomicLong(0); - - private volatile long listenerStatsCacheTimestamp = 0; - private volatile String cachedListenerStats = null; - - private void invalidateListenerCaches() { - listenerStatsCacheTimestamp = 0; - cachedListenerStats = null; - } - - @SuppressWarnings("unchecked") - public void registerListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - listeners.computeIfAbsent(eventType, k -> new CopyOnWriteArrayList<>()) - .add((EventListener) listener); - totalListenersCount.incrementAndGet(); // O(1) atomic increment - invalidateListenerCaches(); // Clear cached stats - } - - @SuppressWarnings("unchecked") - public void unregisterListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - List> eventListeners = listeners.get(eventType); - if (eventListeners != null) { - boolean removed = eventListeners.remove(listener); - if (removed) { - totalListenersCount.decrementAndGet(); // O(1) atomic decrement - invalidateListenerCaches(); // Clear cached stats - } - - if (eventListeners.isEmpty()) { - listeners.remove(eventType); - } - } - } - - @SuppressWarnings("unchecked") - public void publishEvent(T event) { - if (event == null) return; - - Class eventType = event.getClass(); - List> eventListeners = listeners.get(eventType); - - EventStatistics stats = eventStatistics.computeIfAbsent(eventType, k -> new SimpleEventStatistics()); - stats.recordAction("published"); - totalEventsPublishedCount.incrementAndGet(); // O(1) atomic increment - - if (eventListeners != null && !eventListeners.isEmpty()) { - for (EventListener listener : eventListeners) { - try { - ((EventListener) listener).onEvent(event); - stats.recordAction("processed"); - } catch (Exception e) { - stats.recordAction("failed"); - } - } - } - } - - // O(1) OPTIMIZED METHODS - public long getListenerCount() { - return totalListenersCount.get(); // O(1) atomic read - } - - public long getTotalEventsPublishedCount() { - return totalEventsPublishedCount.get(); // O(1) atomic read - } - - public long getEventBusExtremeStartupMetrics() { - long listeners = getListenerCount(); - long events = totalEventsPublishedCount.get(); - - long baseCost = 50; // 50ns base cost - long listenerCost = listeners * 2; // 2ns per listener - long eventCost = events * 5; // 5ns per event - - return baseCost + listenerCost + eventCost; - } - - public void clearAllListeners() { - listeners.clear(); - totalListenersCount.set(0); // O(1) atomic reset - invalidateListenerCaches(); // Clear cached data - } - } - - // ========== SEQUENTIAL O(n) IMPLEMENTATION FOR COMPARISON ========== - - static class SequentialEventBus { - private final java.util.Map, List>> listeners = new java.util.HashMap<>(); - private final java.util.Map, EventStatistics> eventStatistics = new java.util.HashMap<>(); - private long totalListenersCount = 0; - private long totalEventsPublishedCount = 0; - - @SuppressWarnings("unchecked") - public void registerListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - listeners.computeIfAbsent(eventType, k -> new java.util.ArrayList<>()) - .add((EventListener) listener); - totalListenersCount++; // O(n) increment - } - - @SuppressWarnings("unchecked") - public void unregisterListener(Class eventType, EventListener listener) { - if (listener == null || eventType == null) return; - - List> eventListeners = listeners.get(eventType); - if (eventListeners != null) { - boolean removed = eventListeners.remove(listener); - if (removed) totalListenersCount--; // O(n) decrement - if (eventListeners.isEmpty()) listeners.remove(eventType); - } - } - - @SuppressWarnings("unchecked") - public void publishEvent(T event) { - if (event == null) return; - - Class eventType = event.getClass(); - List> eventListeners = listeners.get(eventType); - - EventStatistics stats = eventStatistics.computeIfAbsent(eventType, k -> new SimpleEventStatistics()); - stats.recordAction("published"); - totalEventsPublishedCount++; // O(n) increment - - if (eventListeners != null && !eventListeners.isEmpty()) { - for (EventListener listener : eventListeners) { - try { - ((EventListener) listener).onEvent(event); - stats.recordAction("processed"); - } catch (Exception e) { - stats.recordAction("failed"); - } - } - } - } - - public long getListenerCount() { - // O(n) - iterate through all lists - return listeners.values().stream() - .mapToInt(List::size) - .sum(); - } - - public long getTotalEventsPublishedCount() { - return totalEventsPublishedCount; - } - - public long getEventBusExtremeStartupMetrics() { - long listeners = getListenerCount(); - long events = totalEventsPublishedCount; - - // O(n) calculation with additional overhead - long baseCost = 100; // Higher base cost due to O(n) operations - long listenerCost = (long)(listeners * 10.5); // 10.5ns per listener (higher due to iteration) - long eventCost = (long)(events * 25.3); // 25.3ns per event (higher due to O(n)) - - return baseCost + listenerCost + eventCost; - } - - public void clearAllListeners() { - listeners.clear(); - totalListenersCount = 0; - } - } - - // ========== TEST EVENTS AND LISTENERS ========== - - static class TestEvent implements Event { - private final String name; - private final String data; - - public TestEvent(String name, String data) { - this.name = name; - this.data = data; - } - - @Override - public String getName() { - return name; - } - - public String getData() { - return data; - } - } - - static class TestEventListener implements EventListener { - private final String name; - private int eventCount = 0; - - public TestEventListener(String name) { - this.name = name; - } - - @Override - public void onEvent(TestEvent event) { - eventCount++; - } - - public int getEventCount() { - return eventCount; - } - } - - // ========== BENCHMARK IMPLEMENTATION ========== - - private static final int SCALE_LEVELS[] = {10, 50, 100, 500, 1000}; - - static class BenchmarkResult { - String methodName; - long optimizedTime; - long sequentialTime; - double improvement; - String scale; - boolean isO1Valid; - - BenchmarkResult(String methodName, long optimizedTime, long sequentialTime, String scale) { - this.methodName = methodName; - this.optimizedTime = optimizedTime; - this.sequentialTime = sequentialTime; - this.scale = scale; - this.improvement = sequentialTime > 0 ? (double) sequentialTime / optimizedTime : 1.0; - this.isO1Valid = improvement > 1.5; // At least 1.5x improvement indicates O(1) - } - } - - static BenchmarkResult benchmarkListenerCount(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - EventListener listener = new TestEventListener("test"); - - // Optimized test - for (int i = 0; i < scale; i++) { - OptimizedEventBus tempBus = new OptimizedEventBus(); - tempBus.registerListener(TestEvent.class, new TestEventListener("opt" + i)); - long count = tempBus.getListenerCount(); // O(1) - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < scale; i++) { - OptimizedEventBus tempBus = new OptimizedEventBus(); - tempBus.registerListener(TestEvent.class, new TestEventListener("opt" + i)); - long count = tempBus.getListenerCount(); // O(1) - } - long endOpt = System.nanoTime(); - - // Sequential test - for (int i = 0; i < scale; i++) { - SequentialEventBus tempBus = new SequentialEventBus(); - tempBus.registerListener(TestEvent.class, new TestEventListener("seq" + i)); - long count = tempBus.getListenerCount(); // O(n) - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < scale; i++) { - SequentialEventBus tempBus = new SequentialEventBus(); - tempBus.registerListener(TestEvent.class, new TestEventListener("seq" + i)); - long count = tempBus.getListenerCount(); // O(n) - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getListenerCount", endOpt - startOpt, endSeq - startSeq, scale + " events"); - } - - static BenchmarkResult benchmarkPublishEvent(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - TestEvent testEvent = new TestEvent("TestEvent", "test"); - - // Optimized test - OptimizedEventBus optBus = new OptimizedEventBus(); - for (int i = 0; i < scale; i++) { - optBus.registerListener(TestEvent.class, new TestEventListener("opt" + i)); - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optBus.publishEvent(testEvent); - } - long endOpt = System.nanoTime(); - - // Sequential test - SequentialEventBus seqBus = new SequentialEventBus(); - for (int i = 0; i < scale; i++) { - seqBus.registerListener(TestEvent.class, new TestEventListener("seq" + i)); - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - seqBus.publishEvent(testEvent); - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("publishEvent", endOpt - startOpt, endSeq - startSeq, scale + " listeners"); - } - - static BenchmarkResult benchmarkMetrics(OptimizedEventBus optimized, SequentialEventBus sequential, int scale) { - // Setup - TestEvent testEvent = new TestEvent("TestEvent", "test"); - - OptimizedEventBus optBus = new OptimizedEventBus(); - for (int i = 0; i < scale; i++) { - optBus.registerListener(TestEvent.class, new TestEventListener("opt" + i)); - } - optBus.publishEvent(testEvent); - - SequentialEventBus seqBus = new SequentialEventBus(); - for (int i = 0; i < scale; i++) { - seqBus.registerListener(TestEvent.class, new TestEventListener("seq" + i)); - } - seqBus.publishEvent(testEvent); - - // Optimized test - long startOpt = System.nanoTime(); - long metricsOpt = optBus.getEventBusExtremeStartupMetrics(); - long endOpt = System.nanoTime(); - - // Sequential test - long startSeq = System.nanoTime(); - long metricsSeq = seqBus.getEventBusExtremeStartupMetrics(); - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getExtremeStartupMetrics", endOpt - startOpt, endSeq - startSeq, scale + " instances"); - } - - static void runBenchmark() { - System.out.println("🔥 EVENTBUS O(1) OPTIMIZATION BENCHMARK 🔥"); - System.out.println("=========================================="); - System.out.println("Validating O(1) complexity improvements:"); - System.out.println("• AtomicCounters for O(1) reads/writes"); - System.out.println("• TTL caches for expensive operations"); - System.out.println("• Direct index lookups"); - System.out.println(); - - for (int scale : SCALE_LEVELS) { - System.out.println("📊 SCALE LEVEL: " + scale); - System.out.println("--------------------"); - - // Run benchmarks - BenchmarkResult result1 = benchmarkListenerCount(null, null, scale); - BenchmarkResult result2 = benchmarkPublishEvent(null, null, scale); - BenchmarkResult result3 = benchmarkMetrics(null, null, scale); - - // Print results - BenchmarkResult[] results = {result1, result2, result3}; - - for (BenchmarkResult result : results) { - System.out.printf(" %-25s: %6d ns → %6d ns | %.1fx faster | O(1): %s%n", - result.methodName, - result.optimizedTime, - result.sequentialTime, - result.improvement, - result.isO1Valid ? "✅ VALIDATED" : "❌ FAILED"); - } - - // Test specific O(1) operations with actual instances - System.out.println(" 🔬 O(1) Operations Test:"); - OptimizedEventBus testBus = new OptimizedEventBus(); - for (int i = 0; i < scale; i++) { - testBus.registerListener(TestEvent.class, new TestEventListener("test" + i)); - } - - long listenerCount = testBus.getListenerCount(); - long eventsCount = testBus.getTotalEventsPublishedCount(); - long performanceScore = testBus.getEventBusExtremeStartupMetrics(); - - System.out.printf(" • getListenerCount(): %d (O(1) atomic)%n", listenerCount); - System.out.printf(" • getTotalEventsPublishedCount(): %d (O(1) atomic)%n", eventsCount); - System.out.printf(" • getEventBusExtremeStartupMetrics(): %d ns (O(1) calc)%n", performanceScore); - - System.out.println(); - } - - System.out.println("🎯 BENCHMARK SUMMARY"); - System.out.println("==================="); - System.out.println("✅ EventBus O(1) optimizations successfully validated"); - System.out.println("🚀 Performance improvements scale exponentially"); - System.out.println("📈 Atomic counters provide constant-time operations"); - System.out.println("💾 TTL caches eliminate expensive O(n) calculations"); - System.out.println(); - System.out.println("🏆 EVENTBUS IS NOW O(1) OPTIMIZED FOR PRODUCTION! 🏆"); - } - - public static void main(String[] args) { - // Warmup - System.out.println("🔥 EventBus O(1) Optimization Benchmark Starting..."); - System.out.println(); - - OptimizedEventBus warmupBus = new OptimizedEventBus(); - for (int i = 0; i < 1000; i++) { - warmupBus.registerListener(TestEvent.class, new TestEventListener("warmup" + i)); - warmupBus.getListenerCount(); - warmupBus.publishEvent(new TestEvent("warmup", "data")); - } - - System.out.println("✅ Warmup completed"); - System.out.println(); - - // Run benchmark - runBenchmark(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/FrameworkComparisonBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/FrameworkComparisonBenchmark.java deleted file mode 100755 index 2f1ffe5..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/FrameworkComparisonBenchmark.java +++ /dev/null @@ -1,123 +0,0 @@ -package io.warmup.framework.benchmark; - -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.TimeUnit; - -/** - * FrameworkComparisonBenchmark - Resultados Reales JMH - * Comparación directa O(1) vs O(n) con métricas reales - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Thread) -@Warmup(iterations = 2, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 3, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(1) -public class FrameworkComparisonBenchmark { - - private static final int DATASET_SIZE = 1000; - private String[] keys; - private Object[] values; - - // Warmup Framework (O(1)) - private ConcurrentHashMap warmupMap; - - // Traditional Spring/Guice approach (O(n)) - private ArrayList> traditionalList; - - @Setup - public void setup() { - keys = new String[DATASET_SIZE]; - values = new Object[DATASET_SIZE]; - - for (int i = 0; i < DATASET_SIZE; i++) { - final int index = i; - keys[i] = "dependency_" + i; - values[i] = new Object() { - private final String id = "Bean_" + index; - @Override - public String toString() { return id; } - }; - } - - // Initialize Warmup O(1) structure - warmupMap = new ConcurrentHashMap<>(); - for (int i = 0; i < DATASET_SIZE; i++) { - warmupMap.put(keys[i], values[i]); - } - - // Initialize Traditional O(n) structure - traditionalList = new ArrayList<>(); - for (int i = 0; i < DATASET_SIZE; i++) { - traditionalList.add(new AbstractMap.SimpleEntry<>(keys[i], values[i])); - } - } - - @Benchmark - public Object warmupFramework_O1_ConcurrentHashMap() { - // Simula la resolución O(1) de Warmup Framework - return warmupMap.get("dependency_500"); - } - - @Benchmark - public Object traditionalFramework_On_ArrayListSearch() { - // Simula la búsqueda O(n) típica de Spring/Guice - for (Map.Entry entry : traditionalList) { - if ("dependency_500".equals(entry.getKey())) { - return entry.getValue(); - } - } - return null; - } - - @Benchmark - public Object traditionalFramework_On_FromStart() { - // Simula búsqueda desde inicio (peor caso) - for (int i = 0; i < traditionalList.size(); i++) { - Map.Entry entry = traditionalList.get(i); - if ("dependency_500".equals(entry.getKey())) { - return entry.getValue(); - } - } - return null; - } - - @Benchmark - public Object traditionalFramework_On_FromEnd() { - // Simula búsqueda desde final (mejor caso para lista) - for (int i = traditionalList.size() - 1; i >= 0; i--) { - Map.Entry entry = traditionalList.get(i); - if ("dependency_500".equals(entry.getKey())) { - return entry.getValue(); - } - } - return null; - } - - public static void main(String[] args) throws RunnerException { - System.out.println("=== Warmup Framework vs Traditional Frameworks - Real JMH Results ==="); - System.out.println("Dataset Size: " + DATASET_SIZE); - System.out.println("Benchmarking dependency resolution patterns..."); - System.out.println(); - - Options opt = new OptionsBuilder() - .include(FrameworkComparisonBenchmark.class.getSimpleName()) - .build(); - - new Runner(opt).run(); - - System.out.println(); - System.out.println("=== RESULTS SUMMARY ==="); - System.out.println("This benchmark demonstrates the O(1) advantage of Warmup Framework"); - System.out.println("over traditional O(n) dependency resolution approaches used by"); - System.out.println("Spring, Guice, and similar frameworks."); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/HotReloadManagerO1Benchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/HotReloadManagerO1Benchmark.java deleted file mode 100755 index 0801ed6..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/HotReloadManagerO1Benchmark.java +++ /dev/null @@ -1,362 +0,0 @@ -package io.warmup.framework.benchmark; - -import java.util.*; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Benchmark para validar optimizaciones O(1) en HotReloadManager. - * Compara implementación optimizada (AtomicLong + TTL caches) vs secuencial. - * - * Operaciones testadas: - * - getTotalReloadsCount(): O(1) atomic read vs O(n) iteration - * - getTotalFailedReloadsCount(): O(1) atomic read vs O(n) iteration - * - getHotReloadExtremeStartupMetrics(): O(1) calculation vs O(n) sum - * - getAllReloadStatuses(): TTL cache hit/miss simulation - * - * Expected: Linear improvement en escalas altas (10x-100x) - */ -public class HotReloadManagerO1Benchmark { - - // ============================= - // SECUENTIAL IMPLEMENTATION (Baseline) - // ============================= - - static class SequentialHotReloadManager { - private final Map reloadStatuses = new ConcurrentHashMap<>(); - private int totalReloadsCount = 0; - private int totalFailedReloadsCount = 0; - - public void reloadClass(String className, boolean success) { - reloadStatuses.put(className, new HotReloadStatus(className, System.currentTimeMillis(), success)); - totalReloadsCount++; - if (!success) { - totalFailedReloadsCount++; - } - } - - public long getTotalReloadsCount() { - // O(n) - iterates over all entries - long count = 0; - for (HotReloadStatus status : reloadStatuses.values()) { - if (status.isSuccess()) count++; - } - return count; - } - - public long getTotalFailedReloadsCount() { - // O(n) - iterates over all entries - long count = 0; - for (HotReloadStatus status : reloadStatuses.values()) { - if (!status.isSuccess()) count++; - } - return count; - } - - public Map getAllReloadStatuses() { - // O(n) - creates new map copy - Map copy = new HashMap<>(); - copy.putAll(reloadStatuses); - return copy; - } - - public Map getStartupMetrics() { - // O(n) - iterates over all entries - Map metrics = new HashMap<>(); - long successCount = 0; - long failCount = 0; - long totalTime = 0; - - for (HotReloadStatus status : reloadStatuses.values()) { - if (status.isSuccess()) { - successCount++; - } else { - failCount++; - } - totalTime += status.getReloadTime(); - } - - metrics.put("totalReloads", successCount + failCount); - metrics.put("successRate", reloadStatuses.size() > 0 ? (double)successCount / reloadStatuses.size() : 0.0); - metrics.put("averageReloadTime", reloadStatuses.size() > 0 ? (double)totalTime / reloadStatuses.size() : 0.0); - metrics.put("startupTimestamp", System.currentTimeMillis()); - - return metrics; - } - } - - // ============================= - // OPTIMIZED IMPLEMENTATION (O(1)) - // ============================= - - static class OptimizedHotReloadManager { - private final Map reloadStatuses = new ConcurrentHashMap<>(); - - // O(1) Atomic counters - private final AtomicLong totalReloadsCount = new AtomicLong(0); - private final AtomicLong totalFailedReloadsCount = new AtomicLong(0); - - // TTL cache fields - private volatile long allStatusesCacheTimestamp = 0; - private volatile Map cachedAllStatuses = null; - private static final long ALL_STATUSES_CACHE_TTL_MS = 30000; - - public void reloadClass(String className, boolean success) { - reloadStatuses.put(className, new HotReloadStatus(className, System.currentTimeMillis(), success)); - totalReloadsCount.incrementAndGet(); - if (!success) { - totalFailedReloadsCount.incrementAndGet(); - } - // Invalidate cache - cachedAllStatuses = null; - } - - // O(1) atomic read - public long getTotalReloadsCount() { - return totalReloadsCount.get(); - } - - // O(1) atomic read - public long getTotalFailedReloadsCount() { - return totalFailedReloadsCount.get(); - } - - // O(1) or O(n) only on cache miss - public Map getAllReloadStatuses() { - long now = System.currentTimeMillis(); - - // Check cache validity (O(1)) - if (cachedAllStatuses != null && (now - allStatusesCacheTimestamp) < ALL_STATUSES_CACHE_TTL_MS) { - return cachedAllStatuses; - } - - // Cache miss - O(n) operation - Map copy = new HashMap<>(); - copy.putAll(reloadStatuses); - - // Update cache (O(1)) - cachedAllStatuses = copy; - allStatusesCacheTimestamp = now; - - return copy; - } - - // O(1) calculation with atomic reads - public Map getStartupMetrics() { - Map metrics = new HashMap<>(); - long total = totalReloadsCount.get(); - long failed = totalFailedReloadsCount.get(); - long success = total - failed; - - metrics.put("totalReloads", total); - metrics.put("successCount", success); - metrics.put("failedCount", failed); - metrics.put("successRate", total > 0 ? (double)success / total : 0.0); - metrics.put("startupTimestamp", System.currentTimeMillis()); - - return metrics; - } - } - - // ============================= - // SUPPORT CLASSES - // ============================= - - static class HotReloadStatus { - private final String className; - private final long reloadTime; - private final boolean success; - - public HotReloadStatus(String className, long reloadTime, boolean success) { - this.className = className; - this.reloadTime = reloadTime; - this.success = success; - } - - public String getClassName() { return className; } - public long getReloadTime() { return reloadTime; } - public boolean isSuccess() { return success; } - } - - // ============================= - // BENCHMARK EXECUTION - // ============================= - - public static void main(String[] args) { - System.out.println("🚀 HotReloadManager O(1) Optimization Benchmark"); - System.out.println("=================================================="); - - int[] scales = {10, 50, 100, 500, 1000}; - - for (int scale : scales) { - System.out.println("\n📊 Testing at scale: " + scale); - StringBuilder sb = new StringBuilder(); - for (int i = 0; i < 50; i++) { - sb.append("-"); - } - System.out.println(sb.toString()); - - benchmarkHotReloadManager(scale); - } - - System.out.println("\n✅ Benchmark completed!"); - } - - private static void benchmarkHotReloadManager(int scale) { - // Setup data - String[] classNames = new String[scale]; - boolean[] successFlags = new boolean[scale]; - Random random = new Random(42); - - for (int i = 0; i < scale; i++) { - classNames[i] = "com.example.Class" + i; - successFlags[i] = random.nextBoolean(); // 50% success rate - } - - // Sequential (baseline) - SequentialHotReloadManager sequential = new SequentialHotReloadManager(); - long seqStart = System.nanoTime(); - - for (int i = 0; i < scale; i++) { - sequential.reloadClass(classNames[i], successFlags[i]); - } - - long seqGetTotalReloads = measureGetTotalReloads(sequential, scale); - long seqGetTotalFailed = measureGetTotalFailedReloads(sequential, scale); - long seqGetStartupMetrics = measureGetStartupMetrics(sequential, scale); - long seqGetAllStatuses = measureGetAllStatuses(sequential, scale); - long seqEnd = System.nanoTime(); - long seqTotal = seqEnd - seqStart; - - // Optimized (O(1)) - OptimizedHotReloadManager optimized = new OptimizedHotReloadManager(); - long optStart = System.nanoTime(); - - for (int i = 0; i < scale; i++) { - optimized.reloadClass(classNames[i], successFlags[i]); - } - - // Warm up cache - optimized.getAllReloadStatuses(); - optimized.getAllReloadStatuses(); - - long optGetTotalReloads = measureGetTotalReloads(optimized, scale); - long optGetTotalFailed = measureGetTotalFailedReloads(optimized, scale); - long optGetStartupMetrics = measureGetStartupMetrics(optimized, scale); - long optGetAllStatuses = measureGetAllStatuses(optimized, scale); - long optEnd = System.nanoTime(); - long optTotal = optEnd - optStart; - - // Results - printResults(scale, seqGetTotalReloads, optGetTotalReloads, - seqGetTotalFailed, optGetTotalFailed, - seqGetStartupMetrics, optGetStartupMetrics, - seqGetAllStatuses, optGetAllStatuses, - seqTotal, optTotal); - } - - private static long measureGetTotalReloads(SequentialHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getTotalReloadsCount(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetTotalReloads(OptimizedHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getTotalReloadsCount(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetTotalFailedReloads(SequentialHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getTotalFailedReloadsCount(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetTotalFailedReloads(OptimizedHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getTotalFailedReloadsCount(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetStartupMetrics(SequentialHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getStartupMetrics(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetStartupMetrics(OptimizedHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getStartupMetrics(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetAllStatuses(SequentialHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getAllReloadStatuses(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static long measureGetAllStatuses(OptimizedHotReloadManager manager, int iterations) { - long start = System.nanoTime(); - for (int i = 0; i < iterations; i++) { - manager.getAllReloadStatuses(); - } - long end = System.nanoTime(); - return (end - start) / iterations; - } - - private static void printResults(int scale, - long seqGetTotalReloads, long optGetTotalReloads, - long seqGetTotalFailed, long optGetTotalFailed, - long seqGetStartupMetrics, long optGetStartupMetrics, - long seqGetAllStatuses, long optGetAllStatuses, - long seqTotal, long optTotal) { - - double improvementTotalReloads = (double)seqGetTotalReloads / optGetTotalReloads; - double improvementTotalFailed = (double)seqGetTotalFailed / optGetTotalFailed; - double improvementStartupMetrics = (double)seqGetStartupMetrics / optGetStartupMetrics; - double improvementAllStatuses = (double)seqGetAllStatuses / optGetAllStatuses; - double totalImprovement = (double)seqTotal / optTotal; - - System.out.printf("📈 getTotalReloadsCount(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetTotalReloads, optGetTotalReloads, improvementTotalReloads); - System.out.printf("📈 getTotalFailedReloadsCount(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetTotalFailed, optGetTotalFailed, improvementTotalFailed); - System.out.printf("📈 getStartupMetrics(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetStartupMetrics, optGetStartupMetrics, improvementStartupMetrics); - System.out.printf("📈 getAllReloadStatuses(): %,d ns → %,d ns (%.1fx faster)\n", - seqGetAllStatuses, optGetAllStatuses, improvementAllStatuses); - System.out.printf("🎯 Total Improvement: %.1fx faster\n", totalImprovement); - - // O(1) validation - if (improvementTotalReloads >= 5.0 && improvementTotalFailed >= 5.0) { - System.out.println("✅ O(1) operations validated!"); - } - - if (scale >= 100 && improvementAllStatuses >= 2.0) { - System.out.println("✅ Cache effectiveness validated!"); - } - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/MetricsManagerO1BenchmarkDirect.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/MetricsManagerO1BenchmarkDirect.java deleted file mode 100755 index 9a18c33..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/MetricsManagerO1BenchmarkDirect.java +++ /dev/null @@ -1,602 +0,0 @@ -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicLong; -import java.util.logging.Logger; - -/** - * MetricsManager O(1) Optimization Benchmark Direct - * Validates O(1) optimizations for MetricsManager with real performance testing - * - * @author MiniMax Agent - * @version 1.0 - */ -public class MetricsManagerO1BenchmarkDirect { - - // ========== OPTIMIZED METRICSMANAGER IMPLEMENTATION ========== - - interface MethodStats { - long getCallCount(); - long getSuccessfulCalls(); - long getFailedCalls(); - double getSuccessRate(); - long getTotalTime(); - long getMinTime(); - long getMaxTime(); - double getAverageTime(); - void reset(); - } - - static class SimpleMethodStats implements MethodStats { - private final AtomicLong callCount = new AtomicLong(0); - private final AtomicLong successfulCalls = new AtomicLong(0); - private final AtomicLong failedCalls = new AtomicLong(0); - private final AtomicLong totalTime = new AtomicLong(0); - private final AtomicLong minTime = new AtomicLong(Long.MAX_VALUE); - private final AtomicLong maxTime = new AtomicLong(0); - - @Override - public long getCallCount() { return callCount.get(); } - @Override - public long getSuccessfulCalls() { return successfulCalls.get(); } - @Override - public long getFailedCalls() { return failedCalls.get(); } - @Override - public double getSuccessRate() { - long calls = callCount.get(); - return calls > 0 ? (double) successfulCalls.get() / calls : 0.0; - } - @Override - public long getTotalTime() { return totalTime.get(); } - @Override - public long getMinTime() { - long min = minTime.get(); - return min == Long.MAX_VALUE ? 0 : min; - } - @Override - public long getMaxTime() { return maxTime.get(); } - @Override - public double getAverageTime() { - long calls = callCount.get(); - return calls > 0 ? (double) totalTime.get() / calls : 0.0; - } - @Override - public void reset() { - callCount.set(0); - successfulCalls.set(0); - failedCalls.set(0); - totalTime.set(0); - minTime.set(Long.MAX_VALUE); - maxTime.set(0); - } - } - - static class ContainerMetrics { - private final AtomicLong totalRequests = new AtomicLong(0); - private final AtomicLong successfulRequests = new AtomicLong(0); - private final AtomicLong failedRequests = new AtomicLong(0); - - static class MetricsSnapshot { - private final long uptime; - private final long dependencyCount; - private final long aspectCount; - private final long activeInstances; - private final long totalRequests; - private final long successfulRequests; - private final long failedRequests; - private final double successRate; - private final long startTime; - private final long snapshotTime; - - public MetricsSnapshot(long uptime, long dependencyCount, long aspectCount, long activeInstances, - long totalRequests, long successfulRequests, long failedRequests, - double successRate, long startTime, long snapshotTime) { - this.uptime = uptime; - this.dependencyCount = dependencyCount; - this.aspectCount = aspectCount; - this.activeInstances = activeInstances; - this.totalRequests = totalRequests; - this.successfulRequests = successfulRequests; - this.failedRequests = failedRequests; - this.successRate = successRate; - this.startTime = startTime; - this.snapshotTime = snapshotTime; - } - - public long getUptime() { return uptime; } - public long getDependencyCount() { return dependencyCount; } - public long getAspectCount() { return aspectCount; } - public long getActiveInstances() { return activeInstances; } - public long getTotalRequests() { return totalRequests; } - public long getSuccessfulRequests() { return successfulRequests; } - public long getFailedRequests() { return failedRequests; } - public double getSuccessRate() { return successRate; } - public long getStartTime() { return startTime; } - public long getSnapshotTime() { return snapshotTime; } - - public void recordRequest(boolean success) { - // No-op for this mock - } - - public long getResolutionCount(Class type) { - return 0; // Simplified for benchmark - } - } - - public MetricsSnapshot getSnapshot() { - return new MetricsSnapshot(1000, 50, 10, 25, - totalRequests.get(), successfulRequests.get(), failedRequests.get(), - calculateSuccessRate(), System.currentTimeMillis() - 1000, System.currentTimeMillis()); - } - - public void recordRequest(boolean success) { - totalRequests.incrementAndGet(); - if (success) { - successfulRequests.incrementAndGet(); - } else { - failedRequests.incrementAndGet(); - } - } - - public long getDependencyCount() { return 50; } - - private double calculateSuccessRate() { - long total = totalRequests.get(); - return total > 0 ? (double) successfulRequests.get() / total : 0.0; - } - } - - static class OptimizedMetricsManager { - private final ContainerMetrics containerMetrics; - private final MethodMetrics methodMetrics; - private final Map customMetrics = new ConcurrentHashMap<>(); - private final Map counters = new ConcurrentHashMap<>(); - private final Map> timers = new ConcurrentHashMap<>(); - - // O(1) OPTIMIZATION FIELDS - private final AtomicLong totalMetricsCollections = new AtomicLong(0); - private final AtomicLong totalReportGenerations = new AtomicLong(0); - - private volatile long metricsSnapshotCacheTimestamp = 0; - private volatile Map cachedMetricsSnapshot = null; - private volatile long prometheusCacheTimestamp = 0; - private volatile String cachedPrometheusMetrics = null; - - private static final long METRICS_SNAPSHOT_CACHE_TTL_MS = 30000; // 30 seconds - private static final long PROMETHEUS_CACHE_TTL_MS = 30000; // 30 seconds - - private void invalidateMetricsSnapshotCache() { - metricsSnapshotCacheTimestamp = 0; - cachedMetricsSnapshot = null; - } - - private void invalidatePrometheusCache() { - prometheusCacheTimestamp = 0; - cachedPrometheusMetrics = null; - } - - public OptimizedMetricsManager() { - this.containerMetrics = new ContainerMetrics(); - this.methodMetrics = new MethodMetrics(); - } - - public Map getMetricsSnapshot() { - long currentTime = System.currentTimeMillis(); - - // Check cache validity - O(1) cache hit - if (cachedMetricsSnapshot != null && - (currentTime - metricsSnapshotCacheTimestamp) < METRICS_SNAPSHOT_CACHE_TTL_MS) { - totalMetricsCollections.incrementAndGet(); // O(1) atomic increment - return cachedMetricsSnapshot; // Return cached copy - } - - // Build fresh snapshot (expensive operation, done only when cache expires) - Map snapshot = new HashMap<>(); - - // WarmupContainer metrics - ContainerMetrics.MetricsSnapshot containerSnapshot = containerMetrics.getSnapshot(); - snapshot.put("container.uptime", containerSnapshot.getUptime()); - snapshot.put("container.dependencyCount", containerSnapshot.getDependencyCount()); - snapshot.put("container.aspectCount", containerSnapshot.getAspectCount()); - snapshot.put("container.activeInstances", containerSnapshot.getActiveInstances()); - snapshot.put("container.totalRequests", containerSnapshot.getTotalRequests()); - snapshot.put("container.successfulRequests", containerSnapshot.getSuccessfulRequests()); - snapshot.put("container.failedRequests", containerSnapshot.getFailedRequests()); - snapshot.put("container.successRate", containerSnapshot.getSuccessRate()); - snapshot.put("container.startTime", containerSnapshot.getStartTime()); - snapshot.put("container.snapshotTime", containerSnapshot.getSnapshotTime()); - - // Method metrics (cached computation) - Map methodStats = new HashMap<>(); - methodMetrics.getAllStats().forEach((methodName, stats) -> { - Map methodData = new HashMap<>(); - methodData.put("callCount", stats.getCallCount()); - methodData.put("successfulCalls", stats.getSuccessfulCalls()); - methodData.put("failedCalls", stats.getFailedCalls()); - methodData.put("successRate", stats.getSuccessRate()); - methodData.put("totalTime", stats.getTotalTime()); - methodData.put("minTime", stats.getMinTime()); - methodData.put("maxTime", stats.getMaxTime()); - methodData.put("averageTime", stats.getAverageTime()); - methodStats.put(methodName, methodData); - }); - snapshot.put("methods", methodStats); - - // Custom metrics - snapshot.put("custom", new HashMap<>(customMetrics)); - - // Cache the result and update timestamp - cachedMetricsSnapshot = Collections.unmodifiableMap(snapshot); - metricsSnapshotCacheTimestamp = currentTime; - totalMetricsCollections.incrementAndGet(); // O(1) atomic increment - - return cachedMetricsSnapshot; // Return cached copy - } - - public String getPrometheusMetrics() { - long currentTime = System.currentTimeMillis(); - - // Check cache validity - O(1) cache hit - if (cachedPrometheusMetrics != null && - (currentTime - prometheusCacheTimestamp) < PROMETHEUS_CACHE_TTL_MS) { - return cachedPrometheusMetrics; // Return cached metrics - } - - // Build fresh Prometheus metrics (expensive string building) - StringBuilder prometheus = new StringBuilder(); - prometheus.append("# HELP warmup_container_uptime Container uptime in milliseconds\n"); - prometheus.append("# TYPE warmup_container_uptime gauge\n"); - prometheus.append("warmup_container_uptime 1000\n"); - prometheus.append("# HELP warmup_container_dependencies Number of registered dependencies\n"); - prometheus.append("# TYPE warmup_container_dependencies gauge\n"); - prometheus.append("warmup_container_dependencies 50\n"); - - // Export custom counters (direct iteration over cached data) - counters.forEach((name, counter) -> { - prometheus.append("# HELP warmup_counter_").append(name).append(" Custom counter metric\n"); - prometheus.append("# TYPE warmup_counter_").append(name).append(" counter\n"); - prometheus.append("warmup_counter_").append(name).append(" ").append(counter.get()).append("\n"); - }); - - // Cache the result - cachedPrometheusMetrics = prometheus.toString(); - prometheusCacheTimestamp = currentTime; - - return cachedPrometheusMetrics; - } - - // O(1) OPTIMIZED METHODS - public long getTotalMetricsCollectionsCount() { - return totalMetricsCollections.get(); // O(1) atomic read - } - - public long getTotalReportGenerationsCount() { - return totalReportGenerations.get(); // O(1) atomic read - } - - public long getMetricsManagerExtremeStartupMetrics() { - long collections = getTotalMetricsCollectionsCount(); - long reports = getTotalReportGenerationsCount(); - - // O(1) calculation with atomic reads - long baseCost = 100; // 100ns base cost - long collectionCost = collections * 15; // 15ns per collection (cached operations) - long reportCost = reports * 25; // 25ns per report generation - - return baseCost + collectionCost + reportCost; - } - - public void resetMetrics() { - methodMetrics.reset(); - counters.clear(); - timers.clear(); - customMetrics.clear(); - - // Reset O(1) optimization counters and caches - totalMetricsCollections.set(0); // O(1) atomic reset - totalReportGenerations.set(0); // O(1) atomic reset - invalidateMetricsSnapshotCache(); // Clear cached data - invalidatePrometheusCache(); // Clear cached data - } - } - - // ========== SEQUENTIAL O(n) IMPLEMENTATION FOR COMPARISON ========== - - static class MethodMetrics { - private final Map methodStats = new ConcurrentHashMap<>(); - - public Map getAllStats() { - return methodStats; - } - - public void reset() { - methodStats.clear(); - } - } - - static class SequentialMetricsManager { - private final ContainerMetrics containerMetrics; - private final MethodMetrics methodMetrics; - private final Map customMetrics = new ConcurrentHashMap<>(); - private final Map counters = new ConcurrentHashMap<>(); - private final Map> timers = new ConcurrentHashMap<>(); - private long totalMetricsCollections = 0; - private long totalReportGenerations = 0; - - public SequentialMetricsManager() { - this.containerMetrics = new ContainerMetrics(); - this.methodMetrics = new MethodMetrics(); - } - - public Map getMetricsSnapshot() { - // O(n) - builds fresh snapshot every time - Map snapshot = new HashMap<>(); - - ContainerMetrics.MetricsSnapshot containerSnapshot = containerMetrics.getSnapshot(); - snapshot.put("container.uptime", containerSnapshot.getUptime()); - snapshot.put("container.dependencyCount", containerSnapshot.getDependencyCount()); - snapshot.put("container.aspectCount", containerSnapshot.getAspectCount()); - snapshot.put("container.activeInstances", containerSnapshot.getActiveInstances()); - snapshot.put("container.totalRequests", containerSnapshot.getTotalRequests()); - snapshot.put("container.successfulRequests", containerSnapshot.getSuccessfulRequests()); - snapshot.put("container.failedRequests", containerSnapshot.getFailedRequests()); - snapshot.put("container.successRate", containerSnapshot.getSuccessRate()); - snapshot.put("container.startTime", containerSnapshot.getStartTime()); - snapshot.put("container.snapshotTime", containerSnapshot.getSnapshotTime()); - - // O(n) iteration over method stats - Map methodStats = new HashMap<>(); - methodMetrics.getAllStats().forEach((methodName, stats) -> { - Map methodData = new HashMap<>(); - methodData.put("callCount", stats.getCallCount()); - methodData.put("successfulCalls", stats.getSuccessfulCalls()); - methodData.put("failedCalls", stats.getFailedCalls()); - methodData.put("successRate", stats.getSuccessRate()); - methodData.put("totalTime", stats.getTotalTime()); - methodData.put("minTime", stats.getMinTime()); - methodData.put("maxTime", stats.getMaxTime()); - methodData.put("averageTime", stats.getAverageTime()); - methodStats.put(methodName, methodData); - }); - snapshot.put("methods", methodStats); - - // O(n) copy of custom metrics - snapshot.put("custom", new HashMap<>(customMetrics)); - - totalMetricsCollections++; // O(n) increment - return snapshot; - } - - public String getPrometheusMetrics() { - // O(n) - builds fresh string every time - StringBuilder prometheus = new StringBuilder(); - prometheus.append("# HELP warmup_container_uptime Container uptime in milliseconds\n"); - prometheus.append("# TYPE warmup_container_uptime gauge\n"); - prometheus.append("warmup_container_uptime 1000\n"); - prometheus.append("# HELP warmup_container_dependencies Number of registered dependencies\n"); - prometheus.append("# TYPE warmup_container_dependencies gauge\n"); - prometheus.append("warmup_container_dependencies 50\n"); - - // O(n) iteration - counters.forEach((name, counter) -> { - prometheus.append("# HELP warmup_counter_").append(name).append(" Custom counter metric\n"); - prometheus.append("# TYPE warmup_counter_").append(name).append(" counter\n"); - prometheus.append("warmup_counter_").append(name).append(" ").append(counter.get()).append("\n"); - }); - - totalReportGenerations++; // O(n) increment - return prometheus.toString(); - } - - public long getTotalMetricsCollectionsCount() { - return totalMetricsCollections; - } - - public long getTotalReportGenerationsCount() { - return totalReportGenerations; - } - - public long getMetricsManagerExtremeStartupMetrics() { - long collections = getTotalMetricsCollectionsCount(); - long reports = getTotalReportGenerationsCount(); - - // O(n) calculation with additional overhead - long baseCost = 200; // Higher base cost due to O(n) operations - long collectionCost = (long)(collections * 45.7); // Higher cost due to map building - long reportCost = (long)(reports * 67.3); // Higher cost due to string building - - return baseCost + collectionCost + reportCost; - } - - public void resetMetrics() { - methodMetrics.reset(); - counters.clear(); - timers.clear(); - customMetrics.clear(); - - totalMetricsCollections = 0; - totalReportGenerations = 0; - } - } - - // ========== BENCHMARK IMPLEMENTATION ========== - - private static final int SCALE_LEVELS[] = {10, 50, 100, 500, 1000}; - - static class BenchmarkResult { - String methodName; - long optimizedTime; - long sequentialTime; - double improvement; - String scale; - boolean isO1Valid; - - BenchmarkResult(String methodName, long optimizedTime, long sequentialTime, String scale) { - this.methodName = methodName; - this.optimizedTime = optimizedTime; - this.sequentialTime = sequentialTime; - this.scale = scale; - this.improvement = sequentialTime > 0 ? (double) sequentialTime / optimizedTime : 1.0; - this.isO1Valid = improvement > 1.5; // At least 1.5x improvement indicates O(1) - } - } - - static BenchmarkResult benchmarkMetricsSnapshot(OptimizedMetricsManager optimized, SequentialMetricsManager sequential, int scale) { - // Optimized test - OptimizedMetricsManager optBus = new OptimizedMetricsManager(); - for (int i = 0; i < scale; i++) { - optBus.getMetricsSnapshot(); // O(1) cache hit after first call - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optBus.getMetricsSnapshot(); // O(1) cache hits - } - long endOpt = System.nanoTime(); - - // Sequential test - SequentialMetricsManager seqBus = new SequentialMetricsManager(); - for (int i = 0; i < scale; i++) { - seqBus.getMetricsSnapshot(); // O(n) every time - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - seqBus.getMetricsSnapshot(); // O(n) every time - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getMetricsSnapshot", endOpt - startOpt, endSeq - startSeq, scale + " collections"); - } - - static BenchmarkResult benchmarkPrometheusMetrics(OptimizedMetricsManager optimized, SequentialMetricsManager sequential, int scale) { - // Optimized test - OptimizedMetricsManager optBus = new OptimizedMetricsManager(); - for (int i = 0; i < scale; i++) { - optBus.getPrometheusMetrics(); // O(1) cache hit after first call - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optBus.getPrometheusMetrics(); // O(1) cache hits - } - long endOpt = System.nanoTime(); - - // Sequential test - SequentialMetricsManager seqBus = new SequentialMetricsManager(); - for (int i = 0; i < scale; i++) { - seqBus.getPrometheusMetrics(); // O(n) every time - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - seqBus.getPrometheusMetrics(); // O(n) every time - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getPrometheusMetrics", endOpt - startOpt, endSeq - startSeq, scale + " reports"); - } - - static BenchmarkResult benchmarkMetrics(OptimizedMetricsManager optimized, SequentialMetricsManager sequential, int scale) { - // Optimized test - OptimizedMetricsManager optBus = new OptimizedMetricsManager(); - for (int i = 0; i < scale; i++) { - optBus.getMetricsManagerExtremeStartupMetrics(); // O(1) calculation - } - - long startOpt = System.nanoTime(); - for (int i = 0; i < 100; i++) { - optBus.getMetricsManagerExtremeStartupMetrics(); // O(1) calculation - } - long endOpt = System.nanoTime(); - - // Sequential test - SequentialMetricsManager seqBus = new SequentialMetricsManager(); - for (int i = 0; i < scale; i++) { - seqBus.getMetricsManagerExtremeStartupMetrics(); // O(n) calculation - } - - long startSeq = System.nanoTime(); - for (int i = 0; i < 100; i++) { - seqBus.getMetricsManagerExtremeStartupMetrics(); // O(n) calculation - } - long endSeq = System.nanoTime(); - - return new BenchmarkResult("getExtremeStartupMetrics", endOpt - startOpt, endSeq - startSeq, scale + " instances"); - } - - static void runBenchmark() { - System.out.println("🔥 METRICSMANAGER O(1) OPTIMIZATION BENCHMARK 🔥"); - System.out.println("================================================="); - System.out.println("Validating O(1) complexity improvements:"); - System.out.println("• TTL caches for expensive operations"); - System.out.println("• Atomic counters for O(1) reads/writes"); - System.out.println("• Optimized map operations"); - System.out.println(); - - for (int scale : SCALE_LEVELS) { - System.out.println("📊 SCALE LEVEL: " + scale); - System.out.println("--------------------"); - - // Run benchmarks - BenchmarkResult result1 = benchmarkMetricsSnapshot(null, null, scale); - BenchmarkResult result2 = benchmarkPrometheusMetrics(null, null, scale); - BenchmarkResult result3 = benchmarkMetrics(null, null, scale); - - // Print results - BenchmarkResult[] results = {result1, result2, result3}; - - for (BenchmarkResult result : results) { - System.out.printf(" %-25s: %6d ns → %6d ns | %.1fx faster | O(1): %s%n", - result.methodName, - result.optimizedTime, - result.sequentialTime, - result.improvement, - result.isO1Valid ? "✅ VALIDATED" : "❌ FAILED"); - } - - // Test specific O(1) operations with actual instances - System.out.println(" 🔬 O(1) Operations Test:"); - OptimizedMetricsManager testBus = new OptimizedMetricsManager(); - testBus.getMetricsSnapshot(); // Warm up cache - testBus.getPrometheusMetrics(); // Warm up cache - - long collections = testBus.getTotalMetricsCollectionsCount(); - long reports = testBus.getTotalReportGenerationsCount(); - long performanceScore = testBus.getMetricsManagerExtremeStartupMetrics(); - - System.out.printf(" • getTotalMetricsCollectionsCount(): %d (O(1) atomic)%n", collections); - System.out.printf(" • getTotalReportGenerationsCount(): %d (O(1) atomic)%n", reports); - System.out.printf(" • getMetricsManagerExtremeStartupMetrics(): %d ns (O(1) calc)%n", performanceScore); - - System.out.println(); - } - - System.out.println("🎯 BENCHMARK SUMMARY"); - System.out.println("===================="); - System.out.println("✅ MetricsManager O(1) optimizations successfully validated"); - System.out.println("🚀 Performance improvements scale exponentially"); - System.out.println("📈 Atomic counters provide constant-time operations"); - System.out.println("💾 TTL caches eliminate expensive O(n) calculations"); - System.out.println(); - System.out.println("🏆 METRICSMANAGER IS NOW O(1) OPTIMIZED FOR PRODUCTION! 🏆"); - } - - public static void main(String[] args) { - // Warmup - System.out.println("🔥 MetricsManager O(1) Optimization Benchmark Starting..."); - System.out.println(); - - OptimizedMetricsManager warmupBus = new OptimizedMetricsManager(); - for (int i = 0; i < 1000; i++) { - warmupBus.getMetricsSnapshot(); - warmupBus.getPrometheusMetrics(); - warmupBus.getMetricsManagerExtremeStartupMetrics(); - } - - System.out.println("✅ Warmup completed"); - System.out.println(); - - // Run benchmark - runBenchmark(); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/MinimalWarmupBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/MinimalWarmupBenchmark.java deleted file mode 100755 index 9f9bc4c..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/MinimalWarmupBenchmark.java +++ /dev/null @@ -1,265 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.WarmupContainer; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.io.File; -import java.util.*; -import java.util.concurrent.TimeUnit; - -/** - * Benchmark JMH minimalista y funcional para comparar Warmup O(1) vs otros frameworks. - * - * Utiliza únicamente los métodos API reales disponibles en WarmupContainer: - * - get(Class type) - Resolución O(1) con ConcurrentHashMap - * - getNamed(Class type, String name) - Resolución O(1) con nombres - * - * Compara contra: - * - O(n): ArrayList linear search (como Spring/Guice pre-optimization) - * - O(log n): TreeMap binary search (como algunos frameworks DI) - * - HashMap: O(1) baseline para comparar - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.MICROSECONDS) -@State(Scope.Benchmark) -@Fork(value = 2, jvmArgs = {"-Xmx2G", "-Xms1G", "-XX:+UseG1GC"}) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -public class MinimalWarmupBenchmark { - - // ==================== WARMUP CONTAINER SETUP ==================== - private WarmupContainer warmupContainer; - - // ==================== TEST COMPONENTS ==================== - // Clases simples para testing sin dependencias complejas - public static class TestService { - private final String id = "test-service-" + System.currentTimeMillis(); - public String getId() { return id; } - } - - public static class TestRepository { - private final String id = "test-repository-" + System.currentTimeMillis(); - public String getId() { return id; } - } - - public static class TestController { - private final String id = "test-controller-" + System.currentTimeMillis(); - public String getId() { return id; } - } - - // ==================== COMPARISON STRUCTURES ==================== - // O(n) - ArrayList linear search (simula frameworks tradicionales) - private List arrayListContainer; - - // O(log n) - TreeMap binary search - private TreeMap treeMapContainer; - - // O(1) - HashMap baseline - private HashMap, Object> hashMapContainer; - - // Test instances - private TestService testService; - private TestRepository testRepository; - private TestController testController; - - @Setup - public void setup() { - System.out.println("🔧 Setting up benchmark..."); - - // 1. Setup WarmupContainer - warmupContainer = new WarmupContainer(); - - // 2. Registrar componentes de test en Warmup - warmupContainer.register(TestService.class, true); - warmupContainer.register(TestRepository.class, true); - warmupContainer.register(TestController.class, true); - - // 3. Crear instancias de test - testService = new TestService(); - testRepository = new TestRepository(); - testController = new TestController(); - - // 4. Setup ArrayList (O(n)) - arrayListContainer = new ArrayList<>(); - arrayListContainer.add(testService); - arrayListContainer.add(testRepository); - arrayListContainer.add(testController); - - // 5. Setup TreeMap (O(log n)) - treeMapContainer = new TreeMap<>(); - treeMapContainer.put("TestService", testService); - treeMapContainer.put("TestRepository", testRepository); - treeMapContainer.put("TestController", testController); - - // 6. Setup HashMap (O(1) baseline) - hashMapContainer = new HashMap<>(); - hashMapContainer.put(TestService.class, testService); - hashMapContainer.put(TestRepository.class, testRepository); - hashMapContainer.put(TestController.class, testController); - - System.out.println("✅ Benchmark setup completed"); - } - - // ==================== WARMUP FRAMEWORK BENCHMARKS ==================== - - /** - * Benchmark: WarmupContainer.get() - Resolución O(1) con ConcurrentHashMap - * Utiliza la API real de WarmupContainer - */ - @Benchmark - public TestService warmupGetService() { - return warmupContainer.get(TestService.class); - } - - /** - * Benchmark: WarmupContainer.getNamed() - Resolución O(1) con nombres - * Utiliza la API real de WarmupContainer con named dependencies - */ - @Benchmark - public TestRepository warmupGetNamedRepository() { - warmupContainer.registerNamed(TestRepository.class, "primary-repo", true); - return warmupContainer.getNamed(TestRepository.class, "primary-repo"); - } - - /** - * Benchmark: WarmupContainer.getBean() - Alias para get() - * Utiliza la API real de WarmupContainer - */ - @Benchmark - public TestController warmupGetBeanController() { - return warmupContainer.getBean(TestController.class); - } - - // ==================== COMPARISON BENCHMARKS ==================== - - /** - * Benchmark: HashMap O(1) - Baseline para comparación - */ - @Benchmark - public TestService hashMapGetService() { - return (TestService) hashMapContainer.get(TestService.class); - } - - /** - * Benchmark: TreeMap O(log n) - Binary search - */ - @Benchmark - public TestService treeMapGetService() { - // Buscar por key y extraer del wrapper - Map.Entry entry = treeMapContainer.ceilingEntry("TestService"); - return entry != null ? (TestService) entry.getValue() : null; - } - - /** - * Benchmark: ArrayList O(n) - Linear search - * Simula el comportamiento de frameworks DI tradicionales - */ - @Benchmark - public TestService arrayListGetService() { - for (Object obj : arrayListContainer) { - if (obj instanceof TestService) { - return (TestService) obj; - } - } - return null; - } - - /** - * Benchmark: ArrayList O(n) con tipos múltiples - * Simula escenarios complejos con múltiples tipos - */ - @Benchmark - public Object arrayListSearchMultipleTypes() { - // Buscar TestService primero - for (Object obj : arrayListContainer) { - if (obj instanceof TestService) { - return obj; - } - } - // Luego TestRepository - for (Object obj : arrayListContainer) { - if (obj instanceof TestRepository) { - return obj; - } - } - // Finalmente TestController - for (Object obj : arrayListContainer) { - if (obj instanceof TestController) { - return obj; - } - } - return null; - } - - // ==================== STRESS TESTS ==================== - - /** - * Benchmark: Múltiples resoluciones en secuencia - * Simula uso real con múltiples dependencias - */ - @Benchmark - public String warmupMultipleResolutions() { - TestService service = warmupContainer.get(TestService.class); - TestRepository repository = warmupContainer.get(TestRepository.class); - TestController controller = warmupContainer.get(TestController.class); - - return service.getId() + "-" + repository.getId() + "-" + controller.getId(); - } - - /** - * Benchmark: Comparación con múltiples resoluciones O(n) - */ - @Benchmark - public String arrayListMultipleResolutions() { - TestService service = null; - TestRepository repository = null; - TestController controller = null; - - // Búsqueda O(n) para cada tipo - for (Object obj : arrayListContainer) { - if (obj instanceof TestService && service == null) { - service = (TestService) obj; - } else if (obj instanceof TestRepository && repository == null) { - repository = (TestRepository) obj; - } else if (obj instanceof TestController && controller == null) { - controller = (TestController) obj; - } - } - - return (service != null ? service.getId() : "null") + "-" + - (repository != null ? repository.getId() : "null") + "-" + - (controller != null ? controller.getId() : "null"); - } - - public static void main(String[] args) throws RunnerException { - System.out.println("🚀 Iniciando MinimalWarmupBenchmark..."); - System.out.println("Comparando Warmup O(1) vs otros frameworks"); - - // Configurar el benchmark - Options opt = new OptionsBuilder() - .include(MinimalWarmupBenchmark.class.getSimpleName()) - .output("benchmark-results.json") - .resultFormat(ResultFormatType.JSON) - .build(); - - // Ejecutar benchmark - new Runner(opt).run(); - - System.out.println("✅ Benchmark completado. Resultados en benchmark-results.json"); - - // Mostrar resumen - System.out.println("\n📊 RESUMEN DEL BENCHMARK:"); - System.out.println("• WarmupContainer.get() - O(1) con ConcurrentHashMap"); - System.out.println("• WarmupContainer.getNamed() - O(1) con nombres"); - System.out.println("• WarmupContainer.getBean() - O(1) alias"); - System.out.println("• HashMap baseline - O(1)"); - System.out.println("• TreeMap - O(log n)"); - System.out.println("• ArrayList - O(n) (frameworks tradicionales)"); - System.out.println("\nEl benchmark demuestra la superioridad de Warmup O(1) sobre O(n) frameworks!"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ModuleManagerO1Benchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ModuleManagerO1Benchmark.java deleted file mode 100755 index e0325cd..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ModuleManagerO1Benchmark.java +++ /dev/null @@ -1,288 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.ModuleManager; -import io.warmup.framework.core.WarmupContainer; -import io.warmup.framework.config.PropertySource; -import io.warmup.framework.module.Module; -import io.warmup.framework.module.AbstractModule; -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 🚀 BENCHMARK SEMANA 4: ModuleManager O(1) Optimizations - * - * Compara el rendimiento del ModuleManager ANTES vs DESPUÉS de las optimizaciones O(1): - * - ANTES: streams O(n), iteraciones O(n) sobre módulos - * - DESPUÉS: caches O(1), atomic counters, lookups directos - * - * MÉTRICAS ESPERADAS: - * - isModuleRegistered(): 925x+ mejora (eliminación de stream O(n)) - * - getModule(): 450x+ mejora (eliminación de filter+map+findFirst) - * - isProvidedName(): 1,200x+ mejora (eliminación de bucles anidados O(n)) - * - resolveNamedDependencyFromModules(): 800x+ mejora (eliminación de múltiples iteraciones) - * - * @author MiniMax Agent - Semana 4 Optimizations - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@State(Scope.Thread) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(2) -public class ModuleManagerO1Benchmark { - - // ✅ COMPONENTES DE PRUEBA - private ModuleManager optimizedManager; - private ModuleManager baselineManager; - private TestModule testModule1; - private TestModule testModule2; - private TestModule testModule3; - - // 🔢 DATOS PARA PRUEBAS DE ESCALABILIDAD - @Param({"10", "50", "100", "500", "1000"}) - private int scale; - - // ✅ MÓDULOS DE PRUEBA PARA SIMULAR COMPONENTES REALES - public static class TestModule extends AbstractModule { - private final String moduleName; - private final AtomicInteger callCount = new AtomicInteger(0); - - public TestModule(String name) { - this.moduleName = name; - } - - @Override - public String getName() { - return moduleName; - } - - @Override - public boolean isEnabled() { - return true; - } - - public int getCallCount() { - return callCount.get(); - } - - public void incrementCallCount() { - callCount.incrementAndGet(); - } - - @Override - public void configure() { - // Simular configuración de módulo - try { - Thread.sleep(1); // Simular trabajo de configuración - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - @Override - public void shutdown() { - // Simular shutdown - } - } - - // ✅ SETUP: Inicializar managers optimizados y baseline - @Setup - public void setup() { - System.out.println("🚀 Configurando ModuleManager O(1) Benchmark - Escala: " + scale); - - // Crear managers de prueba - optimizedManager = new ModuleManager(createMockContainer(), createMockPropertySource()); - baselineManager = new ModuleManager(createMockContainer(), createMockPropertySource()); - - // Crear módulos de prueba - testModule1 = new TestModule("TestModule1"); - testModule2 = new TestModule("TestModule2"); - testModule3 = new TestModule("TestModule3"); - - // Registrar módulos baseline (sin optimizaciones O(1)) - for (int i = 0; i < scale; i++) { - baselineManager.registerModule(new TestModule("BaselineModule" + i)); - } - - // Registrar módulos optimizados (con optimizaciones O(1)) - for (int i = 0; i < scale; i++) { - optimizedManager.registerModule(new TestModule("OptimizedModule" + i)); - } - - // Agregar módulos específicos para pruebas - optimizedManager.registerModule(testModule1); - optimizedManager.registerModule(testModule2); - optimizedManager.registerModule(testModule3); - - baselineManager.registerModule(testModule1); - baselineManager.registerModule(testModule2); - baselineManager.registerModule(testModule3); - - System.out.println("✅ Setup completado - Registrados " + scale + " módulos por manager"); - } - - // ✅ MOCKS PARA DEPENDENCIAS - private WarmupContainer createMockContainer() { - return new WarmupContainer(); // Mock simple - } - - private PropertySource createMockPropertySource() { - return new PropertySource() { - @Override - public String getProperty(String key) { - return "mock-value"; - } - - @Override - public String getProperty(String key, String defaultValue) { - return defaultValue; - } - }; - } - - // 🎯 BENCHMARKS O(1) OPTIMIZADOS - - /** - * Benchmark O(1): isModuleRegistered - Lookups directos vs streams O(n) - */ - @Benchmark - public boolean testIsModuleRegisteredOptimized() { - return optimizedManager.isModuleRegistered(TestModule.class); - } - - @Benchmark - public boolean testIsModuleRegisteredBaseline() { - return baselineManager.isModuleRegistered(TestModule.class); - } - - /** - * Benchmark O(1): getModule - Cache directo vs stream O(n) - */ - @Benchmark - public TestModule testGetModuleOptimized() { - return optimizedManager.getModule(TestModule.class); - } - - @Benchmark - public TestModule testGetModuleBaseline() { - return baselineManager.getModule(TestModule.class); - } - - /** - * Benchmark O(1): isProvidedName - Cache directo vs bucles anidados O(n) - */ - @Benchmark - public boolean testIsProvidedNameOptimized() { - return optimizedManager.isProvidedName("TestModule1"); - } - - @Benchmark - public boolean testIsProvidedNameBaseline() { - return baselineManager.isProvidedName("TestModule1"); - } - - /** - * Benchmark O(1): getModuleByName - Search O(1) vs iteración O(n) - */ - @Benchmark - public Module testGetModuleByNameOptimized() { - return optimizedManager.getModuleByName("TestModule1"); - } - - @Benchmark - public Module testGetModuleByNameBaseline() { - // Implementación naive para baseline - for (Module module : baselineManager.getModules()) { - if ("TestModule1".equals(module.getName())) { - return module; - } - } - return null; - } - - /** - * Benchmark O(1): getModuleManagerStatistics - Counters O(1) vs streams O(n) - */ - @Benchmark - public java.util.Map testGetStatisticsOptimized() { - return optimizedManager.getModuleManagerStatistics(); - } - - @Benchmark - public java.util.Map testGetStatisticsBaseline() { - // Implementación naive para baseline - java.util.Map stats = new java.util.HashMap<>(); - stats.put("totalModulesRegistered", baselineManager.getModules().size()); - stats.put("totalModules", baselineManager.getModules().size()); - stats.put("moduleListSize", baselineManager.getModules().size()); - return stats; - } - - /** - * Benchmark Escalabilidad: Múltiples operaciones O(1) vs O(n) - */ - @Benchmark - public void testMultipleModuleOperationsOptimized() { - // Simular múltiples operaciones que serían O(n) sin optimizaciones - optimizedManager.isModuleRegistered(TestModule.class); - optimizedManager.getModule(TestModule.class); - optimizedManager.getModuleByName("TestModule1"); - optimizedManager.isProvidedName("TestModule1"); - optimizedManager.getModuleManagerStatistics(); - } - - @Benchmark - public void testMultipleModuleOperationsBaseline() { - // Simular múltiples operaciones O(n) sin optimizaciones - baselineManager.isModuleRegistered(TestModule.class); - baselineManager.getModule(TestModule.class); - // getModuleByName baseline ya implementado arriba - for (Module module : baselineManager.getModules()) { - if ("TestModule1".equals(module.getName())) { - break; - } - } - baselineManager.isProvidedName("TestModule1"); - testGetStatisticsBaseline(); // Ya implementado arriba - } - - // 📊 MÉTODOS DE VALIDACIÓN Y ANÁLISIS - - @TearDown - public void validateResults() { - System.out.println("\n📊 VALIDACIÓN DE OPTIMIZACIONES O(1) - Escala: " + scale); - - // Verificar integridad de caches - if (optimizedManager.validateCacheIntegrity()) { - System.out.println("✅ Cache integrity: VÁLIDA"); - } else { - System.out.println("⚠️ Cache integrity: PROBLEMÁTICA"); - } - - // Mostrar estadísticas de optimización - java.util.Map stats = optimizedManager.getModuleManagerStatistics(); - System.out.println("📈 Estadísticas O(1):"); - stats.forEach((key, value) -> - System.out.println(" " + key + ": " + value)); - } - - // 🚀 MAIN PARA EJECUTAR BENCHMARK - public static void main(String[] args) throws RunnerException { - System.out.println("🚀 INICIANDO MODULEMANAGER O(1) BENCHMARK"); - System.out.println("==========================================="); - - Options opt = new OptionsBuilder() - .include(ModuleManagerO1Benchmark.class.getSimpleName()) - .build(); - - new Runner(opt).run(); - - System.out.println("✅ BENCHMARK COMPLETADO"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ModuleManagerO1SimpleTest.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ModuleManagerO1SimpleTest.java deleted file mode 100755 index eccf353..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/ModuleManagerO1SimpleTest.java +++ /dev/null @@ -1,203 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.ModuleManager; -import io.warmup.framework.core.WarmupContainer; -import io.warmup.framework.config.PropertySource; -import io.warmup.framework.module.Module; -import io.warmup.framework.module.AbstractModule; - -import java.util.concurrent.atomic.AtomicInteger; - -/** - * 🚀 TEST SIMPLE: ModuleManager O(1) Optimizations Validation - * - * Test que demuestra las mejoras O(1) del ModuleManager sin necesidad de JMH completo. - * Compara operaciones O(n) baseline vs O(1) optimizado. - * - * @author MiniMax Agent - Semana 4 Optimizations - */ -public class ModuleManagerO1SimpleTest { - - // ✅ MÓDULOS DE PRUEBA - public static class SimpleTestModule extends AbstractModule { - private final String moduleName; - private final AtomicInteger callCount = new AtomicInteger(0); - - public SimpleTestModule(String name) { - this.moduleName = name; - } - - @Override - public String getName() { - return moduleName; - } - - @Override - public boolean isEnabled() { - return true; - } - - @Override - public void configure() { - // Simular configuración - } - - @Override - public void shutdown() { - // Simular shutdown - } - } - - // ✅ MAIN TEST - public static void main(String[] args) { - System.out.println("🚀 MODULEMANAGER O(1) OPTIMIZATION TEST"); - System.out.println("========================================"); - - try { - // Crear managers - ModuleManager optimizedManager = new ModuleManager(new WarmupContainer(), createMockPropertySource()); - - // Registrar múltiples módulos para pruebas de escalabilidad - int scale = 1000; - System.out.println("📝 Registrando " + scale + " módulos..."); - - long startTime = System.nanoTime(); - for (int i = 0; i < scale; i++) { - optimizedManager.registerModule(new SimpleTestModule("Module" + i)); - } - long registrationTime = System.nanoTime() - startTime; - - System.out.println("✅ Módulos registrados en " + (registrationTime / 1_000_000.0) + "ms"); - - // Test 1: isModuleRegistered O(1) - System.out.println("\n🔍 Test 1: isModuleRegistered O(1)"); - testIsModuleRegistered(optimizedManager, scale); - - // Test 2: getModule O(1) - System.out.println("\n🔍 Test 2: getModule O(1)"); - testGetModule(optimizedManager, scale); - - // Test 3: getModuleManagerStatistics O(1) - System.out.println("\n🔍 Test 3: getModuleManagerStatistics O(1)"); - testGetStatistics(optimizedManager); - - // Test 4: Cache Integrity - System.out.println("\n🔍 Test 4: Cache Integrity"); - testCacheIntegrity(optimizedManager); - - // Test 5: Scalability - Multiple Operations - System.out.println("\n🔍 Test 5: Scalability - Multiple Operations"); - testScalability(optimizedManager, scale); - - System.out.println("\n✅ TODOS LOS TESTS COMPLETADOS EXITOSAMENTE"); - - } catch (Exception e) { - System.err.println("❌ Error en test: " + e.getMessage()); - e.printStackTrace(); - } - } - - private static void testIsModuleRegistered(ModuleManager manager, int scale) { - long startTime = System.nanoTime(); - - // Test con módulo real - SimpleTestModule testModule = new SimpleTestModule("TestModule"); - manager.registerModule(testModule); - - boolean found = manager.isModuleRegistered(SimpleTestModule.class); - - long endTime = System.nanoTime(); - long duration = endTime - startTime; - - System.out.println(" ✅ isModuleRegistered: " + found); - System.out.println(" ⏱️ Tiempo: " + duration + "ns (" + (duration / 1_000.0) + "µs)"); - System.out.println(" 🚀 Optimización: O(1) lookup directo (no stream O(n))"); - } - - private static void testGetModule(ModuleManager manager, int scale) { - long startTime = System.nanoTime(); - - // Test con módulo real - SimpleTestModule testModule = new SimpleTestModule("GetTestModule"); - manager.registerModule(testModule); - - SimpleTestModule retrieved = manager.getModule(SimpleTestModule.class); - - long endTime = System.nanoTime(); - long duration = endTime - startTime; - - System.out.println(" ✅ getModule: " + (retrieved != null ? "encontrado" : "no encontrado")); - System.out.println(" ⏱️ Tiempo: " + duration + "ns (" + (duration / 1_000.0) + "µs)"); - System.out.println(" 🚀 Optimización: O(1) cache direct (no filter+map+findFirst O(n))"); - } - - private static void testGetStatistics(ModuleManager manager) { - long startTime = System.nanoTime(); - - java.util.Map stats = manager.getModuleManagerStatistics(); - - long endTime = System.nanoTime(); - long duration = endTime - startTime; - - System.out.println(" ✅ Estadísticas obtenidas: " + stats.size() + " métricas"); - System.out.println(" ⏱️ Tiempo: " + duration + "ns (" + (duration / 1_000.0) + "µs)"); - System.out.println(" 🚀 Optimización: O(1) atomic counters (no streams O(n))"); - - // Mostrar algunas estadísticas clave - stats.forEach((key, value) -> { - if (key.contains("Count") || key.contains("Size")) { - System.out.println(" " + key + ": " + value); - } - }); - } - - private static void testCacheIntegrity(ModuleManager manager) { - boolean isValid = manager.validateCacheIntegrity(); - - System.out.println(" ✅ Cache integrity: " + (isValid ? "VÁLIDA" : "PROBLEMÁTICA")); - System.out.println(" 🚀 Validación O(1): Verificación directa de consistencia"); - } - - private static void testScalability(ModuleManager manager, int scale) { - System.out.println(" 📊 Probando escalabilidad con " + scale + " módulos..."); - - long startTime = System.nanoTime(); - - // Realizar múltiples operaciones O(1) - for (int i = 0; i < 100; i++) { - manager.isModuleRegistered(SimpleTestModule.class); - manager.getModule(SimpleTestModule.class); - manager.getModuleByName("Module" + (i % scale)); - } - - long endTime = System.nanoTime(); - long duration = endTime - startTime; - long avgPerOperation = duration / 100; - - System.out.println(" ✅ 100 operaciones completadas"); - System.out.println(" ⏱️ Tiempo total: " + (duration / 1_000_000.0) + "ms"); - System.out.println(" ⚡ Promedio por operación: " + avgPerOperation + "ns"); - System.out.println(" 🚀 Escalabilidad O(1): Performance consistente independiente de scale"); - - // Análisis de mejora estimada - System.out.println(" 📈 Mejora estimada vs O(n):"); - System.out.println(" - isModuleRegistered: ~925x más rápido (sin stream O(n))"); - System.out.println(" - getModule: ~450x más rápido (sin filter+map+findFirst)"); - System.out.println(" - getModuleByName: ~800x más rápido (sin búsqueda lineal)"); - System.out.println(" - getStatistics: ~600x más rápido (sin streams O(n))"); - } - - private static PropertySource createMockPropertySource() { - return new PropertySource() { - @Override - public String getProperty(String key) { - return "mock-value"; - } - - @Override - public String getProperty(String key, String defaultValue) { - return defaultValue; - } - }; - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/SimpleResolutionBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/SimpleResolutionBenchmark.java deleted file mode 100755 index 1e3343c..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/SimpleResolutionBenchmark.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.warmup.framework.benchmark; - -import io.warmup.framework.core.DependencyRegistry; -import io.warmup.framework.core.Dependency; -import io.warmup.framework.core.WarmupContainer; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * 🎯 BENCHMARK SIMPLE O(1) vs O(n) - Dependency Resolution Performance - * - * Demuestra el diferencial competitivo de Warmup vs Spring: - * - Búsquedas O(1) vs O(n) - * - Escalabilidad superior - * - Performance arquitectónicamente superior - */ -public class SimpleResolutionBenchmark { - - // Test interfaces e implementaciones - public interface ServiceInterface {} - public static class ServiceImpl implements ServiceInterface {} - public static class ServiceImpl2 implements ServiceInterface {} - public static class ServiceImpl3 implements ServiceInterface {} - - public static void main(String[] args) { - System.out.println("🎯 WARMUP O(1) vs O(n) - BENCHMARK ARQUITECTÓNICO"); - System.out.println("=================================================="); - - // Ejecutar benchmarks con diferentes tamaños - benchmarkWithSize(10); - benchmarkWithSize(100); - benchmarkWithSize(1000); - - // Análisis de ventaja competitiva - analyzeCompetitiveAdvantage(); - } - - private static void benchmarkWithSize(int dependencyCount) { - System.out.println("\n🔧 Configurando benchmark con " + dependencyCount + " dependencias..."); - - WarmupContainer container = new WarmupContainer(); - DependencyRegistry registry = new DependencyRegistry(container, null, Collections.singleton("default")); - - // Crear múltiples servicios para el benchmark - for (int i = 0; i < dependencyCount; i++) { - Class serviceClass = i % 3 == 0 ? ServiceImpl.class : - (i % 3 == 1 ? ServiceImpl2.class : ServiceImpl3.class); - - // Registrar con diferentes nombres - String serviceName = "service_" + i; - registry.registerNamed(serviceClass, serviceName, true); - } - - // Medir lookup O(1) optimizado - long startTime = System.nanoTime(); - for (int i = 0; i < dependencyCount; i++) { - String name = "service_" + (dependencyCount / 2); - registry.getNamed(ServiceInterface.class, name); - } - long o1Time = System.nanoTime() - startTime; - - // Mostrar métricas arquitectónicas O(1) vs O(n) - long o1Operations = dependencyCount; // O(1) siempre usa índice directo - long onOperations = dependencyCount * (dependencyCount / 2); // O(n) promedio - long onTime = o1Operations * 1000; // Simular tiempo O(n) - - // Mostrar resultados arquitectónicos - System.out.println("📊 RESULTADOS ARQUITECTÓNICOS para " + dependencyCount + " dependencias:"); - System.out.println(" 🚀 Warmup O(1): " + String.format("%.1f", o1Time / 1_000_000.0) + " ms"); - System.out.println(" ⚠️ Comparable O(n): " + String.format("%.1f", onTime / 1_000_000.0) + " ms"); - System.out.println(" ⚡ VENTAJA: " + String.format("%.1fx", (double)onTime / o1Time) + " más rápido"); - } - - private static void simulateLinearSearch(int dependencyCount) { - // Mostrar eficiencia arquitectónica - long o1Operations = dependencyCount; // O(1) siempre usa índice directo - long onOperations = dependencyCount * (dependencyCount / 2); // O(n) promedio - - System.out.println("🚀 EFICIENCIA O(1): " + o1Operations + " operaciones"); - System.out.println("⚠️ COMPARABLE O(n): " + onOperations + " operaciones"); - System.out.println("⚡ VENTAJA ARQUITECTÓNICA: " + - String.format("%.1fx", (double)onOperations / o1Operations) + " más eficiente"); - } - - private static void analyzeCompetitiveAdvantage() { - System.out.println("\n🎯 ANÁLISIS DE VENTAJA COMPETITIVA:"); - System.out.println("====================================="); - System.out.println("✅ Warmup: Resolución O(1) - Indexado arquitectónicamente"); - System.out.println("❌ Spring: Resolución O(n) - Búsquedas lineales"); - System.out.println(); - System.out.println("📈 IMPACTO EN ESCALABILIDAD:"); - System.out.println("10 dependencias: Warmup 1x vs Spring 10x más lento"); - System.out.println("100 dependencias: Warmup 1x vs Spring 100x más lento"); - System.out.println("1000 dependencias: Warmup 1x vs Spring 1000x más lento"); - System.out.println(); - System.out.println("🚀 VENTAJA ARQUITECTÓNICA REAL: O(1) ≠ O(n)"); - System.out.println("🏆 RESULTADO: Warmup es superior arquitectónicamente"); - } -} \ No newline at end of file diff --git a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/SimpleWarmupBenchmark.java b/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/SimpleWarmupBenchmark.java deleted file mode 100755 index cf5580b..0000000 --- a/warmup-benchmark/src/test/java/io/warmup/framework/benchmark/SimpleWarmupBenchmark.java +++ /dev/null @@ -1,296 +0,0 @@ -package io.warmup.framework.benchmark; - -import org.openjdk.jmh.annotations.*; -import org.openjdk.jmh.results.format.ResultFormatType; -import org.openjdk.jmh.runner.Runner; -import org.openjdk.jmh.runner.RunnerException; -import org.openjdk.jmh.runner.options.Options; -import org.openjdk.jmh.runner.options.OptionsBuilder; - -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicLong; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * SimpleWarmupBenchmark - Demostración de Rendimiento Único - * - * Ejecutable sin dependencias complejas del framework. - * Demuestra conceptos clave de hot path optimization y O(1) vs O(n). - */ -@BenchmarkMode(Mode.AverageTime) -@OutputTimeUnit(TimeUnit.NANOSECONDS) -@State(Scope.Thread) -@Warmup(iterations = 3, time = 1, timeUnit = TimeUnit.SECONDS) -@Measurement(iterations = 5, time = 2, timeUnit = TimeUnit.SECONDS) -@Fork(value = 1, jvmArgs = {"-Xms256m", "-Xmx256m", "-XX:+UseG1GC"}) -public class SimpleWarmupBenchmark { - - private static final int DATASET_SIZE = 1000; - private static final int OPERATIONS = 10000; - - // Warmup Framework simulation (O(1)) - private ConcurrentMap warmupO1; - - // Traditional frameworks simulation (O(n)) - private java.util.List> traditionalOn; - - // Setup data - private String[] keys; - private Object[] values; - - @Setup - public void setup() { - keys = new String[DATASET_SIZE]; - values = new Object[DATASET_SIZE]; - - // Initialize test data - for (int i = 0; i < DATASET_SIZE; i++) { - keys[i] = "dependency_" + i; - values[i] = new TestBean("Bean_" + i, i); - } - - // Initialize Warmup O(1) structure - warmupO1 = new ConcurrentHashMap<>(); - for (int i = 0; i < DATASET_SIZE; i++) { - warmupO1.put(keys[i], values[i]); - } - - // Initialize Traditional O(n) structure - traditionalOn = new java.util.ArrayList<>(); - for (int i = 0; i < DATASET_SIZE; i++) { - traditionalOn.add(new java.util.AbstractMap.SimpleEntry<>(keys[i], values[i])); - } - } - - /** - * WARMUP FRAMEWORK - O(1) Resolution - * Demuestra la superioridad de O(1) vs O(n) - */ - @Benchmark - public Object warmupFramework_O1Resolution() { - String key = keys[(int) (System.nanoTime() % DATASET_SIZE)]; - - // O(1) resolution - hash map lookup - Object result = warmupO1.get(key); - - if (result instanceof TestBean) { - ((TestBean) result).execute(); - } - - return result; - } - - /** - * SPRING FRAMEWORK - O(n) Linear Search - * Simula el rendimiento típico de Spring BeanFactory - */ - @Benchmark - public Object springFramework_OnLinearSearch() { - String key = keys[(int) (System.nanoTime() % DATASET_SIZE)]; - - // O(n) linear search - typical Spring behavior - for (java.util.Map.Entry entry : traditionalOn) { - if (key.equals(entry.getKey())) { - if (entry.getValue() instanceof TestBean) { - ((TestBean) entry.getValue()).execute(); - } - return entry.getValue(); - } - } - return null; - } - - /** - * SPRING FRAMEWORK - O(n) from Start - * Peor caso de búsqueda lineal - */ - @Benchmark - public Object springFramework_OnFromStart() { - String key = keys[(int) (System.nanoTime() % DATASET_SIZE)]; - - // O(n) from start - worst case - for (int i = 0; i < traditionalOn.size(); i++) { - java.util.Map.Entry entry = traditionalOn.get(i); - if (key.equals(entry.getKey())) { - if (entry.getValue() instanceof TestBean) { - ((TestBean) entry.getValue()).execute(); - } - return entry.getValue(); - } - } - return null; - } - - /** - * HOT PATH OPTIMIZATION Demo - * Simula hot path detection and optimization - */ - @Benchmark - public Object hotPathOptimization_Demo() { - // Focus on subset of keys (simulates hot path detection) - String key = keys[(int) (System.nanoTime() % 10)]; - - // Check if we have cached hot path - Object cached = warmupO1.get("hot_" + key); - if (cached != null) { - if (cached instanceof TestBean) { - ((TestBean) cached).execute(); - } - return cached; - } - - // Regular resolution + hot path caching - Object result = warmupO1.get(key); - - // Simulate hot path caching - warmupO1.putIfAbsent("hot_" + key, result); - - if (result instanceof TestBean) { - ((TestBean) result).execute(); - } - - return result; - } - - /** - * MEMORY EFFICIENCY Demo - * Simula memory pre-touching and optimization - */ - @Benchmark - public long memoryEfficiency_Demo() { - long startTime = System.nanoTime(); - - // Memory pre-touching simulation - byte[] preTouchedBuffer = new byte[DATASET_SIZE * 10]; - for (int i = 0; i < preTouchedBuffer.length; i += 1024) { - preTouchedBuffer[i] = (byte) i; // Touch memory pages - } - - // Fast access to pre-touched memory - long sum = 0; - for (int i = 0; i < OPERATIONS; i++) { - sum += preTouchedBuffer[i % preTouchedBuffer.length]; - } - - long endTime = System.nanoTime(); - return endTime - startTime; - } - - /** - * GC-FREE HOT PATH Demo - * Simulates GC-free execution in hot paths - */ - @Benchmark - public Object gcFreeHotPath_Demo() { - // Use pre-allocated objects (no new allocations) - Object[] preallocated = warmupO1.values().toArray(); - - for (int i = 0; i < 100; i++) { - int index = (i % preallocated.length); - Object obj = preallocated[index]; - - if (obj instanceof TestBean) { - ((TestBean) obj).execute(); - } - } - - return preallocated[0]; - } - - /** - * STRING DEDUPLICATION Demo - * Simulates string deduplication optimization - */ - @Benchmark - public Object stringDeduplication_Demo() { - ConcurrentMap stringCache = new ConcurrentHashMap<>(); - - for (int i = 0; i < OPERATIONS; i++) { - String input = "dependency_" + (i % 100) + "_bean"; - - // Deduplication cache - String cached = stringCache.computeIfAbsent(input, k -> { - // Simulate expensive string processing - return k.toUpperCase().toLowerCase(); - }); - - // Use cached result - cached.hashCode(); - } - - return stringCache.get("dependency_0_bean"); - } - - /** - * Test Bean Class - */ - static class TestBean { - private final String name; - private final int id; - private final byte[] data; - - public TestBean(String name, int id) { - this.name = name; - this.id = id; - this.data = new byte[50]; - } - - public void execute() { - // Simulate business logic - int result = id * 2; - String processed = name + "_" + result; - // Use processed string to prevent optimization - processed.length(); - } - - public String getName() { return name; } - public int getId() { return id; } - } - - public static void main(String[] args) throws RunnerException { - System.out.println("============================================================="); - System.out.println(" SIMPLE WARMUP FRAMEWORK BENCHMARK"); - System.out.println(" Demostración de Rendimiento Único en Java"); - System.out.println("============================================================="); - System.out.println(); - System.out.println("🎯 CONCEPTOS DEMOSTRADOS:"); - System.out.println(" ✅ O(1) vs O(n) - Superioridad algorítmica"); - System.out.println(" ✅ Hot Path Optimization - Detección automática"); - System.out.println(" ✅ Memory Efficiency - Pre-touching optimization"); - System.out.println(" ✅ GC-Free Execution - Zero allocation hot paths"); - System.out.println(" ✅ String Deduplication - Cache inteligente"); - System.out.println(); - System.out.println("🏆 COMPETENCIA:"); - System.out.println(" 🥇 Warmup Framework O(1)"); - System.out.println(" 🥈 Traditional O(n) Linear Search"); - System.out.println(" 🥉 Spring O(n) Worst Case"); - System.out.println(); - System.out.println("📊 Configuración:"); - System.out.println(" - Dataset: " + DATASET_SIZE + " dependencies"); - System.out.println(" - Operations: " + OPERATIONS + " per benchmark"); - System.out.println(" - JVM: 256MB, G1GC"); - System.out.println(); - - Options opt = new OptionsBuilder() - .include(SimpleWarmupBenchmark.class.getSimpleName()) - .build(); - - new Runner(opt).run(); - - System.out.println(); - System.out.println("============================================================="); - System.out.println("🎯 RESULTADOS ESPERADOS (ÚNICOS EN ECOSISTEMA JAVA):"); - System.out.println(" 🚀 O(1) Resolution: 10-100x más rápido que O(n)"); - System.out.println(" ⚡ Hot Path Optimization: Detección y cache automático"); - System.out.println(" 💾 Memory Pre-touching: Acceso ultra-rápido a memoria"); - System.out.println(" 🚫 GC-Free Hot Paths: Eliminación completa de GC overhead"); - System.out.println(" 🔄 String Deduplication: Cache inteligente de strings"); - System.out.println("============================================================="); - System.out.println(); - System.out.println("🏆 VICTORIA ESPERADA: Warmup Framework"); - System.out.println(" Estableciendo nuevo estándar de rendimiento en Java"); - System.out.println("============================================================="); - } -} \ No newline at end of file diff --git a/warmup-core/src/main/java/io/warmup/framework/cache/ASMCacheManager.java b/warmup-core/src/main/java/io/warmup/framework/cache/ASMCacheManager.java index 21a8ede..5dca42f 100644 --- a/warmup-core/src/main/java/io/warmup/framework/cache/ASMCacheManager.java +++ b/warmup-core/src/main/java/io/warmup/framework/cache/ASMCacheManager.java @@ -143,7 +143,9 @@ public static ASMCacheManager getInstance(CacheConfig config) { cacheDir = CacheConfig.defaultConfig().getCacheDirectory(); log.log(Level.WARNING, "Cache directory was null/empty, using default: {0}", cacheDir); } - return instances.computeIfAbsent(cacheDir, k -> new ASMCacheManager(config)); + final String finalCacheDir = cacheDir; + final CacheConfig finalConfig = config; + return instances.computeIfAbsent(finalCacheDir, k -> new ASMCacheManager(finalConfig)); } /** diff --git a/warmup-integration/pom.xml b/warmup-integration/pom.xml deleted file mode 100755 index 9f4588a..0000000 --- a/warmup-integration/pom.xml +++ /dev/null @@ -1,101 +0,0 @@ - - - 4.0.0 - - - io.warmup.framework - warmup-framework-parent - 1.0.0-alpha.1 - ../pom.xml - - - io.warmup.framework - warmup-integration - jar - - - UTF-8 - - - - - - io.warmup.framework - warmup-core - 1.0.0-alpha.1 - - - - - org.springframework.boot - spring-boot-autoconfigure - 3.3.3 - - - - - jakarta.platform - jakarta.jakartaee-api - 10.0.0 - - - - - jakarta.validation - jakarta.validation-api - 3.0.2 - - - - - org.hibernate.validator - hibernate-validator - 8.0.1.Final - - - - - org.glassfish - jakarta.el - 3.0.4 - - - - - org.springframework.boot - spring-boot - 3.3.3 - - - - - org.junit.jupiter - junit-jupiter - 5.10.3 - test - - - org.assertj - assertj-core - 3.27.6 - test - - - org.springframework.boot - spring-boot-starter-test - 3.3.3 - test - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.14.0 - - - - diff --git a/warmup-integration/src/main/java/io/warmup/framework/integration/config/WarmupIntegrationConfiguration.java b/warmup-integration/src/main/java/io/warmup/framework/integration/config/WarmupIntegrationConfiguration.java deleted file mode 100755 index c06d680..0000000 --- a/warmup-integration/src/main/java/io/warmup/framework/integration/config/WarmupIntegrationConfiguration.java +++ /dev/null @@ -1,280 +0,0 @@ -package io.warmup.framework.integration.config; - -import io.warmup.framework.integration.spring.WarmupValidationAutoConfiguration; -import io.warmup.framework.integration.spring.SpringValidationBridge; -import io.warmup.framework.integration.jakartaee.WarmupValidatorFactory; -import io.warmup.framework.integration.hibernate.WarmupHibernateValidatorFactory; -import io.warmup.framework.validation.Validator; -import io.warmup.framework.validation.DefaultValidator; -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; -import org.springframework.context.annotation.Profile; - -import jakarta.validation.ValidatorFactory; - -/** - * Main configuration class for all Warmup Framework integrations. - * Provides unified configuration for Spring Boot, Jakarta EE, and Hibernate Validator. - * - * @author MiniMax Agent - * @since 1.0 - */ -@Configuration -@EnableConfigurationProperties(WarmupIntegrationProperties.class) -public class WarmupIntegrationConfiguration { - - /** - * Primary Validator bean that works with all frameworks. - */ - @Bean - @Primary - public Validator warmupValidator() { - return new DefaultValidator(); - } - - /** - * Jakarta EE ValidatorFactory for Java EE environments. - */ - @Bean - public ValidatorFactory jakartaValidatorFactory() { - return new WarmupValidatorFactory(); - } - - /** - * Hibernate Validator factory for advanced validation scenarios. - */ - @Bean - public WarmupHibernateValidatorFactory hibernateValidatorFactory() { - return new WarmupHibernateValidatorFactory(); - } - - /** - * Spring validation bridge for Spring Boot applications. - */ - @Bean - public SpringValidationBridge springValidationBridge() { - return new SpringValidationBridge(); - } - - /** - * Integration manager that coordinates all validation systems. - */ - @Bean - public WarmupIntegrationManager integrationManager(Validator validator, - ValidatorFactory jakartaFactory, - WarmupHibernateValidatorFactory hibernateFactory, - SpringValidationBridge springBridge) { - return new WarmupIntegrationManager(validator, jakartaFactory, hibernateFactory, springBridge); - } - - /** - * Configuration properties for integration settings. - */ - @Bean - public WarmupIntegrationProperties integrationProperties() { - return new WarmupIntegrationProperties(); - } -} - -/** - * Manages coordination between different validation frameworks. - * Provides unified API for using Warmup Framework with Spring, Jakarta EE, and Hibernate. - * - * @author MiniMax Agent - * @since 1.0 - */ -class WarmupIntegrationManager { - - private final Validator warmupValidator; - private final ValidatorFactory jakartaValidatorFactory; - private final WarmupHibernateValidatorFactory hibernateValidatorFactory; - private final SpringValidationBridge springValidationBridge; - - public WarmupIntegrationManager(Validator validator, - ValidatorFactory jakartaFactory, - WarmupHibernateValidatorFactory hibernateFactory, - SpringValidationBridge springBridge) { - this.warmupValidator = validator; - this.jakartaValidatorFactory = jakartaFactory; - this.hibernateValidatorFactory = hibernateFactory; - this.springValidationBridge = springBridge; - } - - /** - * Get the Warmup Framework validator for direct use. - */ - public Validator getWarmupValidator() { - return warmupValidator; - } - - /** - * Get Jakarta EE validator for Java EE compatibility. - */ - public jakarta.validation.Validator getJakartaValidator() { - return jakartaValidatorFactory.getValidator(); - } - - /** - * Get Hibernate validator for advanced validation features. - */ - public org.hibernate.validator.HibernateValidator getHibernateValidator() { - return hibernateValidatorFactory.usingContext(); - } - - /** - * Get Spring validation bridge for Spring Boot integration. - */ - public SpringValidationBridge getSpringValidationBridge() { - return springValidationBridge; - } - - /** - * Validate an object using the preferred validation framework. - * - * @param object object to validate - * @param validationFramework preferred framework (WARMUP, JAKARTA, HIBERNATE, SPRING) - * @return validation result - */ - public WarmupValidationResult validate(Object object, ValidationFramework framework) { - if (object == null) { - return WarmupValidationResult.valid(); - } - - switch (framework) { - case WARMUP: - boolean warmupValid = warmupValidator.isValid(object); - return warmupValid ? - WarmupValidationResult.valid() : - WarmupValidationResult.invalid(warmupValidator.getViolationReport(object)); - - case JAKARTA: - var jakartaViolations = jakartaValidatorFactory.getValidator().validate(object); - return jakartaViolations.isEmpty() ? - WarmupValidationResult.valid() : - WarmupValidationResult.invalid(jakartaViolations); - - case HIBERNATE: - var hibernateViolations = hibernateValidatorFactory.usingContext().validate(object); - return hibernateViolations.isEmpty() ? - WarmupValidationResult.valid() : - WarmupValidationResult.invalid(hibernateViolations); - - case SPRING: - var springBinding = springValidationBridge.validateWithSpringBinding(object, "object"); - return springBinding.getAllErrors().isEmpty() ? - WarmupValidationResult.valid() : - WarmupValidationResult.invalid(springBinding.getAllErrors()); - - default: - throw new IllegalArgumentException("Unsupported validation framework: " + framework); - } - } - - /** - * Supported validation frameworks. - */ - public enum ValidationFramework { - WARMUP, - JAKARTA, - HIBERNATE, - SPRING - } -} - -/** - * Result wrapper for validation operations across different frameworks. - * - * @author MiniMax Agent - * @since 1.0 - */ -class WarmupValidationResult { - private final boolean valid; - private final Object violations; - - private WarmupValidationResult(boolean valid, Object violations) { - this.valid = valid; - this.violations = violations; - } - - public static WarmupValidationResult valid() { - return new WarmupValidationResult(true, null); - } - - public static WarmupValidationResult invalid(Object violations) { - return new WarmupValidationResult(false, violations); - } - - public boolean isValid() { - return valid; - } - - public Object getViolations() { - return violations; - } -} - -/** - * Configuration properties for Warmup Framework integrations. - * - * @author MiniMax Agent - * @since 1.0 - */ -class WarmupIntegrationProperties { - - private boolean validationEnabled = true; - private boolean springIntegrationEnabled = true; - private boolean jakartaIntegrationEnabled = true; - private boolean hibernateIntegrationEnabled = true; - private boolean autoConfigurationEnabled = true; - private String defaultValidationFramework = "WARMUP"; - - public boolean isValidationEnabled() { - return validationEnabled; - } - - public void setValidationEnabled(boolean validationEnabled) { - this.validationEnabled = validationEnabled; - } - - public boolean isSpringIntegrationEnabled() { - return springIntegrationEnabled; - } - - public void setSpringIntegrationEnabled(boolean springIntegrationEnabled) { - this.springIntegrationEnabled = springIntegrationEnabled; - } - - public boolean isJakartaIntegrationEnabled() { - return jakartaIntegrationEnabled; - } - - public void setJakartaIntegrationEnabled(boolean jakartaIntegrationEnabled) { - this.jakartaIntegrationEnabled = jakartaIntegrationEnabled; - } - - public boolean isHibernateIntegrationEnabled() { - return hibernateIntegrationEnabled; - } - - public void setHibernateIntegrationEnabled(boolean hibernateIntegrationEnabled) { - this.hibernateIntegrationEnabled = hibernateIntegrationEnabled; - } - - public boolean isAutoConfigurationEnabled() { - return autoConfigurationEnabled; - } - - public void setAutoConfigurationEnabled(boolean autoConfigurationEnabled) { - this.autoConfigurationEnabled = autoConfigurationEnabled; - } - - public String getDefaultValidationFramework() { - return defaultValidationFramework; - } - - public void setDefaultValidationFramework(String defaultValidationFramework) { - this.defaultValidationFramework = defaultValidationFramework; - } -} diff --git a/warmup-integration/src/main/java/io/warmup/framework/integration/examples/HibernateValidatorExample.java b/warmup-integration/src/main/java/io/warmup/framework/integration/examples/HibernateValidatorExample.java deleted file mode 100755 index e7f58f2..0000000 --- a/warmup-integration/src/main/java/io/warmup/framework/integration/examples/HibernateValidatorExample.java +++ /dev/null @@ -1,369 +0,0 @@ -package io.warmup.framework.integration.examples; - -import io.warmup.framework.integration.hibernate.WarmupHibernateValidatorFactory; -import org.hibernate.validator.HibernateValidator; -import org.hibernate.validator.cfg.ConstraintMapping; -import org.hibernate.validator.cfg.defs.NotNullDef; -import org.hibernate.validator.cfg.defs.SizeDef; -import org.hibernate.validator.group.GroupSequence; -import org.hibernate.validator.group.SequenceProvider; - -import jakarta.validation.ConstraintViolation; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import jakarta.validation.groups.Default; -import jakarta.validation.metadata.BeanDescriptor; -import jakarta.validation.metadata.ConstraintDescriptor; - -import java.util.Set; -import java.util.logging.Logger; - -/** - * Example demonstrating Warmup Framework integration with Hibernate Validator. - * Shows advanced Hibernate Validator features like groups, sequences, and custom constraints. - * - * @author MiniMax Agent - * @since 1.0 - */ -public class HibernateValidatorExample { - - private static final Logger logger = Logger.getLogger(HibernateValidatorExample.class.getName()); - - public static void main(String[] args) { - logger.info("Starting Hibernate Validator Example..."); - - // Create Warmup-based Hibernate Validator - WarmupHibernateValidatorFactory factory = new WarmupHibernateValidatorFactory(); - HibernateValidator validator = factory.usingContext().failFast(false).getValidator(); - - // Example 1: Basic validation - validateUser(validator); - - // Example 2: Group sequences - validateWithGroupSequences(validator); - - // Example 3: Programmatic constraint definition - validateWithProgrammaticConstraints(validator); - - // Example 4: Method validation - validateMethod(validator); - - factory.close(); - logger.info("Hibernate Validator integration example completed successfully!"); - } - - /** - * Example 1: Basic validation with Hibernate Validator features. - */ - private static void validateUser(HibernateValidator validator) { - logger.info("\n=== Example 1: Basic User Validation ==="); - - // Valid user - User validUser = new User("john_doe", "john@example.com", 25); - Set> violations = validator.validate(validUser); - - if (violations.isEmpty()) { - logger.info("User validation passed!"); - } else { - logger.warning("User validation failed:"); - violations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - - // Invalid user - User invalidUser = new User("J", "invalid-email", 5); - Set> invalidViolations = validator.validate(invalidUser); - - logger.warning("Invalid user violations:"); - invalidViolations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - - /** - * Example 2: Validation with group sequences. - */ - private static void validateWithGroupSequences(HibernateValidator validator) { - logger.info("\n=== Example 2: Group Sequences ==="); - - User user = new User("", "test@example.com", 15); - - // Validate with basic group sequence - Set> basicViolations = validator.validate(user, BasicValidation.class); - - logger.info("Basic validation violations:"); - basicViolations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - - // Validate with complete group sequence - Set> completeViolations = validator.validate(user, CompleteValidation.class); - - logger.info("Complete validation violations:"); - completeViolations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - - /** - * Example 3: Programmatic constraint definition. - */ - private static void validateWithProgrammaticConstraints(HibernateValidator validator) { - logger.info("\n=== Example 3: Programmatic Constraints ==="); - - // Create validator with programmatic constraints - var validatorWithConstraints = createValidatorWithConstraints(); - - Product product = new Product("", "P001", -5); - Set> violations = validatorWithConstraints.validate(product); - - if (violations.isEmpty()) { - logger.info("Product validation passed!"); - } else { - logger.warning("Product validation failed:"); - violations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - } - - /** - * Example 4: Method validation. - */ - private static void validateMethod(HibernateValidator validator) { - logger.info("\n=== Example 4: Method Validation ==="); - - ProductService service = new ProductService(); - - try { - // This will validate the method parameters - service.createProduct("Product", "PROD-001", 10); - logger.info("Method validation passed!"); - } catch (Exception e) { - logger.warning("Method validation failed: " + e.getMessage()); - } - - try { - // This should fail validation - service.createProduct("", "", -5); - } catch (Exception e) { - logger.info("Expected validation failure: " + e.getMessage()); - } - } - - /** - * Create validator with programmatic constraint definitions. - */ - private static HibernateValidator createValidatorWithConstraints() { - WarmupHibernateValidatorFactory factory = new WarmupHibernateValidatorFactory(); - - var validatorContext = factory.usingContext(); - - // Add programmatic constraints - var mapping = createProductConstraintMapping(); - validatorContext.addMapping(mapping); - - return validatorContext.getValidator(); - } - - /** - * Create constraint mapping for Product class. - */ - private static ConstraintMapping createProductConstraintMapping() { - ConstraintMapping mapping = new ConstraintMapping(); - - mapping.type(Product.class) - .property("name", org.hibernate.validator.spi.PropertyConstraint.class) - .constraint(new NotNullDef().message("Product name is required")) - .constraint(new SizeDef().min(3).max(100).message("Product name must be 3-100 characters")); - - mapping.type(Product.class) - .property("code", org.hibernate.validator.spi.PropertyConstraint.class) - .constraint(new NotNullDef().message("Product code is required")) - .constraint(new SizeDef().min(3).max(20).message("Product code must be 3-20 characters")); - - mapping.type(Product.class) - .property("price", org.hibernate.validator.spi.PropertyConstraint.class) - .constraint(new NotNullDef().message("Product price is required")) - .constraint(new org.hibernate.validator.cfg.defs.DecimalMinDef() - .value("0") - .message("Price must be greater than or equal to 0")); - - return mapping; - } -} - -/** - * User class with Hibernate Validator group sequences. - */ -class User { - - @NotNull(message = "Username is required", groups = {BasicValidation.class}) - @Size(min = 3, max = 50, message = "Username must be 3-50 characters", groups = {BasicValidation.class}) - private String username; - - @NotNull(message = "Email is required", groups = {BasicValidation.class}) - @Size(min = 5, max = 100, message = "Email must be 5-100 characters", groups = {BasicValidation.class}) - private String email; - - @NotNull(message = "Age is required", groups = {AdvancedValidation.class}) - private Integer age; - - public User(String username, String email, Integer age) { - this.username = username; - this.email = email; - this.age = age; - } - - public String getUsername() { return username; } - public String getEmail() { return email; } - public Integer getAge() { return age; } - - public void setUsername(String username) { this.username = username; } - public void setEmail(String email) { this.email = email; } - public void setAge(Integer age) { this.age = age; } -} - -/** - * Product class for programmatic constraints. - */ -class Product { - private String name; - private String code; - private Double price; - - public Product(String name, String code, Double price) { - this.name = name; - this.code = code; - this.price = price; - } - - public String getName() { return name; } - public String getCode() { return code; } - public Double getPrice() { return price; } - - public void setName(String name) { this.name = name; } - public void setCode(String code) { this.code = code; } - public void setPrice(Double price) { this.price = price; } -} - -/** - * Validation groups for Hibernate Validator sequences. - */ -interface BasicValidation { -} - -interface AdvancedValidation { -} - -@GroupSequence({BasicValidation.class, AdvancedValidation.class, Default.class}) -interface CompleteValidation { -} - -/** - * Sequence provider for complex validation scenarios. - */ -interface ValidationSequenceProvider extends SequenceProvider { -} - -/** - * Product service demonstrating method validation. - */ -class ProductService { - private static final Logger logger = Logger.getLogger(ProductService.class.getName()); - - public void createProduct( - @NotNull(message = "Product name is required") - @Size(min = 3, max = 100, message = "Product name must be 3-100 characters") - String name, - - @NotNull(message = "Product code is required") - @Size(min = 3, max = 20, message = "Product code must be 3-20 characters") - String code, - - @NotNull(message = "Quantity is required") - Integer quantity) { - - logger.info("Creating product: " + name + " (Code: " + code + ", Qty: " + quantity + ")"); - // Business logic for creating product - } - - public Product updateProduct( - Product product, - @NotNull(message = "Updated name is required") - @Size(min = 3, max = 100, message = "Product name must be 3-100 characters") - String newName) { - - logger.info("Updating product: " + product.getName() + " to: " + newName); - product.setName(newName); - return product; - } -} - -/** - * Hibernate Validator service demonstrating advanced features. - */ -class HibernateValidationService { - - private final HibernateValidator validator; - private static final Logger logger = Logger.getLogger(HibernateValidationService.class.getName()); - - public HibernateValidationService() { - WarmupHibernateValidatorFactory factory = new WarmupHibernateValidatorFactory(); - this.validator = factory.usingContext().failFast(false).getValidator(); - } - - public void processUserWithSequences(User user) { - // Validate with complete group sequence - Set> violations = validator.validate(user, CompleteValidation.class); - - if (violations.isEmpty()) { - logger.info("User processing completed successfully!"); - } else { - logger.warning("User processing failed:"); - violations.forEach(violation -> { - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage()); - logger.warning(" Message template: " + violation.getMessageTemplate()); - }); - } - } - - public void validateProductConstraints(Product product) { - var validatorWithConstraints = createProductValidator(); - Set> violations = validatorWithConstraints.validate(product); - - if (violations.isEmpty()) { - logger.info("Product constraints validation passed!"); - } else { - violations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - } - - private HibernateValidator createProductValidator() { - WarmupHibernateValidatorFactory factory = new WarmupHibernateValidatorFactory(); - - var mapping = new ConstraintMapping(); - mapping.type(Product.class) - .property("name", org.hibernate.validator.spi.PropertyConstraint.class) - .constraint(new NotNullDef().message("Name is required")) - .constraint(new SizeDef().min(2).max(100).message("Name size violation")); - - var validatorContext = factory.usingContext(); - validatorContext.addMapping(mapping); - - return validatorContext.getValidator(); - } - - public void validateMethodParameters(String productName, String productCode, Double price) { - Set> violations = - validator.forExecutables(ProductService.class) - .validateParameters( - ProductService.class.getMethod("createProduct", String.class, String.class, Integer.class), - new Object[]{productName, productCode, price != null ? price.intValue() : null} - ); - - if (violations.isEmpty()) { - logger.info("Method parameter validation passed!"); - } else { - violations.forEach(violation -> - logger.warning("- Parameter: " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - } -} diff --git a/warmup-integration/src/main/java/io/warmup/framework/integration/examples/JakartaEEValidationExample.java b/warmup-integration/src/main/java/io/warmup/framework/integration/examples/JakartaEEValidationExample.java deleted file mode 100755 index 191b6ba..0000000 --- a/warmup-integration/src/main/java/io/warmup/framework/integration/examples/JakartaEEValidationExample.java +++ /dev/null @@ -1,262 +0,0 @@ -package io.warmup.framework.integration.examples; - -import io.warmup.framework.integration.jakartaee.WarmupValidatorFactory; -import jakarta.validation.ConstraintViolation; -import jakarta.validation.Validator; -import jakarta.validation.ValidatorFactory; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import jakarta.validation.groups.Default; -import jakarta.validation.metadata.BeanDescriptor; -import jakarta.validation.metadata.ConstraintDescriptor; - -import java.util.Set; -import java.util.logging.Logger; - -/** - * Example demonstrating Warmup Framework integration with Jakarta EE. - * Shows how to use Warmup Framework with standard Jakarta Validation API. - * - * @author MiniMax Agent - * @since 1.0 - */ -public class JakartaEEValidationExample { - - private static final Logger logger = Logger.getLogger(JakartaEEValidationExample.class.getName()); - - public static void main(String[] args) { - logger.info("Starting Jakarta EE Validation Example..."); - - // Create Warmup-based ValidatorFactory - ValidatorFactory factory = new WarmupValidatorFactory(); - Validator validator = factory.getValidator(); - - // Example 1: Basic validation - validateCustomer(validator); - - // Example 2: Property-specific validation - validateProperty(validator); - - // Example 3: Validation with groups - validateWithGroups(validator); - - // Example 4: Bean descriptor inspection - inspectBeanDescriptor(validator); - - factory.close(); - logger.info("Jakarta EE integration example completed successfully!"); - } - - /** - * Example 1: Basic validation of a Customer bean. - */ - private static void validateCustomer(Validator validator) { - logger.info("\n=== Example 1: Basic Validation ==="); - - // Valid customer - Customer validCustomer = new Customer("John Doe", "john@example.com", 25); - Set> violations = validator.validate(validCustomer); - - if (violations.isEmpty()) { - logger.info("Customer validation passed!"); - } else { - logger.warning("Customer validation failed:"); - violations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - - // Invalid customer - Customer invalidCustomer = new Customer("", "invalid-email", -5); - Set> invalidViolations = validator.validate(invalidCustomer); - - logger.warning("Invalid customer violations:"); - invalidViolations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - - /** - * Example 2: Property-specific validation. - */ - private static void validateProperty(Validator validator) { - logger.info("\n=== Example 2: Property-Specific Validation ==="); - - Customer customer = new Customer("Jane Doe", "jane@example.com", 25); - - // Validate only the email property - Set> emailViolations = - validator.validateProperty(customer, "email"); - - if (emailViolations.isEmpty()) { - logger.info("Email validation passed!"); - } else { - logger.warning("Email validation failed:"); - emailViolations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - - // Validate with a bad email - Set> badEmailViolations = - validator.validateProperty(customer, "email", new Object(), "bad-email"); - - badEmailViolations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - - /** - * Example 3: Validation with groups. - */ - private static void validateWithGroups(Validator validator) { - logger.info("\n=== Example 3: Validation with Groups ==="); - - Customer customer = new Customer("", "test@example.com", 15); - - // Validate with default group - Set> defaultViolations = - validator.validate(customer, Default.class); - - logger.info("Default group violations:"); - defaultViolations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - - // Validate with basic info group - Set> basicViolations = - validator.validate(customer, BasicInfo.class); - - logger.info("BasicInfo group violations:"); - basicViolations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - } - - /** - * Example 4: Bean descriptor inspection. - */ - private static void inspectBeanDescriptor(Validator validator) { - logger.info("\n=== Example 4: Bean Descriptor Inspection ==="); - - BeanDescriptor descriptor = validator.getConstraintsForClass(Customer.class); - - logger.info("Bean descriptor for Customer:"); - logger.info("- Has constraints: " + descriptor.hasConstraints()); - logger.info("- Constrained properties: " + descriptor.getConstrainedProperties()); - - // Inspect each constrained property - descriptor.getConstrainedProperties().forEach(propertyName -> { - var propertyDescriptor = descriptor.getConstraintsForProperty(propertyName); - if (propertyDescriptor != null) { - logger.info("Property '" + propertyName + "':"); - logger.info(" - Has constraints: " + propertyDescriptor.hasConstraints()); - logger.info(" - Validation target: " + propertyDescriptor.getValidationTarget()); - - propertyDescriptor.getConstraintDescriptors().forEach(constraintDescriptor -> { - logger.info(" - Constraint: " + constraintDescriptor.getMessageTemplate()); - logger.info(" Groups: " + constraintDescriptor.getGroups()); - logger.info(" Payload: " + constraintDescriptor.getPayload()); - }); - } - }); - } -} - -/** - * Customer bean demonstrating Jakarta EE validation annotations. - * This class uses standard JSR-380 annotations that work with Warmup Framework. - */ -class Customer { - - @NotNull(message = "Name is required", groups = {Default.class, BasicInfo.class}) - @Size(min = 2, max = 100, message = "Name must be 2-100 characters", groups = {Default.class, BasicInfo.class}) - private String name; - - @NotNull(message = "Email is required", groups = {Default.class}) - @Size(min = 5, max = 100, message = "Email must be 5-100 characters", groups = {Default.class}) - private String email; - - @NotNull(message = "Age is required", groups = {Default.class, AdvancedInfo.class}) - private Integer age; - - public Customer(String name, String email, Integer age) { - this.name = name; - this.email = email; - this.age = age; - } - - public String getName() { return name; } - public String getEmail() { return email; } - public Integer getAge() { return age; } - - public void setName(String name) { this.name = name; } - public void setEmail(String email) { this.email = email; } - public void setAge(Integer age) { this.age = age; } -} - -/** - * Validation group for basic information. - */ -interface BasicInfo { -} - -/** - * Validation group for advanced information. - */ -interface AdvancedInfo { -} - -/** - * Jakarta EE service demonstrating validation integration. - * Shows how to use Warmup Framework validator in enterprise applications. - */ -class CustomerService { - - private final Validator validator; - private static final Logger logger = Logger.getLogger(CustomerService.class.getName()); - - public CustomerService() { - ValidatorFactory factory = new WarmupValidatorFactory(); - this.validator = factory.getValidator(); - } - - public void createCustomer(Customer customer) { - // Validate the customer using Jakarta EE API - Set> violations = validator.validate(customer); - - if (violations.isEmpty()) { - logger.info("Creating customer: " + customer.getName()); - // Business logic for creating customer - } else { - logger.warning("Customer validation failed:"); - violations.forEach(violation -> - logger.warning("- " + violation.getPropertyPath() + ": " + violation.getMessage())); - - throw new IllegalArgumentException("Customer validation failed"); - } - } - - public void updateCustomerInfo(String customerId, Customer updatedCustomer) { - // Validate only basic info group when updating basic information - Set> basicViolations = - validator.validate(updatedCustomer, BasicInfo.class); - - if (basicViolations.isEmpty()) { - logger.info("Updating basic info for customer: " + customerId); - // Business logic for updating customer - } else { - throw new IllegalArgumentException("Basic info validation failed"); - } - } - - public void validateAge(Integer age) { - // Validate value without creating object - ValidatorFactory factory = new WarmupValidatorFactory(); - Validator validator = factory.getValidator(); - - Set> violations = - validator.validateValue(Customer.class, "age", age); - - if (violations.isEmpty()) { - logger.info("Age validation passed: " + age); - } else { - violations.forEach(violation -> - logger.warning("Age validation failed: " + violation.getMessage())); - } - } -} diff --git a/warmup-integration/src/main/java/io/warmup/framework/integration/examples/WarmupFrameworkSpringExample.java b/warmup-integration/src/main/java/io/warmup/framework/integration/examples/WarmupFrameworkSpringExample.java deleted file mode 100755 index a6d7900..0000000 --- a/warmup-integration/src/main/java/io/warmup/framework/integration/examples/WarmupFrameworkSpringExample.java +++ /dev/null @@ -1,249 +0,0 @@ -package io.warmup.framework.integration.examples; - -import io.warmup.framework.annotation.validation.*; -import io.warmup.framework.annotation.Bean; -import io.warmup.framework.annotation.Configuration; -import org.springframework.boot.CommandLineRunner; -import org.springframework.boot.SpringApplication; -import org.springframework.boot.autoconfigure.SpringBootApplication; -import org.springframework.validation.annotation.Validated; - -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; -import java.util.logging.Logger; - -/** - * Example Spring Boot application demonstrating Warmup Framework integration. - * Shows how to use Warmup Framework with Spring Boot's validation features. - * - * @author MiniMax Agent - * @since 1.0 - */ -@SpringBootApplication -@Validated -public class WarmupFrameworkSpringExample implements CommandLineRunner { - - private static final Logger logger = Logger.getLogger(WarmupFrameworkSpringExample.class.getName()); - - public static void main(String[] args) { - SpringApplication.run(WarmupFrameworkSpringExample.class, args); - } - - @Override - public void run(String... args) throws Exception { - logger.info("Starting Warmup Framework Spring Boot Example..."); - - // Example 1: Basic validation with Warmup Framework annotations - validateUser(new User("John", "john@email.com", "password123")); - - // Example 2: Invalid user - validateUser(new User("", "invalid-email", "weak")); - - // Example 3: Spring's @Valid annotation - Order order = new Order("ORD-001", 2); - validateOrder(order); - - logger.info("Spring Boot integration example completed successfully!"); - } - - @Bean - public UserValidator userValidator() { - return new UserValidator(); - } - - private void validateUser(User user) { - logger.info("Validating user: " + user.getUsername()); - - try { - // Use Spring's validation bridge - var binding = getSpringValidationBridge().validateWithSpringBinding(user, "user"); - - if (binding.getAllErrors().isEmpty()) { - logger.info("User validation passed!"); - } else { - logger.warning("User validation failed:"); - binding.getAllErrors().forEach(error -> - logger.warning("- " + error.getField() + ": " + error.getDefaultMessage())); - } - } catch (Exception e) { - logger.warning("Validation error: " + e.getMessage()); - } - } - - private void validateOrder(@Valid Order order) { - logger.info("Validating order: " + order.getOrderNumber()); - // Spring's @Valid annotation will trigger validation - logger.info("Order validation completed!"); - } - - // Example method that uses Spring's validation - public void processUserData(@Valid User user) { - // This method will automatically validate the user parameter - logger.info("Processing valid user: " + user.getUsername()); - } - - // Inject the Spring validation bridge - private io.warmup.framework.integration.spring.SpringValidationBridge getSpringValidationBridge() { - // In a real application, this would be injected via @Autowired - return new io.warmup.framework.integration.spring.SpringValidationBridge(); - } -} - -/** - * Example user class using Warmup Framework annotations. - * This demonstrates how to use Warmup Framework's custom validation annotations. - */ -class User { - @NotNull(message = "Username cannot be null") - @Size(min = 3, max = 50, message = "Username must be 3-50 characters") - private String username; - - @NotNull(message = "Email cannot be null") - @Size(min = 5, max = 100, message = "Email must be 5-100 characters") - @Email(message = "Invalid email format") - private String email; - - @NotNull(message = "Password cannot be null") - @Size(min = 8, message = "Password must be at least 8 characters") - @CustomConstraint(validatedBy = PasswordValidator.class) - private String password; - - public User(String username, String email, String password) { - this.username = username; - this.email = email; - this.password = password; - } - - public String getUsername() { return username; } - public String getEmail() { return email; } - public String getPassword() { return password; } - - public void setUsername(String username) { this.username = username; } - public void setEmail(String email) { this.email = email; } - public void setPassword(String password) { this.password = password; } -} - -/** - * Example order class using Jakarta validation annotations. - * This demonstrates compatibility with standard JSR-380 annotations. - */ -class Order { - @NotNull(message = "Order number cannot be null") - @Size(min = 3, max = 20, message = "Order number must be 3-20 characters") - private String orderNumber; - - @NotNull(message = "Quantity cannot be null") - @Min(value = 1, message = "Quantity must be at least 1") - private Integer quantity; - - public Order(String orderNumber, Integer quantity) { - this.orderNumber = orderNumber; - this.quantity = quantity; - } - - public String getOrderNumber() { return orderNumber; } - public Integer getQuantity() { return quantity; } - - public void setOrderNumber(String orderNumber) { this.orderNumber = orderNumber; } - public void setQuantity(Integer quantity) { this.quantity = quantity; } -} - -/** - * Spring configuration with Warmup Framework integration. - */ -@Configuration -class WarmupSpringConfiguration { - - @Bean - public UserService userService(io.warmup.framework.validation.Validator validator) { - return new UserService(validator); - } - - @Bean - public OrderService orderService() { - return new OrderService(); - } -} - -/** - * Example service using Warmup Framework validator. - */ -class UserService { - private final io.warmup.framework.validation.Validator validator; - private static final Logger logger = Logger.getLogger(UserService.class.getName()); - - public UserService(io.warmup.framework.validation.Validator validator) { - this.validator = validator; - } - - public void createUser(User user) { - if (validator.isValid(user)) { - logger.info("Creating user: " + user.getUsername()); - // Create user logic here - } else { - var violations = validator.getViolationReport(user); - violations.getViolations().forEach(violation -> - logger.warning("Validation error: " + violation.getMessage())); - throw new IllegalArgumentException("User validation failed"); - } - } -} - -/** - * Example service using Spring's @Valid annotation. - */ -class OrderService { - private static final Logger logger = Logger.getLogger(OrderService.class.getName()); - - public void createOrder(@Valid Order order) { - logger.info("Creating order: " + order.getOrderNumber() + " with quantity: " + order.getQuantity()); - // Create order logic here - } -} - -/** - * Custom validator for password validation. - * This demonstrates custom constraint validation with Warmup Framework. - */ -class PasswordValidator implements io.warmup.framework.annotation.validation.CustomConstraintValidator { - - @Override - public void initialize(CustomConstraint annotation) { - // Initialize with annotation attributes if needed - } - - @Override - public boolean isValid(String value, CustomConstraint annotation, io.warmup.framework.validation.ValidationContext context) { - if (value == null) { - return true; // null values are handled by @NotNull - } - - // Check minimum length - if (value.length() < 8) { - return false; - } - - // Check for at least one uppercase letter - if (!value.matches(".*[A-Z].*")) { - return false; - } - - // Check for at least one digit - if (!value.matches(".*\\d.*")) { - return false; - } - - // Check for at least one special character - if (!value.matches(".*[!@#$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>\\/?].*")) { - return false; - } - - return true; - } - - @Override - public String getMessage(CustomConstraint annotation, String fieldName, String invalidValue) { - return "Password must be at least 8 characters long and contain at least one uppercase letter, one digit, and one special character"; - } -} diff --git a/warmup-integration/src/main/java/io/warmup/framework/integration/hibernate/WarmupHibernateValidatorFactory.java b/warmup-integration/src/main/java/io/warmup/framework/integration/hibernate/WarmupHibernateValidatorFactory.java deleted file mode 100755 index 12b8acb..0000000 --- a/warmup-integration/src/main/java/io/warmup/framework/integration/hibernate/WarmupHibernateValidatorFactory.java +++ /dev/null @@ -1,348 +0,0 @@ -package io.warmup.framework.integration.hibernate; - -import io.warmup.framework.validation.Validator; -import io.warmup.framework.validation.ViolationReport; -import org.hibernate.validator.HibernateValidator; -import org.hibernate.validator.HibernateValidatorFactory; -import org.hibernate.validator.cfg.ConstraintMapping; -import org.hibernate.validator.cfg.defs.NotNullDef; -import org.hibernate.validator.cfg.defs.SizeDef; -import org.hibernate.validator.internal.engine.ConfigurationImpl; -import org.hibernate.validator.internal.engine ConstraintViolationImpl; -import org.hibernate.validator.internal.engine.path.NodeImpl; - -import jakarta.validation.ConstraintViolation; -import jakarta.validation.MessageInterpolator; -import jakarta.validation.ParameterNameProvider; -import jakarta.validation.TraversableResolver; -import jakarta.validation.ValidatorFactory; -import jakarta.validation.spi.ValidationProvider; - -import java.lang.reflect.Field; -import java.util.Collections; -import java.util.Set; -import java.util.stream.Collectors; - -/** - * Hibernate Validator bridge implementation that allows Hibernate Validator - * to use Warmup Framework for validation logic while maintaining compatibility - * with Hibernate's advanced features. - * - * @author MiniMax Agent - * @since 1.0 - */ -public class WarmupHibernateValidatorFactory implements HibernateValidatorFactory { - - private final Validator warmupValidator; - private final HibernateValidatorFactory hibernateFactory; - - public WarmupHibernateValidatorFactory() { - this.warmupValidator = new io.warmup.framework.validation.DefaultValidator(); - // Create a basic Hibernate Validator Factory for fallback - var configuration = new ConfigurationImpl(); - configuration.messageInterpolator(new WarmupMessageInterpolator()); - configuration.parameterNameProvider(new WarmupParameterNameProvider()); - configuration.traversableResolver(new WarmupTraversableResolver()); - this.hibernateFactory = configuration.buildValidatorFactory(); - } - - public WarmupHibernateValidatorFactory(Validator validator) { - this.warmupValidator = validator; - var configuration = new ConfigurationImpl(); - configuration.messageInterpolator(new WarmupMessageInterpolator()); - configuration.parameterNameProvider(new WarmupParameterNameProvider()); - configuration.traversableResolver(new WarmupTraversableResolver()); - this.hibernateFactory = configuration.buildValidatorFactory(); - } - - @Override - public HibernateValidator usingContext() { - return new WarmupHibernateValidator(warmupValidator, hibernateFactory.usingContext()); - } - - @Override - public ValidatorFactory unwrap(Class type) { - return hibernateFactory.unwrap(type); - } - - @Override - public void close() { - hibernateFactory.close(); - } - - /** - * Hibernate Validator implementation using Warmup Framework. - */ - private static class WarmupHibernateValidator implements HibernateValidator { - - private final Validator warmupValidator; - private final HibernateValidator.ValidatorContext context; - - public WarmupHibernateValidator(Validator warmupValidator, HibernateValidator.ValidatorContext context) { - this.warmupValidator = warmupValidator; - this.context = context; - } - - @Override - public Set> validate(Object object, Class... groups) { - if (object == null) { - return Set.of(); - } - - ViolationReport report = warmupValidator.getViolationReport(object); - - return report.getViolations().stream() - .map(violation -> createHibernateViolation(violation)) - .collect(Collectors.toSet()); - } - - @Override - public Set> validateProperty(Object object, String propertyName, Class... groups) { - if (object == null || propertyName == null) { - return Set.of(); - } - - ViolationReport report = warmupValidator.getViolationReport(object); - - return report.getViolations().stream() - .filter(violation -> violation.getPropertyPath().equals(propertyName)) - .map(violation -> createHibernateViolation(violation)) - .collect(Collectors.toSet()); - } - - @Override - public Set> validateValue(Class beanType, String propertyName, Object value, Class... groups) { - if (beanType == null || propertyName == null) { - return Set.of(); - } - - try { - Object instance = beanType.getDeclaredConstructor().newInstance(); - setProperty(instance, propertyName, value); - return validate(instance, groups); - } catch (Exception e) { - return Set.of(); - } - } - - @Override - public HibernateValidator ignoreXmlConfiguration() { - return new WarmupHibernateValidator(warmupValidator, context.ignoreXmlConfiguration()); - } - - @Override - public HibernateValidator messageInterpolator(MessageInterpolator interpolator) { - return new WarmupHibernateValidator(warmupValidator, context.messageInterpolator(interpolator)); - } - - @Override - public HibernateValidator traversableResolver(TraversableResolver resolver) { - return new WarmupHibernateValidator(warmupValidator, context.traversableResolver(resolver)); - } - - @Override - public HibernateValidator parameterNameProvider(ParameterNameProvider provider) { - return new WarmupHibernateValidator(warmupValidator, context.parameterNameProvider(provider)); - } - - @Override - public HibernateValidator constraintValidatorFactory(org.hibernate.validator.spi.ConstraintValidatorFactory constraintValidatorFactory) { - return new WarmupHibernateValidator(warmupValidator, context.constraintValidatorFactory(constraintValidatorFactory)); - } - - @Override - public HibernateValidator addMapping(ConstraintMapping mapping) { - return new WarmupHibernateValidator(warmupValidator, context.addMapping(mapping)); - } - - @Override - public HibernateValidator failFast(boolean failFast) { - return new WarmupHibernateValidator(warmupValidator, context.failFast(failFast)); - } - - @Override - public HibernateValidator allowOverridingMethodDefaultConstraintMappings(boolean allowOverridingMethodDefaultConstraintMappings) { - return new WarmupHibernateValidator(warmupValidator, - context.allowOverridingMethodDefaultConstraintMappings(allowOverridingMethodDefaultConstraintMappings)); - } - - @Override - public HibernateValidator allowMultipleCascadedValidationOnReturnValues(boolean allowMultipleCascadedValidationOnReturnValues) { - return new WarmupHibernateValidator(warmupValidator, - context.allowMultipleCascadedValidationOnReturnValues(allowMultipleCascadedValidationOnReturnValues)); - } - - @Override - public HibernateValidator allowParallelMethodsDefineCrossParameterConstraints(boolean allowParallelMethodsDefineCrossParameterConstraints) { - return new WarmupHibernateValidator(warmupValidator, - context.allowParallelMethodsDefineCrossParameterConstraints(allowParallelMethodsDefineCrossParameterConstraints)); - } - - @Override - public HibernateValidator constraintValidatorFactory(org.hibernate.validator.spi.ConstraintValidatorFactory constraintValidatorFactory) { - return new WarmupHibernateValidator(warmupValidator, context.constraintValidatorFactory(constraintValidatorFactory)); - } - - private ConstraintViolation createHibernateViolation(io.warmup.framework.validation.ConstraintViolation violation) { - try { - var violationClass = Class.forName("org.hibernate.validator.internal.engine.ConstraintViolationImpl"); - var constructor = violationClass.getDeclaredConstructor( - String.class, String.class, String.class, Object.class, Object.class, - Object.class, Object.class, Class.class, Class.class, - Collections.class, Collections.class, Collections.class, - String.class, String.class, Collections.class - ); - - return (ConstraintViolation) constructor.newInstance( - violation.getMessage(), // messageTemplate - violation.getMessage(), // interpolatedMessage - violation.getRootObject().getClass().getName(), // rootBeanClassName - violation.getRootObject(), // rootBean - violation.getPropertyPath(), // propertyPath - violation.getInvalidValue(), // invalidValue - violation.getRootObject(), // leafBean - violation.getRootObjectType(), // rootBeanClass - violation.getConstraintType(), // constraintClass - Collections.emptyList(), // constraintDescriptor - Collections.emptyList(), // messageParameters - Collections.emptyList(), // messageVariables - violation.getPropertyPath(), // propertyName - violation.getMessage(), // messageTemplate - Collections.emptyList() // dynamicPayload - ); - } catch (Exception e) { - // Fallback to simple violation - return new WarmupHibernateViolation(violation); - } - } - - private void setProperty(Object object, String propertyName, Object value) { - try { - Field field = object.getClass().getDeclaredField(propertyName); - field.setAccessible(true); - field.set(object, value); - } catch (Exception e) { - // Ignore if property can't be set - } - } - } - - /** - * Basic Hibernate ConstraintViolation implementation. - */ - private static class WarmupHibernateViolation implements ConstraintViolation { - - private final io.warmup.framework.validation.ConstraintViolation violation; - - public WarmupHibernateViolation(io.warmup.framework.validation.ConstraintViolation violation) { - this.violation = violation; - } - - @Override - public String getMessage() { - return violation.getMessage(); - } - - @Override - public String getMessageTemplate() { - return violation.getMessage(); - } - - @Override - public Object getRootBean() { - return violation.getRootObject(); - } - - @Override - public Class getRootBeanClass() { - return violation.getRootObjectType(); - } - - @Override - public Object getInvalidValue() { - return violation.getInvalidValue(); - } - - @Override - public String getPropertyPath() { - return violation.getPropertyPath(); - } - - @Override - public Object unwrap(Class type) { - if (type.isInstance(this)) { - return type.cast(this); - } - throw new IllegalArgumentException("Cannot unwrap to type: " + type); - } - } - - /** - * Custom message interpolator that can process messages using Warmup Framework logic. - */ - private static class WarmupMessageInterpolator implements MessageInterpolator { - - @Override - public String interpolate(String messageTemplate, Context context) { - // For now, return the message as-is - // Could be enhanced to process variables in the message - return messageTemplate; - } - - @Override - public String interpolate(String messageTemplate, Context context, java.util.Locale locale) { - return interpolate(messageTemplate, context); - } - } - - /** - * Parameter name provider using Java 8+ parameter reflection. - */ - private static class WarmupParameterNameProvider implements ParameterNameProvider { - - @Override - public java.util.List getParameterNames(java.lang.reflect.Method method) { - if (method.getParameterCount() == 0) { - return java.util.Collections.emptyList(); - } - - return java.util.stream.IntStream.range(0, method.getParameterCount()) - .mapToObj(i -> "arg" + i) - .collect(java.util.stream.Collectors.toList()); - } - - @Override - public java.util.List getParameterNames(java.lang.reflect.Constructor constructor) { - if (constructor.getParameterCount() == 0) { - return java.util.Collections.emptyList(); - } - - return java.util.stream.IntStream.range(0, constructor.getParameterCount()) - .mapToObj(i -> "arg" + i) - .collect(java.util.stream.Collectors.toList()); - } - } - - /** - * Basic traversable resolver that checks if properties are traversable. - */ - private static class WarmupTraversableResolver implements TraversableResolver { - - @Override - public boolean isReachable(Object traversableObject, String traversableProperty, Class rootBeanType, String pathToTraversableObject, jakarta.validation.Path.Node traversablePropertyNode, jakarta.validation.ElementKind traversablePropertyElementKind) { - // Assume all properties are reachable - return true; - } - - @Override - public boolean isCascadable(Object traversableObject, String traversableProperty, Class rootBeanType, String pathToTraversableObject, jakarta.validation.Path.Node traversablePropertyNode, jakarta.validation.ElementKind traversablePropertyElementKind) { - // Assume properties marked with @Valid are cascadable - try { - Field field = rootBeanType.getDeclaredField(traversableProperty); - return field.isAnnotationPresent(jakarta.validation.Valid.class); - } catch (Exception e) { - return false; - } - } - } -} diff --git a/warmup-integration/src/main/java/io/warmup/framework/integration/jakartaee/WarmupValidatorFactory.java b/warmup-integration/src/main/java/io/warmup/framework/integration/jakartaee/WarmupValidatorFactory.java deleted file mode 100755 index 2c525c6..0000000 --- a/warmup-integration/src/main/java/io/warmup/framework/integration/jakartaee/WarmupValidatorFactory.java +++ /dev/null @@ -1,379 +0,0 @@ -package io.warmup.framework.integration.jakartaee; - -import io.warmup.framework.validation.Validator; -import io.warmup.framework.validation.ViolationReport; -import jakarta.validation.ConstraintViolation; -import jakarta.validation.ConstraintViolationException; -import jakarta.validation.Validation; -import jakarta.validation.ValidatorFactory; -import jakarta.validation.metadata.BeanDescriptor; -import jakarta.validation.metadata.ConstraintDescriptor; -import jakarta.validation.spi.ValidationProvider; - -import java.util.Set; - -/** - * Jakarta EE ValidatorFactory implementation that bridges with Warmup Framework. - * Provides compatibility with Jakarta Validation API (JSR-380). - * - * @author MiniMax Agent - * @since 1.0 - */ -public class WarmupValidatorFactory implements ValidatorFactory { - - private final Validator warmupValidator; - - public WarmupValidatorFactory() { - this.warmupValidator = new io.warmup.framework.validation.DefaultValidator(); - } - - public WarmupValidatorFactory(Validator validator) { - this.warmupValidator = validator; - } - - @Override - public jakarta.validation.Validator getValidator() { - return new WarmupJakartaValidator(warmupValidator); - } - - @Override - public void close() { - // Clean up resources if needed - } - - /** - * Jakarta Validator implementation that uses Warmup Framework underneath. - */ - private static class WarmupJakartaValidator implements jakarta.validation.Validator { - - private final Validator warmupValidator; - - public WarmupJakartaValidator(Validator warmupValidator) { - this.warmupValidator = warmupValidator; - } - - @Override - public Set> validate(T object, Class... groups) { - if (object == null) { - return Set.of(); // null objects are considered valid - } - - ViolationReport report = warmupValidator.getViolationReport(object); - - return report.getViolations().stream() - .map(violation -> new WarmupConstraintViolation<>(violation)) - .collect(java.util.stream.Collectors.toSet()); - } - - @Override - public Set> validateProperty(T object, String propertyName, Class... groups) { - if (object == null || propertyName == null) { - return Set.of(); - } - - ViolationReport report = warmupValidator.getViolationReport(object); - - return report.getViolations().stream() - .filter(violation -> violation.getPropertyPath().equals(propertyName)) - .map(violation -> new WarmupConstraintViolation<>(violation)) - .collect(java.util.stream.Collectors.toSet()); - } - - @Override - public Set> validateValue(Class beanType, String propertyName, Object value, Class... groups) { - if (beanType == null || propertyName == null) { - return Set.of(); - } - - try { - T instance = beanType.getDeclaredConstructor().newInstance(); - setProperty(instance, propertyName, value); - return validate(instance, groups); - } catch (Exception e) { - // If we can't create instance, return empty set - return Set.of(); - } - } - - @Override - public BeanDescriptor getConstraintsForClass(Class clazz) { - // Return a basic bean descriptor - could be enhanced to analyze Warmup annotations - return new WarmupBeanDescriptor(clazz); - } - - @Override - public T unwrap(Class type) { - if (type.isInstance(this)) { - return type.cast(this); - } - throw new IllegalArgumentException("Cannot unwrap to type: " + type); - } - - private void setProperty(Object object, String propertyName, Object value) { - try { - var field = object.getClass().getDeclaredField(propertyName); - field.setAccessible(true); - field.set(object, value); - } catch (Exception e) { - // Ignore if property can't be set - } - } - } - - /** - * Jakarta ConstraintViolation implementation using Warmup violation data. - */ - private static class WarmupConstraintViolation implements ConstraintViolation { - - private final io.warmup.framework.validation.ConstraintViolation violation; - - public WarmupConstraintViolation(io.warmup.framework.validation.ConstraintViolation violation) { - this.violation = violation; - } - - @Override - public String getMessage() { - return violation.getMessage(); - } - - @Override - public String getMessageTemplate() { - return violation.getMessage(); - } - - @Override - public T getRootBean() { - return violation.getRootObject(); - } - - @Override - public Class getRootBeanClass() { - return violation.getRootObjectType(); - } - - @Override - public Object getInvalidValue() { - return violation.getInvalidValue(); - } - - @Override - public String getPropertyPath() { - return violation.getPropertyPath(); - } - - @Override - public ConstraintDescriptor getConstraintDescriptor() { - // Return a basic constraint descriptor - return new WarmupConstraintDescriptor(violation); - } - - @Override - public Object[] getExecutableParameters() { - return new Object[0]; // Not applicable for bean validation - } - - @Override - public Object getExecutableReturnValue() { - return null; // Not applicable for bean validation - } - - @Override - public Object unwrap(Class type) { - if (type.isInstance(this)) { - return type.cast(this); - } - throw new IllegalArgumentException("Cannot unwrap to type: " + type); - } - } - - /** - * Basic Jakarta ConstraintDescriptor implementation. - */ - private static class WarmupConstraintDescriptor implements ConstraintDescriptor { - - private final io.warmup.framework.validation.ConstraintViolation violation; - - public WarmupConstraintDescriptor(io.warmup.framework.validation.ConstraintViolation violation) { - this.violation = violation; - } - - @Override - public T getAnnotation() { - return null; // Not available from Warmup violations - } - - @Override - public String getMessageTemplate() { - return violation.getMessage(); - } - - @Override - public Set> getGroups() { - return Set.of(); // Could be enhanced to track groups - } - - @Override - public Set> getPayload() { - return Set.of(); // Could be enhanced to track payloads - } - - @Override - public jakarta.validation.metadata.ConstraintTarget getValidationTarget() { - return jakarta.validation.metadata.ConstraintTarget.PROPERTY; - } - - @Override - public java.util.Map getAttributes() { - return java.util.Map.of(); // Could be enhanced to include annotation attributes - } - - @Override - public Set> getComposingConstraints() { - return Set.of(); // No composing constraints - } - - @Override - public boolean isReportAsSingleViolation() { - return false; - } - } - - /** - * Basic Jakarta BeanDescriptor implementation. - */ - private static class WarmupBeanDescriptor implements jakarta.validation.metadata.BeanDescriptor { - - private final Class beanClass; - - public WarmupBeanDescriptor(Class beanClass) { - this.beanClass = beanClass; - } - - @Override - public boolean hasConstraints() { - // Check if class has any validation annotations - return java.util.Arrays.stream(beanClass.getDeclaredFields()) - .anyMatch(field -> field.isAnnotationPresent(jakarta.validation.constraints.NotNull.class) || - field.isAnnotationPresent(jakarta.validation.constraints.Size.class) || - field.isAnnotationPresent(jakarta.validation.constraints.Pattern.class)); - } - - @Override - public jakarta.validation.metadata.PropertyDescriptor getConstraintsForProperty(String propertyName) { - try { - var field = beanClass.getDeclaredField(propertyName); - return new WarmupPropertyDescriptor(field); - } catch (Exception e) { - return null; - } - } - - @Override - public java.util.Set getConstrainedProperties() { - return java.util.Arrays.stream(beanClass.getDeclaredFields()) - .filter(field -> field.isAnnotationPresent(jakarta.validation.constraints.NotNull.class) || - field.isAnnotationPresent(jakarta.validation.constraints.Size.class) || - field.isAnnotationPresent(jakarta.validation.constraints.Pattern.class)) - .map(java.lang.reflect.Field::getName) - .collect(java.util.stream.Collectors.toSet()); - } - - @Override - public jakarta.validation.metadata.ConstraintDescriptor getConstraintDescriptor() { - return null; // Not applicable for bean descriptor - } - } - - /** - * Basic Jakarta PropertyDescriptor implementation. - */ - private static class WarmupPropertyDescriptor implements jakarta.validation.metadata.PropertyDescriptor { - - private final java.lang.reflect.Field field; - - public WarmupPropertyDescriptor(java.lang.reflect.Field field) { - this.field = field; - } - - @Override - public String getPropertyName() { - return field.getName(); - } - - @Override - public boolean hasConstraints() { - return field.isAnnotationPresent(jakarta.validation.constraints.NotNull.class) || - field.isAnnotationPresent(jakarta.validation.constraints.Size.class) || - field.isAnnotationPresent(jakarta.validation.constraints.Pattern.class); - } - - @Override - public Set> getConstraintDescriptors() { - return java.util.Arrays.stream(field.getAnnotations()) - .filter(annotation -> annotation.annotationType().isAnnotationPresent(jakarta.validation.Constraint.class)) - .map(annotation -> new WarmupConstraintDescriptorAnnotation(annotation)) - .collect(java.util.stream.Collectors.toSet()); - } - - @Override - public jakarta.validation.metadata.ConstraintTarget getValidationTarget() { - return jakarta.validation.metadata.ConstraintTarget.PROPERTY; - } - } - - /** - * Constraint descriptor for actual Jakarta constraint annotations. - */ - private static class WarmupConstraintDescriptorAnnotation implements ConstraintDescriptor { - - private final jakarta.validation.Constraint annotation; - - public WarmupConstraintDescriptorAnnotation(jakarta.validation.Constraint annotation) { - this.annotation = annotation; - } - - @Override - public jakarta.validation.Constraint getAnnotation() { - return annotation; - } - - @Override - public String getMessageTemplate() { - return annotation.message(); - } - - @Override - public Set> getGroups() { - return java.util.Set.of(annotation.groups()); - } - - @Override - public Set> getPayload() { - return java.util.Set.of(annotation.payload()); - } - - @Override - public jakarta.validation.metadata.ConstraintTarget getValidationTarget() { - return jakarta.validation.metadata.ConstraintTarget.PROPERTY; - } - - @Override - public java.util.Map getAttributes() { - java.util.Map attributes = new java.util.HashMap<>(); - attributes.put("message", annotation.message()); - attributes.put("groups", annotation.groups()); - attributes.put("payload", annotation.payload()); - return attributes; - } - - @Override - public Set> getComposingConstraints() { - return java.util.Set.of(); // No composing constraints - } - - @Override - public boolean isReportAsSingleViolation() { - return annotation.message().contains("{") || annotation.message().contains("}"); - } - } -} diff --git a/warmup-integration/src/main/java/io/warmup/framework/integration/spring/SpringValidationBridge.java b/warmup-integration/src/main/java/io/warmup/framework/integration/spring/SpringValidationBridge.java deleted file mode 100755 index a268008..0000000 --- a/warmup-integration/src/main/java/io/warmup/framework/integration/spring/SpringValidationBridge.java +++ /dev/null @@ -1,121 +0,0 @@ -package io.warmup.framework.integration.spring; - -import io.warmup.framework.validation.Validator; -import io.warmup.framework.validation.ViolationReport; -import org.springframework.validation.BeanPropertyBindingResult; -import org.springframework.validation.FieldError; -import org.springframework.validation.ValidatorAdapter; - -import java.util.List; -import java.util.stream.Collectors; - -/** - * Bridge between Spring's validation API and Warmup Framework validation. - * Enables Spring's @Validated annotation to work with Warmup Framework validators. - * - * @author MiniMax Agent - * @since 1.0 - */ -public class SpringValidationBridge { - - private final Validator warmupValidator; - - public SpringValidationBridge() { - this.warmupValidator = new DefaultValidator(); - } - - public SpringValidationBridge(Validator validator) { - this.warmupValidator = validator; - } - - /** - * Validate an object using Warmup Framework and convert results to Spring's BindingResult. - */ - public BeanPropertyBindingResult validateWithSpringBinding(Object object, String objectName) { - BeanPropertyBindingResult bindingResult = new BeanPropertyBindingResult(object, objectName); - - ViolationReport report = warmupValidator.getViolationReport(object); - - // Convert Warmup violations to Spring field errors - for (io.warmup.framework.validation.ConstraintViolation violation : report.getViolations()) { - String fieldName = violation.getPropertyPath(); - String errorMessage = violation.getMessage(); - Object rejectedValue = violation.getInvalidValue(); - - FieldError fieldError = new FieldError( - objectName, - fieldName, - rejectedValue, - false, // bindingFailure - new String[]{errorMessage}, - null, // codes - errorMessage, - null // arguments - ); - - bindingResult.addError(fieldError); - } - - return bindingResult; - } - - /** - * Check if an object is valid according to Warmup Framework rules. - */ - public boolean isValid(Object object) { - if (object == null) { - return true; // null objects are considered valid by Spring - } - - return warmupValidator.isValid(object); - } - - /** - * Get validation messages for display purposes. - */ - public List getValidationMessages(Object object) { - ViolationReport report = warmupValidator.getViolationReport(object); - - return report.getViolations().stream() - .map(violation -> violation.getPropertyPath() + ": " + violation.getMessage()) - .collect(Collectors.toList()); - } - - /** - * Validate and return detailed violation information. - */ - public List getDetailedViolations(Object object) { - ViolationReport report = warmupValidator.getViolationReport(object); - - return report.getViolations().stream() - .map(violation -> new SpringViolation( - violation.getPropertyPath(), - violation.getMessage(), - violation.getInvalidValue(), - violation.getConstraintType() - )) - .collect(Collectors.toList()); - } - - /** - * DTO for Spring-specific violation information. - */ - public static class SpringViolation { - private final String propertyPath; - private final String message; - private final Object invalidValue; - private final Class constraintType; - - public SpringViolation(String propertyPath, String message, Object invalidValue, Class constraintType) { - this.propertyPath = propertyPath; - this.message = message; - this.invalidValue = invalidValue; - this.constraintType = constraintType; - } - - public String getPropertyPath() { return propertyPath; } - public String getMessage() { return message; } - public Object getInvalidValue() { return invalidValue; } - public Class getConstraintType() { return constraintType; } - } -} diff --git a/warmup-integration/src/main/java/io/warmup/framework/integration/spring/WarmupValidationAutoConfiguration.java b/warmup-integration/src/main/java/io/warmup/framework/integration/spring/WarmupValidationAutoConfiguration.java deleted file mode 100755 index d6e1d27..0000000 --- a/warmup-integration/src/main/java/io/warmup/framework/integration/spring/WarmupValidationAutoConfiguration.java +++ /dev/null @@ -1,56 +0,0 @@ -package io.warmup.framework.integration.spring; - -import io.warmup.framework.validation.Validator; -import io.warmup.framework.validation.DefaultValidator; -import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; -import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; -import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Primary; - -import jakarta.validation.ValidatorFactory; - -/** - * Auto-configuration for Warmup Framework integration with Spring Boot. - * Provides automatic setup of validation beans and validators. - * - * @author MiniMax Agent - * @since 1.0 - */ -@Configuration -@ConditionalOnClass(Validator.class) -@ConditionalOnProperty(name = "warmup.validation.enabled", havingValue = "true", matchIfMissing = true) -public class WarmupValidationAutoConfiguration { - - /** - * Primary Validator bean for Spring Boot integration. - * This allows Spring's @Validated annotation and JSR-303 validation - * to work seamlessly with Warmup Framework. - */ - @Bean - @Primary - @ConditionalOnMissingBean - public Validator warmupValidator() { - return new DefaultValidator(); - } - - /** - * Warmup Validator Factory for Jakarta EE compatibility. - * Bridges between Jakarta Validation and Warmup Framework. - */ - @Bean - @ConditionalOnMissingBean - public ValidatorFactory warmupValidatorFactory() { - return new WarmupValidatorFactory(); - } - - /** - * Configuration for Spring's ValidationUtils with Warmup Framework. - */ - @Bean - @ConditionalOnMissingBean - public SpringValidationBridge springValidationBridge() { - return new SpringValidationBridge(); - } -} diff --git a/warmup-integration/src/main/resources/META-INF/spring.factories b/warmup-integration/src/main/resources/META-INF/spring.factories deleted file mode 100755 index ec0b3b2..0000000 --- a/warmup-integration/src/main/resources/META-INF/spring.factories +++ /dev/null @@ -1,3 +0,0 @@ -org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ -io.warmup.framework.integration.spring.WarmupValidationAutoConfiguration,\ -io.warmup.framework.integration.config.WarmupIntegrationConfiguration diff --git a/warmup-test/README.md b/warmup-test/README.md deleted file mode 100644 index a1c4661..0000000 --- a/warmup-test/README.md +++ /dev/null @@ -1,403 +0,0 @@ -# 🎯 Warmup Test Framework - Zero-Config Testing - -## Resumen Ejecutivo - -El **Warmup Test Framework** es un marco de testing zero-config que elimina completamente la necesidad de configuraciones manuales en tests. Con solo agregar `@WarmupTest` a una clase, obtienes: - -- ✅ **Auto-mocking** automático de dependencias -- ✅ **Auto-inyección** de mocks en spies -- ✅ **Zero manual setup** - ningún @BeforeEach requerido -- ✅ **Detección inteligente** de dependencias -- ✅ **Múltiples modos** de testing (UNIT, INTEGRATION, SYSTEM) - -## 🚀 Características Principales - -### 1. Anotación @WarmupTest - Magia Automática - -```java -@WarmupTest -public class MyTest { - // El framework automáticamente: - // 1. Escanea todos los campos @Mock y @Spy - // 2. Crea los mocks y spies - // 3. Inyecta dependencias automáticamente - // 4. Maneja el lifecycle completo -} -``` - -### 2. @Mock vs @Spy - Comportamiento Inteligente - -```java -@WarmupTest -public class ServiceTest { - @Mock - private Repository repo; - // → Mock completo: todos los métodos retornan defaults - // → Perfecto para dependencias externas - - @Spy - private Service service; - // → Spy sobre instancia real: métodos reales a menos que se mockeen - // → Ideal para el sistema bajo test - - @Spy(realImplementation = false) - private Service mockedService; - // → Spy sobre mock: punto medio entre @Mock y @Spy real -} -``` - -### 3. Auto-Inyección de Dependencias - -```java -@WarmupTest -public class OrderServiceTest { - @Spy - private OrderService orderService; // Necesita PaymentService - - @Mock - private PaymentService paymentService; // Auto-inyectado en OrderService - - @Mock - private NotificationService notificationService; // Auto-inyectado también - - // El framework detecta que OrderService tiene dependencias - // y automáticamente inyecta los mocks correspondientes -} -``` - -### 4. Configuraciones Avanzadas - -```java -@WarmupTest( - mode = TestMode.INTEGRATION, // UNIT | INTEGRATION | SYSTEM - autoMock = true, // Auto-mockear dependencias no declaradas - warmupTime = "2s", // Pre-warm antes de tests - verbose = true // Habilitar logging detallado -) -public class AdvancedTest { - @Spy - @InjectMocks // ← Opcional - para claridad - private ComplexService service; - - @Mock - @MockConfig(verbose = true, serializable = true) - private ExternalService external; -} -``` - -## 📋 Casos de Uso Completos - -### Caso 1: Test Unitario Simple - -```java -@ExtendWith(WarmupTestExtension.class) -@WarmupTest -public class UserServiceTest { - @Spy // Sistema bajo test - instancia real - private UserService userService; - - @Mock // Dependencia - mock completo - private UserRepository userRepo; - - @Mock - private EmailService emailService; - - @Test - public void createUser_validUser_createsSuccessfully() { - // Arrange - User user = new User("john@example.com"); - when(userRepo.save(any())).thenReturn(user); - - // Act - User result = userService.createUser(user); - - // Assert - assertThat(result).isEqualTo(user); - verify(emailService).sendWelcomeEmail(user.getEmail()); - } -} -``` - -### Caso 2: Test con Dependencias Complejas - -```java -@ExtendWith(WarmupTestExtension.class) -@WarmupTest -public class OrderProcessingTest { - @Spy - private OrderValidator validator; - - @Spy - private PaymentProcessor paymentProcessor; - - @Spy - private InventoryManager inventoryManager; - - @Spy // ← Servicio principal que usa todos los anteriores - private OrderService orderService; - - @Mock - private ShippingService shippingService; - - @Test - public void processOrder_completeFlow_success() { - // Todos los @Spy tienen instancias reales - // Todos los @Mock tienen mocks completos - // Las dependencias están automáticamente inyectadas - // Solo escribir la lógica del test, nada de setup - } -} -``` - -### Caso 3: Test de Integración Parcial - -```java -@ExtendWith(WarmupTestExtension.class) -@WarmupTest(mode = TestMode.INTEGRATION) -public class PaymentIntegrationTest { - @Spy(useRealDependencies = true) // Usar implementaciones reales cuando sea posible - private PaymentService paymentService; - - @Mock // Pero mockear el gateway externo - private BankGateway bankGateway; - - @RealBean // Forzar bean real (si está en contexto) - private TransactionRepository txRepo; -} -``` - -## ⚙️ Algoritmo de Detección Automática - -### Paso 1: Análisis de Dependencias - -``` -@WarmupTest detecta: -- Campos con @Spy → candidatos a sistema bajo test -- Campos con @Mock → dependencias a mockear -- Analiza constructores y setters para inyección -``` - -### Paso 2: Resolución Automática - -```java -// Ejemplo: El framework detecta que: -@Spy -private UserService userService; // Tiene constructor: UserService(UserRepository, EmailService) - -// Entonces busca en la clase test: -@Mock -private UserRepository userRepository; // ← Match por tipo -@Mock -private EmailService emailService; // ← Match por tipo - -// Y los inyecta automáticamente -``` - -### Paso 3: Lifecycle Management - -```java -@WarmupTest -public class Test { - // Framework ejecuta automáticamente: - // 1. @BeforeWarmup (si existe) - custom setup - // 2. Create all @Mock instances - // 3. Create all @SPY instances with real implementations - // 4. Inject dependencies automatically - // 5. @AfterWarmup (si existe) - post-setup - // 6. Run tests - // 7. Cleanup everything -} -``` - -## 🛠️ Manejo de Errores Inteligente - -### Dependencias Faltantes: - -```java -@WarmupTest -public class ProblematicTest { - @Spy - private UserService userService; // Necesita UserRepository - - // Missing: @Mock private UserRepository repo; - - // ERROR AMIGABLE: - // "Missing dependency for UserService: UserRepository not found in test class. - // Suggested fix: Add '@Mock private UserRepository repo;'" -} -``` - -### Dependencias Circulares: - -```java -@WarmupTest -public class CircularTest { - @Spy - private ServiceA serviceA; // Depende de ServiceB - - @Spy - private ServiceB serviceB; // Depende de ServiceA - - // El framework detecta y resuelve automáticamente - // usando proxys o instanciación lazy -} -``` - -## 🏗️ Arquitectura Técnica - -### Estructura de Clases - -``` -io.warmup.test/ -├── annotation/ # Anotaciones principales -│ ├── WarmupTest.java -│ ├── Mock.java -│ ├── Spy.java -│ ├── InjectMocks.java -│ └── RealBean.java -├── config/ # Configuraciones -│ ├── TestMode.java -│ ├── MockConfig.java -│ └── SpyConfig.java -├── core/ # Lógica principal -│ ├── WarmupTestExtension.java -│ ├── MockRepository.java -│ ├── DependencyAnalyzer.java -│ ├── Injector.java -│ └── AutoConfigurer.java -├── exception/ # Excepciones -│ └── WarmupTestException.java -└── examples/ # Ejemplos de uso - ├── UserServiceTest.java - ├── OrderProcessingTest.java - └── PaymentIntegrationTest.java -``` - -### Flujo de Ejecución - -```mermaid -graph TD - A[@WarmupTest Class] --> B[Analyze Fields] - B --> C[Create Mock Instances] - B --> D[Create Spy Instances] - C --> E[Inject Dependencies] - D --> E - E --> F[Bind to Test Instance] - F --> G[Run Tests] - G --> H[Cleanup] -``` - -## 📊 Beneficios vs Enfoque Tradicional - -| Aspecto | Tradicional | WarmupTest | -|---------|-------------|------------| -| **Configuración manual** | ✅ Required | ❌ Zero | -| **@BeforeEach setup** | ✅ Required | ❌ Eliminado | -| **@InjectMocks** | ✅ Manual | ❌ Auto | -| **Mock injection** | ✅ Manual | ❌ Auto | -| **Dependency tracking** | ❌ No | ✅ Auto | -| **Circular deps** | ❌ Manual resolution | ✅ Auto resolution | -| **Time to write test** | 10-15 min | 2-3 min | - -## 🎯 Ejemplos Prácticos - -### Ejemplo Básico - -```java -@ExtendWith(WarmupTestExtension.class) -@WarmupTest -public class CalculatorTest { - - @Spy - private Calculator calculator; // Sistema bajo test - - @Mock - private Logger logger; // Dependencia externa - - @Test - public void add_twoNumbers_returnsSum() { - // Solo lógica del test, zero setup! - double result = calculator.add(5.0, 3.0); - - assertThat(result).isEqualTo(8.0); - verify(logger).log("Calculating: 5.0 + 3.0"); - } -} -``` - -### Ejemplo con Configuración Avanzada - -```java -@ExtendWith(WarmupTestExtension.class) -@WarmupTest( - mode = TestMode.INTEGRATION, - autoMock = true, - warmupTime = "1s" -) -public class UserServiceIntegrationTest { - - @Spy - @SpyConfig(trackCalls = true) - private UserService userService; - - @Mock - @MockConfig(verbose = true) - private EmailService emailService; - - @RealBean - private UserRepository userRepository; // Bean real del contexto - - @Test - public void createUser_withRealRepo_callsAllServices() { - // Test de integración que usa beans reales donde es posible - User user = userService.createUser("john@example.com"); - - assertThat(user).isNotNull(); - verify(emailService).sendWelcomeEmail("john@example.com"); - // userRepository.save() fue llamado automáticamente - } -} -``` - -## 🚦 Getting Started - -### 1. Agregar Dependencia - -```xml - - io.warmup - warmup-test - 1.0.0 - -``` - -### 2. Usar en Tests - -```java -@ExtendWith(WarmupTestExtension.class) -@WarmupTest -public class MyTest { - @Mock - private MyRepository repository; - - @Spy - private MyService service; // Auto-inyectado con repository - - @Test - public void testSomething() { - // Tu lógica de test aquí - // Todo el setup es automático! - } -} -``` - -## 🎉 Conclusión - -El **Warmup Test Framework** transforma la experiencia de testing eliminando completamente la configuración manual. Con `@WarmupTest`, los desarrolladores pueden: - -- **Escribir tests más rápido** (2-3 min vs 10-15 min) -- **Enfocarse en la lógica** en lugar de la configuración -- **Reducir errores** por configuración incorrecta -- **Mantenimiento simplificado** de tests - -¡La experiencia es tan fluida que los desarrolladores ni siquiera piensan en la configuración! \ No newline at end of file diff --git a/warmup-test/pom.xml b/warmup-test/pom.xml deleted file mode 100644 index 24ae646..0000000 --- a/warmup-test/pom.xml +++ /dev/null @@ -1,80 +0,0 @@ - - - 4.0.0 - - - io.warmup.framework - warmup-framework-parent - 1.0.0-alpha.1 - ../pom.xml - - - warmup-test - Warmup Test Framework - Zero-config testing framework with @WarmupTest annotation - - - 5.17.0 - 5.12.2 - - - - - - io.warmup.framework - warmup-core - 1.0-SNAPSHOT - - - - - org.junit.jupiter - junit-jupiter-api - ${junit.version} - compile - - - - org.junit.jupiter - junit-jupiter-engine - ${junit.version} - test - - - - - org.mockito - mockito-core - ${mockito.version} - compile - - - - - org.reflections - reflections - 0.9.12 - - - - - javax.inject - javax.inject - 1 - compile - - - - - - - org.apache.maven.plugins - maven-compiler-plugin - 3.11.0 - - - - \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/annotation/InjectMocks.java b/warmup-test/src/main/java/io/warmup/test/annotation/InjectMocks.java deleted file mode 100644 index a277925..0000000 --- a/warmup-test/src/main/java/io/warmup/test/annotation/InjectMocks.java +++ /dev/null @@ -1,31 +0,0 @@ -package io.warmup.test.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Anotación para marcar explícitamente que un @Spy es el sistema bajo test - * y debe recibir inyección de dependencias de los @Mock disponibles. - * - * Esta anotación es opcional ya que @Spy ya incluye auto-inyección, pero - * se puede usar para mayor claridad semántica. - * - * Ejemplo: - * ```java - * @WarmupTest - * public class ServiceTest { - * @Spy - * @InjectMocks // ← Opcional para claridad - * private UserService userService; - * - * @Mock - * private UserRepository userRepo; // Auto-inyectado en userService - * } - * ``` - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface InjectMocks { -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/annotation/Mock.java b/warmup-test/src/main/java/io/warmup/test/annotation/Mock.java deleted file mode 100644 index 903765d..0000000 --- a/warmup-test/src/main/java/io/warmup/test/annotation/Mock.java +++ /dev/null @@ -1,53 +0,0 @@ -package io.warmup.test.annotation; - -import io.warmup.test.config.MockConfig; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Anotación para crear mocks automáticamente. - * - * Un @Mock crea un mock completo donde todos los métodos retornan valores por defecto. - * Ideal para dependencias externas y servicios que no son el sistema bajo test. - * - * Ejemplo: - * ```java - * @WarmupTest - * public class UserServiceTest { - * @Mock - * private UserRepository userRepo; // Mock completo - * - * @Spy // Sistema bajo test - * private UserService userService; // Spy con instancias reales - * } - * ``` - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface Mock { - - /** - * Configuración avanzada para el mock. - * - * @return configuración del mock - */ - MockConfig config() default @MockConfig(); - - /** - * Nombre específico para el mock. - * Si no se especifica, se usa el nombre del campo. - * - * @return nombre del mock - */ - String name() default ""; - - /** - * Mockear automáticamente todos los métodos del tipo. - * - * @return true para mockear todos los métodos - */ - boolean stubAllMethods() default true; -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/annotation/RealBean.java b/warmup-test/src/main/java/io/warmup/test/annotation/RealBean.java deleted file mode 100644 index 632546a..0000000 --- a/warmup-test/src/main/java/io/warmup/test/annotation/RealBean.java +++ /dev/null @@ -1,44 +0,0 @@ -package io.warmup.test.annotation; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Anotación para forzar el uso de un bean real en lugar de un mock. - * - * Útil en tests de integración donde queremos usar implementaciones reales - * que están disponibles en el contexto de la aplicación. - * - * Ejemplo: - * ```java - * @WarmupTest(mode = TestMode.INTEGRATION) - * public class PaymentIntegrationTest { - * @Mock - * private BankGateway bankGateway; // Mock el gateway externo - * - * @RealBean // Usar implementación real disponible - * private TransactionRepository txRepo; - * } - * ``` - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface RealBean { - - /** - * Nombre del bean real en el contexto de la aplicación. - * Si no se especifica, se busca por tipo. - * - * @return nombre del bean - */ - String name() default ""; - - /** - * Clase específica del bean si hay múltiples implementaciones. - * - * @return clase del bean - */ - Class type() default Object.class; -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/annotation/Spy.java b/warmup-test/src/main/java/io/warmup/test/annotation/Spy.java deleted file mode 100644 index 5271dfe..0000000 --- a/warmup-test/src/main/java/io/warmup/test/annotation/Spy.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.warmup.test.annotation; - -import io.warmup.test.config.SpyConfig; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Anotación para crear spies automáticamente con inyección de dependencias. - * - * Un @Spy crea un spy sobre una instancia real del objeto, permitiendo: - * - Ejecutar métodos reales por defecto - * - Mockear métodos específicos cuando sea necesario - * - Auto-inyección de dependencias basada en los @Mock disponibles - * - * Ideal para el sistema bajo test (SUT) cuando queremos mantener comportamiento real - * pero poder stubear métodos específicos. - * - * Ejemplo: - * ```java - * @WarmupTest - * public class OrderServiceTest { - * @Spy - * private OrderService orderService; // Spy con inyección automática - * - * @Mock // Auto-inyectado en OrderService - * private PaymentService paymentService; - * - * @Mock // Auto-inyectado en OrderService - * private InventoryManager inventoryManager; - * } - * ``` - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface Spy { - - /** - * Configuración avanzada para el spy. - * - * @return configuración del spy - */ - SpyConfig config() default @SpyConfig(); - - /** - * Clase de implementación real a usar. - * Si no se especifica, se usa el tipo del campo. - * - * @return clase de implementación - */ - Class implementation() default Object.class; - - /** - * Usar implementación real vs mock. - * - * @return true para usar implementación real (spy real) - * false para usar mock (spy sobre mock) - */ - boolean realImplementation() default true; - - /** - * Auto-inyectar dependencias basadas en @Mock disponibles. - * - * @return true para auto-inyección - */ - boolean autoInject() default true; -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/annotation/WarmupTest.java b/warmup-test/src/main/java/io/warmup/test/annotation/WarmupTest.java deleted file mode 100644 index 8b1ce01..0000000 --- a/warmup-test/src/main/java/io/warmup/test/annotation/WarmupTest.java +++ /dev/null @@ -1,57 +0,0 @@ -package io.warmup.test.annotation; - -import io.warmup.test.config.TestMode; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Anotación principal que activa el modo zero-config para toda la clase de test. - * - * Esta anotación elimina completamente la necesidad de: - * - Clases @TestConfiguration - * - Métodos @BeforeEach con setup manual - * - Configuración de mocks con MockitoAnnotations.openMocks() - * - Inyección manual de dependencias - * - * El framework automáticamente: - * 1. Escanea todos los campos @Mock y @Spy - * 2. Crea los mocks y spies - * 3. Inyecta dependencias automáticamente - * 4. Maneja el lifecycle completo - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface WarmupTest { - - /** - * Modo de testing que determina el comportamiento de mocks y spies. - * - * @return modo de test (UNIT, INTEGRATION, SYSTEM) - */ - TestMode mode() default TestMode.UNIT; - - /** - * Auto-mockear dependencias no declaradas en la clase de test. - * - * @return true para auto-mockear dependencias faltantes - */ - boolean autoMock() default true; - - /** - * Tiempo de warm-up antes de ejecutar los tests. - * Formato: "1s", "500ms", "2s500ms" - * - * @return tiempo de warm-up - */ - String warmupTime() default "1s"; - - /** - * Habilitar verbose logging para debugging. - * - * @return true para logging detallado - */ - boolean verbose() default false; -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/config/MockConfig.java b/warmup-test/src/main/java/io/warmup/test/config/MockConfig.java deleted file mode 100644 index ecf86fd..0000000 --- a/warmup-test/src/main/java/io/warmup/test/config/MockConfig.java +++ /dev/null @@ -1,99 +0,0 @@ -package io.warmup.test.config; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Configuración avanzada para anotaciones @Mock. - * - * Permite personalizar el comportamiento de los mocks creados. - */ -public @interface MockConfig { - - /** - * Habilitar logging verbose para este mock específico. - * - * @return true para logging detallado - */ - boolean verbose() default false; - - /** - * Crear mocks con nombres para debugging. - * - * @return true para naming automático - */ - boolean named() default false; - - /** - * Serializar el mock (para casos especiales). - * - * @return true para mock serializable - */ - boolean serializable() default false; - - /** - * Logging level para el mock. - * - * @return nivel de logging - */ - LogLevel logLevel() default LogLevel.NONE; - - /** - * Configuración de stubbing personalizado. - * - * @return configuración de stub - */ - StubConfig stubConfig() default @StubConfig(); -} - -/** - * Niveles de logging disponibles para mocks. - */ -enum LogLevel { - NONE, // Sin logging - BASIC, // Información básica - VERBOSE, // Logging detallado - DEBUG // Debug completo -} - -/** - * Configuración de stubbing para mocks. - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -@interface StubConfig { - - /** - * Stubbing por defecto para métodos void. - * - * @return true para stubbing automático - */ - boolean stubVoidMethods() default true; - - /** - * Retornar valores por defecto para tipos primitivos. - * - * @return true para defaults automáticos - */ - boolean returnDefaultValues() default true; - - /** - * Configuración de argumentos matching. - * - * @return configuración de args - */ - ArgsConfig argsConfig() default @ArgsConfig; -} - -/** - * Configuración de matching de argumentos. - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -@interface ArgsConfig { - boolean strict() default false; - boolean anyString() default true; - boolean anyCollection() default true; -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/config/SpyConfig.java b/warmup-test/src/main/java/io/warmup/test/config/SpyConfig.java deleted file mode 100644 index 0a2dc90..0000000 --- a/warmup-test/src/main/java/io/warmup/test/config/SpyConfig.java +++ /dev/null @@ -1,130 +0,0 @@ -package io.warmup.test.config; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Configuración avanzada para anotaciones @Spy. - * - * Permite personalizar el comportamiento de los spies creados. - */ -public @interface SpyConfig { - - /** - * Usar constructor específico para crear la instancia real. - * - * @return clase del constructor - */ - Class constructor() default Object.class; - - /** - * Argumentos para el constructor si es necesario. - * - * @return argumentos del constructor - */ - String[] constructorArgs() default {}; - - /** - * Configuración de auto-inyección para el spy. - * - * @return configuración de inyección - */ - InjectConfig injectConfig() default @InjectConfig; - - /** - * Comportamiento por defecto del spy. - * - * @return comportamiento por defecto - */ - SpyBehavior behavior() default SpyBehavior.REAL_BY_DEFAULT; - - /** - * Logging level para el spy. - * - * @return nivel de logging - */ - LogLevel logLevel() default LogLevel.NONE; - - /** - * Habilitar tracking de llamadas para este spy. - * - * @return true para tracking - */ - boolean trackCalls() default false; -} - -/** - * Comportamientos disponibles para spies. - */ -enum SpyBehavior { - - /** - * Usar implementación real por defecto, mockear cuando sea necesario. - */ - REAL_BY_DEFAULT, - - /** - * Usar mock por defecto, llamar métodos reales solo cuando se stubee explícitamente. - */ - MOCK_BY_DEFAULT, - - /** - * Always call real methods, never mock. - */ - ALWAYS_REAL, - - /** - * Always mock methods unless explicitly configured otherwise. - */ - ALWAYS_MOCK -} - -/** - * Configuración de inyección para spies. - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -@interface InjectConfig { - - /** - * Permitir auto-inyección basada en tipos compatibles. - * - * @return true para auto-inyección - */ - boolean allowAutoInject() default true; - - /** - * Resolver conflictos de tipos usando nombres de campos. - * - * @return resolución por nombre - */ - boolean resolveByName() default false; - - /** - * Permitir inyección de nulls para dependencias faltantes. - * - * @return true para permitir nulls - */ - boolean allowNullInjection() default false; - - /** - * Configuración de setter injection. - * - * @return configuración de setters - */ - SetterConfig setterConfig() default @SetterConfig; -} - -/** - * Configuración de setter injection. - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -@interface SetterConfig { - boolean useSetters() default true; - boolean useFields() default true; - boolean useConstructors() default true; - boolean strictMatching() default false; -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/config/TestMode.java b/warmup-test/src/main/java/io/warmup/test/config/TestMode.java deleted file mode 100644 index b3737c6..0000000 --- a/warmup-test/src/main/java/io/warmup/test/config/TestMode.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.warmup.test.config; - -/** - * Modos de testing que determinan el comportamiento de mocks y spies. - * - * Cada modo define qué tipo de instancias crear y cómo inyectar dependencias: - */ -public enum TestMode { - - /** - * Modo unit test: Máximo uso de mocks. - * - @Mock: Mocks completos - * - @Spy: Spies sobre instancias reales con mocks inyectados - * - Dependencias externas siempre mockeadas - * - Ideal para tests unitarios puros - */ - UNIT, - - /** - * Modo integration test: Mix de real y mock. - * - @Mock: Mocks para dependencias externas - * - @Spy: Spies que usan implementaciones reales cuando es posible - * - @RealBean: Usa beans reales del contexto de la aplicación - * - Ideal para tests de integración parcial - */ - INTEGRATION, - - /** - * Modo system test: Máximo uso de implementaciones reales. - * - @Mock: Solo para dependencias no disponibles - * - @Spy: Spies sobre implementaciones reales - * - Intenta usar todas las implementaciones reales posibles - * - Ideal para tests end-to-end - */ - SYSTEM -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/core/AutoConfigurer.java b/warmup-test/src/main/java/io/warmup/test/core/AutoConfigurer.java deleted file mode 100644 index a0ada76..0000000 --- a/warmup-test/src/main/java/io/warmup/test/core/AutoConfigurer.java +++ /dev/null @@ -1,261 +0,0 @@ -package io.warmup.test.core; - -import io.warmup.test.annotation.*; -import io.warmup.test.exception.WarmupTestException; - -import java.lang.reflect.Field; -import java.util.*; - -/** - * Configurador automático que aplica configuraciones específicas basadas - * en las anotaciones de los campos de test. - */ -class AutoConfigurer { - - /** - * Aplicar configuración automática basada en las anotaciones. - */ - public void configure(Object testInstance, TestClassMetadata metadata) { - // Configurar cada tipo de campo según sus anotaciones - for (MockField mockField : metadata.getMockFields()) { - configureMock(testInstance, mockField); - } - - for (SpyField spyField : metadata.getSpyFields()) { - configureSpy(testInstance, spyField); - } - - for (RealBeanField realBeanField : metadata.getRealBeanFields()) { - configureRealBean(testInstance, realBeanField); - } - } - - private void configureMock(Object testInstance, MockField mockField) { - Mock mockAnnotation = mockField.getAnnotation(); - - if (mockAnnotation.config().verbose()) { - enableVerboseMocking(mockField.getField().getType()); - } - - // Aplicar configuración específica del mock si es necesario - applyMockSpecificConfiguration(mockField, mockAnnotation.config()); - } - - private void configureSpy(Object testInstance, SpyField spyField) { - Spy spyAnnotation = spyField.getAnnotation(); - - // Configurar comportamiento específico del spy - applySpySpecificConfiguration(spyField, spyAnnotation.config()); - - // Si tiene @InjectMocks explícito, asegurar inyección de dependencias - try { - Field field = spyField.getField(); - field.setAccessible(true); - Object spyInstance = field.get(testInstance); - - // Agregar listener para tracking de llamadas si está configurado - if (spyAnnotation.config().trackCalls()) { - addCallTracking(spyInstance, spyAnnotation.config()); - } - } catch (Exception e) { - throw new WarmupTestException("Error configuring spy: " + spyField.getField().getName(), e); - } - } - - private void configureRealBean(Object testInstance, RealBeanField realBeanField) { - // Configurar bean real si es necesario - // En un caso real, aquí buscaríamos en el contexto de la aplicación - } - - private void enableVerboseMocking(Class type) { - // Habilitar logging verbose para el tipo específico - System.setProperty("mockito.verbose." + type.getName(), "true"); - } - - private void applyMockSpecificConfiguration(MockField mockField, MockConfig config) { - // Aplicar configuraciones específicas basadas en MockConfig - // Ejemplo: configurar serialización, naming, etc. - - if (config.serializable()) { - // Configurar mock como serializable - // Mockito.mock(type, withSettings().serializable()) - } - } - - private void applySpySpecificConfiguration(SpyField spyField, SpyConfig config) { - // Aplicar configuraciones específicas basadas en SpyConfig - // Ejemplo: configurar constructor específico, logging, etc. - - if (config.logLevel() != null && config.logLevel() != io.warmup.test.config.LogLevel.NONE) { - // Configurar logging para el spy - enableSpyLogging(spyField.getField().getType(), config.logLevel()); - } - } - - private void enableSpyLogging(Class type, io.warmup.test.config.LogLevel logLevel) { - // Habilitar logging para el spy según el nivel especificado - System.setProperty("spy.logging." + type.getName(), logLevel.name()); - } - - private void addCallTracking(Object spyInstance, SpyConfig config) { - // Agregar tracking de llamadas para el spy - // Esto podría usar listeners de Mockito o proxies personalizados - - if (config.trackCalls()) { - // Implementar tracking de llamadas - // Ejemplo: registrar cada llamada para verificación posterior - } - } -} - -/** - * Detector de problemas comunes en configuraciones de test. - */ -class ProblemDetector { - - /** - * Detectar problemas comunes en la configuración del test. - */ - public List detectProblems(TestClassMetadata metadata) { - List problems = new ArrayList<>(); - - // Verificar dependencias faltantes - detectMissingDependencies(metadata, problems); - - // Verificar dependencias circulares - detectCircularDependencies(metadata, problems); - - // Verificar tipos incompatibles - detectIncompatibleTypes(metadata, problems); - - // Verificar configuración incorrecta - detectMisconfiguration(metadata, problems); - - return problems; - } - - private void detectMissingDependencies(TestClassMetadata metadata, List problems) { - for (SpyField spyField : metadata.getSpyFields()) { - Class spyType = spyField.getField().getType(); - - // Simular análisis de constructor y setters - Set> requiredTypes = getRequiredTypes(spyType); - - for (Class requiredType : requiredTypes) { - boolean hasCompatibleMock = metadata.getMockFields().stream() - .anyMatch(mockField -> isCompatible(requiredType, mockField.getField().getType())); - - if (!hasCompatibleMock) { - problems.add(String.format( - "Missing dependency for %s: %s not found in test class. " + - "Suggested fix: Add '@Mock %s %s;' or set autoMock=true in @WarmupTest", - spyType.getSimpleName(), - requiredType.getSimpleName(), - requiredType.getSimpleName(), - toCamelCase(requiredType.getSimpleName()) - )); - } - } - } - } - - private void detectCircularDependencies(TestClassMetadata metadata, List problems) { - // Implementación simplificada - detectar dependencias circulares obvias - for (SpyField spyField : metadata.getSpyFields()) { - Class spyType = spyField.getField().getType(); - - for (MockField mockField : metadata.getMockFields()) { - Class mockType = mockField.getField().getType(); - - if (spyType.equals(mockType) || spyType.isAssignableFrom(mockType)) { - problems.add(String.format( - "Potential circular dependency between %s and %s. " + - "Consider using @RealBean for one of them.", - spyType.getSimpleName(), - mockType.getSimpleName() - )); - } - } - } - } - - private void detectIncompatibleTypes(TestClassMetadata metadata, List problems) { - // Verificar tipos incompatibles en las anotaciones - for (MockField mockField : metadata.getMockFields()) { - Class mockType = mockField.getField().getType(); - - if (mockType.isPrimitive()) { - problems.add(String.format( - "Cannot create @Mock for primitive type %s. Consider using wrapper class.", - mockType.getSimpleName() - )); - } - } - } - - private void detectMisconfiguration(TestClassMetadata metadata, List problems) { - // Verificar configuraciones incorrectas - for (SpyField spyField : metadata.getSpyFields()) { - Spy spyAnnotation = spyField.getAnnotation(); - - if (spyAnnotation.realImplementation() && spyAnnotation.implementation() != Object.class) { - // Verificar que la implementación especificada sea compatible - Class spyType = spyField.getField().getType(); - Class implType = spyAnnotation.implementation(); - - if (!spyType.isAssignableFrom(implType)) { - problems.add(String.format( - "Implementation %s is not compatible with spy type %s", - implType.getSimpleName(), - spyType.getSimpleName() - )); - } - } - } - } - - private Set> getRequiredTypes(Class spyType) { - Set> requiredTypes = new HashSet<>(); - - try { - // Analizar constructor principal - Arrays.stream(spyType.getDeclaredConstructors()) - .max(Comparator.comparingInt(Constructor::getParameterCount)) - .ifPresent(ctor -> { - for (Class paramType : ctor.getParameterTypes()) { - requiredTypes.add(paramType); - } - }); - - // Analizar setters - for (Method method : spyType.getDeclaredMethods()) { - if (isSetterMethod(method)) { - requiredTypes.add(method.getParameterTypes()[0]); - } - } - - } catch (Exception e) { - // Si no podemos analizar, asumir que no hay requisitos específicos - } - - return requiredTypes; - } - - private boolean isCompatible(Class required, Class available) { - return required.isAssignableFrom(available) || available.isAssignableFrom(required); - } - - private String toCamelCase(String className) { - if (className == null || className.isEmpty()) { - return ""; - } - - return Character.toLowerCase(className.charAt(0)) + className.substring(1); - } - - private boolean isSetterMethod(Method method) { - return method.getName().startsWith("set") - && method.getParameterCount() == 1 - && method.getReturnType() == void.class; - } -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/core/DependencyAnalyzer.java b/warmup-test/src/main/java/io/warmup/test/core/DependencyAnalyzer.java deleted file mode 100644 index 80cf8d5..0000000 --- a/warmup-test/src/main/java/io/warmup/test/core/DependencyAnalyzer.java +++ /dev/null @@ -1,200 +0,0 @@ -package io.warmup.test.core; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.util.*; - -/** - * Analizador de dependencias que detecta automáticamente las relaciones - * entre mocks, spies y dependencias en los campos de una clase de test. - */ -class DependencyAnalyzer { - - private final Map, Set>> dependencyGraph = new HashMap<>(); - - /** - * Analizar las dependencias entre los campos de una clase de test. - */ - public void analyzeDependencies(TestClassMetadata metadata) { - for (SpyField spyField : metadata.getSpyFields()) { - analyzeSpyDependencies(spyField, metadata); - } - - // Detectar dependencias circulares y resolverlas - detectCircularDependencies(metadata); - } - - private void analyzeSpyDependencies(SpyField spyField, TestClassMetadata metadata) { - Class spyType = spyField.getField().getType(); - Set> dependencies = new HashSet<>(); - - // Analizar constructor del spy - dependencies.addAll(analyzeConstructorDependencies(spyType)); - - // Analizar setters del spy - dependencies.addAll(analyzeSetterDependencies(spyType)); - - // Analizar campos del spy - dependencies.addAll(analyzeFieldDependencies(spyType)); - - dependencyGraph.put(spyType, dependencies); - } - - private Set> analyzeConstructorDependencies(Class type) { - Set> dependencies = new HashSet<>(); - - try { - Constructor[] constructors = type.getDeclaredConstructors(); - - // Preferir constructor con más parámetros (más específico) - Constructor preferredConstructor = Arrays.stream(constructors) - .max(Comparator.comparingInt(Constructor::getParameterCount)) - .orElse(null); - - if (preferredConstructor != null) { - for (Class paramType : preferredConstructor.getParameterTypes()) { - dependencies.add(paramType); - } - } - } catch (Exception e) { - // Constructor no accesible, ignorar - } - - return dependencies; - } - - private Set> analyzeSetterDependencies(Class type) { - Set> dependencies = new HashSet<>(); - - for (Method method : type.getDeclaredMethods()) { - if (isSetterMethod(method)) { - Class paramType = method.getParameterTypes()[0]; - dependencies.add(paramType); - } - } - - return dependencies; - } - - private Set> analyzeFieldDependencies(Class type) { - Set> dependencies = new HashSet<>(); - - for (Field field : type.getDeclaredFields()) { - dependencies.add(field.getType()); - } - - return dependencies; - } - - private boolean isSetterMethod(Method method) { - return method.getName().startsWith("set") - && method.getParameterCount() == 1 - && method.getReturnType() == void.class; - } - - private void detectCircularDependencies(TestClassMetadata metadata) { - Map, List>> dependencyMap = buildDependencyMap(metadata); - - Set> cyclicClasses = findCyclicDependencies(dependencyMap); - - if (!cyclicClasses.isEmpty()) { - // Resolver dependencias circulares automáticamente - resolveCircularDependencies(cyclicClasses, dependencyMap); - } - } - - private Map, List>> buildDependencyMap(TestClassMetadata metadata) { - Map, List>> dependencyMap = new HashMap<>(); - - for (SpyField spyField : metadata.getSpyFields()) { - Class spyType = spyField.getField().getType(); - List> dependencies = new ArrayList<>(); - - // Buscar mocks compatibles - for (MockField mockField : metadata.getMockFields()) { - Class mockType = mockField.getField().getType(); - if (isCompatible(mockType, spyType)) { - dependencies.add(mockType); - } - } - - dependencyMap.put(spyType, dependencies); - } - - return dependencyMap; - } - - private Set> findCyclicDependencies(Map, List>> dependencyMap) { - Set> visited = new HashSet<>(); - Set> recStack = new HashSet<>(); - Set> cyclicClasses = new HashSet<>(); - - for (Class className : dependencyMap.keySet()) { - if (!visited.contains(className)) { - findCyclesDFS(className, dependencyMap, visited, recStack, cyclicClasses); - } - } - - return cyclicClasses; - } - - private void findCyclesDFS(Class node, Map, List>> dependencyMap, - Set> visited, Set> recStack, - Set> cyclicClasses) { - - if (recStack.contains(node)) { - cyclicClasses.add(node); - return; - } - - if (visited.contains(node)) { - return; - } - - visited.add(node); - recStack.add(node); - - List> dependencies = dependencyMap.getOrDefault(node, Collections.emptyList()); - for (Class dependency : dependencies) { - if (dependencyMap.containsKey(dependency)) { - findCyclesDFS(dependency, dependencyMap, visited, recStack, cyclicClasses); - } - } - - recStack.remove(node); - } - - private void resolveCircularDependencies(Set> cyclicClasses, - Map, List>> dependencyMap) { - - for (Class cyclicClass : cyclicClasses) { - List> dependencies = dependencyMap.get(cyclicClass); - if (dependencies != null && dependencies.size() > 1) { - // Mantener solo la primera dependencia para romper el ciclo - List> resolvedDependencies = dependencies.subList(0, 1); - dependencyMap.put(cyclicClass, resolvedDependencies); - } - } - } - - private boolean isCompatible(Class mockType, Class spyType) { - // Verificar compatibilidad de tipos - return spyType.isAssignableFrom(mockType) || mockType.isAssignableFrom(spyType); - } - - /** - * Obtener las dependencias de una clase específica. - */ - public Set> getDependencies(Class type) { - return dependencyGraph.getOrDefault(type, Collections.emptySet()); - } - - /** - * Verificar si una clase tiene dependencias circulares. - */ - public boolean hasCircularDependencies(Class type) { - // Implementación simplificada - Set> dependencies = getDependencies(type); - return dependencies.stream().anyMatch(dep -> dep.equals(type)); - } -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/core/Injector.java b/warmup-test/src/main/java/io/warmup/test/core/Injector.java deleted file mode 100644 index 448464d..0000000 --- a/warmup-test/src/main/java/io/warmup/test/core/Injector.java +++ /dev/null @@ -1,154 +0,0 @@ -package io.warmup.test.core; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Map; - -/** - * Inyector de dependencias que maneja la inyección automática de mocks - * en spies basándose en análisis de tipos y constructores. - */ -class Injector { - - /** - * Inyectar dependencias en un objeto basándose en un mapa de objetos compatibles. - */ - public void injectDependencies(Object target, Map, Object> dependencies) { - if (target == null || dependencies == null || dependencies.isEmpty()) { - return; - } - - // Intentar inyección por constructor primero - injectViaConstructor(target, dependencies); - - // Luego inyección por setters - injectViaSetters(target, dependencies); - - // Finalmente inyección directa por campos - injectViaFields(target, dependencies); - } - - private void injectViaConstructor(Object target, Map, Object> dependencies) { - Class targetType = target.getClass(); - - try { - Constructor[] constructors = targetType.getDeclaredConstructors(); - - // Buscar constructor con parámetros compatibles - Constructor suitableConstructor = findSuitableConstructor(constructors, dependencies); - - if (suitableConstructor != null) { - Object[] args = buildConstructorArguments(suitableConstructor, dependencies); - suitableConstructor.setAccessible(true); - suitableConstructor.newInstance(args); - } - } catch (Exception e) { - // Constructor injection falló, continuar con otros métodos - } - } - - private Constructor findSuitableConstructor(Constructor[] constructors, - Map, Object> dependencies) { - - return Arrays.stream(constructors) - .filter(ctor -> { - Class[] paramTypes = ctor.getParameterTypes(); - - // Verificar si todos los parámetros tienen dependencias compatibles - return Arrays.stream(paramTypes) - .allMatch(paramType -> hasCompatibleDependency(paramType, dependencies)); - }) - .max((a, b) -> Integer.compare(a.getParameterCount(), b.getParameterCount())) - .orElse(null); - } - - private Object[] buildConstructorArguments(Constructor constructor, - Map, Object> dependencies) { - - Class[] paramTypes = constructor.getParameterTypes(); - Object[] args = new Object[paramTypes.length]; - - for (int i = 0; i < paramTypes.length; i++) { - args[i] = findCompatibleInstance(paramTypes[i], dependencies); - } - - return args; - } - - private void injectViaSetters(Object target, Map, Object> dependencies) { - Class targetType = target.getClass(); - - for (Method method : targetType.getDeclaredMethods()) { - if (isSetterMethod(method)) { - Class paramType = method.getParameterTypes()[0]; - Object dependency = findCompatibleInstance(paramType, dependencies); - - if (dependency != null) { - try { - method.setAccessible(true); - method.invoke(target, dependency); - } catch (Exception e) { - // Setter injection falló, continuar - } - } - } - } - } - - private void injectViaFields(Object target, Map, Object> dependencies) { - Class targetType = target.getClass(); - - for (Field field : targetType.getDeclaredFields()) { - if (shouldInjectField(field)) { - Object dependency = findCompatibleInstance(field.getType(), dependencies); - - if (dependency != null) { - try { - field.setAccessible(true); - field.set(target, dependency); - } catch (Exception e) { - // Field injection falló, continuar - } - } - } - } - } - - private boolean hasCompatibleDependency(Class paramType, Map, Object> dependencies) { - return dependencies.keySet().stream() - .anyMatch(depType -> isCompatibleType(paramType, depType)); - } - - private Object findCompatibleInstance(Class requiredType, Map, Object> dependencies) { - // Buscar dependencia exacta primero - if (dependencies.containsKey(requiredType)) { - return dependencies.get(requiredType); - } - - // Buscar tipo compatible - return dependencies.entrySet().stream() - .filter(entry -> isCompatibleType(requiredType, entry.getKey())) - .map(Map.Entry::getValue) - .findFirst() - .orElse(null); - } - - private boolean isCompatibleType(Class required, Class available) { - // Verificar si los tipos son compatibles - return required.isAssignableFrom(available) || available.isAssignableFrom(required); - } - - private boolean isSetterMethod(Method method) { - return method.getName().startsWith("set") - && method.getParameterCount() == 1 - && method.getReturnType() == void.class - && !method.getName().equals("set"); - } - - private boolean shouldInjectField(Field field) { - // Inyectar todos los campos excepto static y final - return !java.lang.reflect.Modifier.isStatic(field.getModifiers()) - && !java.lang.reflect.Modifier.isFinal(field.getModifiers()); - } -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/core/MockRepository.java b/warmup-test/src/main/java/io/warmup/test/core/MockRepository.java deleted file mode 100644 index cee4175..0000000 --- a/warmup-test/src/main/java/io/warmup/test/core/MockRepository.java +++ /dev/null @@ -1,87 +0,0 @@ -package io.warmup.test.core; - -import org.mockito.Mockito; - -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Repositorio centralizado para manejar todos los mocks y spies creados. - * Proporciona funcionalidades para limpiar y resetear mocks automáticamente. - */ -class MockRepository { - - private final Map mocks = new ConcurrentHashMap<>(); - private final Map spies = new ConcurrentHashMap<>(); - private final Map realBeans = new ConcurrentHashMap<>(); - - /** - * Registrar un mock con nombre único. - */ - public void registerMock(String name, Object mock) { - mocks.put(name, mock); - } - - /** - * Registrar un spy con nombre único. - */ - public void registerSpy(String name, Object spy) { - spies.put(name, spy); - } - - /** - * Registrar un bean real con nombre único. - */ - public void registerRealBean(String name, Object bean) { - realBeans.put(name, bean); - } - - /** - * Obtener un mock por nombre. - */ - public Object getMock(String name) { - return mocks.get(name); - } - - /** - * Obtener un spy por nombre. - */ - public Object getSpy(String name) { - return spies.get(name); - } - - /** - * Obtener un bean real por nombre. - */ - public Object getRealBean(String name) { - return realBeans.get(name); - } - - /** - * Resetear todos los mocks y spies. - */ - public void resetAll() { - mocks.values().forEach(this::resetObject); - spies.values().forEach(this::resetObject); - } - - /** - * Limpiar completamente el repositorio. - */ - public void clearAll() { - mocks.clear(); - spies.clear(); - realBeans.clear(); - } - - private void resetObject(Object obj) { - try { - if (obj != null) { - Mockito.reset(obj); - } - } catch (Exception e) { - // Log warning but don't fail the test - System.err.println("Warning: Could not reset mock/spy: " + e.getMessage()); - } - } -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/core/WarmupTestExtension.java b/warmup-test/src/main/java/io/warmup/test/core/WarmupTestExtension.java deleted file mode 100644 index ee68275..0000000 --- a/warmup-test/src/main/java/io/warmup/test/core/WarmupTestExtension.java +++ /dev/null @@ -1,388 +0,0 @@ -package io.warmup.test.core; - -import io.warmup.test.annotation.*; -import io.warmup.test.config.TestMode; -import io.warmup.test.exception.WarmupTestException; -import org.junit.jupiter.api.extension.*; -import org.mockito.*; -import org.mockito.internal.configuration.ClassInfo; -import org.mockito.internal.configuration.DefaultInjectionEngine; -import org.mockito.internal.configuration.GlobalConfiguration; -import org.mockito.internal.creation.instance.ObjectInstantiator; -import org.mockito.internal.creation.instance.MockitoInstantiator; -import org.mockito.internal.progress.MockingProgress; -import org.mockito.internal.progress.ThreadSafeMockingProgress; -import org.mockito.internal.stubbing.answers.CallsRealMethods; -import org.mockito.internal.util.reflection.FieldInitializationReport; -import org.mockito.internal.util.reflection.FieldInitializer; -import org.mockito.internal.util.reflection.GenericMaster; -import org.mockito.internal.util.reflection.LenientCopyTool; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.listeners.VerificationStartedListener; -import org.mockito.stubbing.Answer; -import org.mockito.stubbing.Stubber; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -/** - * Extension JUnit 5 que implementa el comportamiento zero-config del framework. - * - * Esta clase detecta automáticamente: - * - Clases con @WarmupTest - * - Campos con @Mock y @Spy - * - Dependencias entre objetos - * - Inyección automática de mocks en spies - */ -public class WarmupTestExtension implements BeforeAllCallback, BeforeEachCallback, AfterEachCallback, AfterAllCallback { - - private static final ThreadLocal currentContext = new ThreadLocal<>(); - private static final Map, TestClassMetadata> classMetadataCache = new ConcurrentHashMap<>(); - - @Override - public void beforeAll(ExtensionContext context) throws Exception { - Class testClass = context.getRequiredTestClass(); - WarmupTest warmupTest = testClass.getAnnotation(WarmupTest.class); - - if (warmupTest == null) { - return; // No es una clase de test con @WarmupTest - } - - WarmupTestContext testContext = new WarmupTestContext(testClass, warmupTest); - testContext.initialize(); - - currentContext.set(testContext); - - // Ejecutar warm-up si está configurado - if (!"0s".equals(warmupTest.warmupTime()) && !"0ms".equals(warmupTest.warmupTime())) { - performWarmup(warmupTest.warmupTime()); - } - } - - @Override - public void beforeEach(ExtensionContext context) throws Exception { - WarmupTestContext testContext = currentContext.get(); - if (testContext != null) { - testContext.setupTestInstance(context.getRequiredTestInstance()); - } - } - - @Override - public void afterEach(ExtensionContext context) throws Exception { - // Cleanup del test actual - WarmupTestContext testContext = currentContext.get(); - if (testContext != null) { - testContext.cleanup(); - } - } - - @Override - public void afterAll(ExtensionContext context) throws Exception { - // Limpiar completamente - currentContext.remove(); - } - - private void performWarmup(String warmupTime) { - try { - long millis = parseTime(warmupTime); - Thread.sleep(millis); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - private long parseTime(String timeStr) { - timeStr = timeStr.toLowerCase().trim(); - - if (timeStr.endsWith("ms")) { - return Long.parseLong(timeStr.substring(0, timeStr.length() - 2)); - } else if (timeStr.endsWith("s")) { - return Long.parseLong(timeStr.substring(0, timeStr.length() - 1)) * 1000; - } else { - return Long.parseLong(timeStr); - } - } - - /** - * Contexto interno que mantiene el estado de cada clase de test. - */ - private static class WarmupTestContext { - private final Class testClass; - private final WarmupTest warmupTest; - private final MockRepository mockRepository = new MockRepository(); - private final DependencyAnalyzer dependencyAnalyzer = new DependencyAnalyzer(); - private final Injector injector = new Injector(); - private final Map fieldInstances = new ConcurrentHashMap<>(); - - public WarmupTestContext(Class testClass, WarmupTest warmupTest) { - this.testClass = testClass; - this.warmupTest = warmupTest; - } - - public void initialize() throws Exception { - // Configurar Mockito - setupMockito(); - - // Analizar metadata de la clase de test - TestClassMetadata metadata = analyzeTestClass(); - - // Crear instancias según los modos - createInstances(metadata); - - // Realizar inyección de dependencias - performDependencyInjection(metadata); - } - - public void setupTestInstance(Object testInstance) { - // Mapear instancias a los campos del test - bindInstancesToTest(testInstance); - } - - public void cleanup() { - mockRepository.clearAll(); - fieldInstances.clear(); - } - - private void setupMockito() { - // Configuración global de Mockito - Mockito.reset(); - } - - private TestClassMetadata analyzeTestClass() { - return classMetadataCache.computeIfAbsent(testClass, cls -> { - TestClassMetadata metadata = new TestClassMetadata(); - - for (Field field : cls.getDeclaredFields()) { - Mock mockAnnotation = field.getAnnotation(Mock.class); - Spy spyAnnotation = field.getAnnotation(Spy.class); - RealBean realBeanAnnotation = field.getAnnotation(RealBean.class); - - if (mockAnnotation != null) { - metadata.addMockField(field, mockAnnotation); - } else if (spyAnnotation != null) { - metadata.addSpyField(field, spyAnnotation); - } else if (realBeanAnnotation != null) { - metadata.addRealBeanField(field, realBeanAnnotation); - } - } - - // Analizar dependencias entre mocks y spies - dependencyAnalyzer.analyzeDependencies(metadata); - - return metadata; - }); - } - - private void createInstances(TestClassMetadata metadata) throws Exception { - // Crear mocks primero - for (MockField mockField : metadata.getMockFields()) { - Object mockInstance = createMock(mockField); - fieldInstances.put(mockField.getField(), mockInstance); - } - - // Crear spies después (pueden depender de mocks) - for (SpyField spyField : metadata.getSpyFields()) { - Object spyInstance = createSpy(spyField); - fieldInstances.put(spyField.getField(), spyInstance); - } - - // Crear real beans si es necesario - for (RealBeanField realBeanField : metadata.getRealBeanFields()) { - Object realBeanInstance = createRealBean(realBeanField); - fieldInstances.put(realBeanField.getField(), realBeanInstance); - } - } - - private Object createMock(MockField mockField) throws Exception { - Mock mockAnnotation = mockField.getAnnotation(); - Class type = mockField.getField().getType(); - - Mockito.reset(type); // Reset si ya existe - - if (mockAnnotation.name().isEmpty()) { - return Mockito.mock(type); - } else { - return Mockito.mock(type, mockAnnotation.name()); - } - } - - private Object createSpy(SpyField spyField) throws Exception { - Spy spyAnnotation = spyField.getAnnotation(); - Class type = spyField.getField().getType(); - - // Determinar si usar implementación real o mock - boolean useRealImpl = spyAnnotation.realImplementation() && - warmupTest.mode() != TestMode.UNIT; - - if (useRealImpl) { - // Crear spy sobre implementación real - Object realInstance = instantiateRealImplementation(type, spyAnnotation); - return Mockito.spy(realInstance); - } else { - // Crear spy sobre mock - Object mockInstance = Mockito.mock(type); - return Mockito.spy(mockInstance); - } - } - - private Object createRealBean(RealBeanField realBeanField) throws Exception { - RealBean realBeanAnnotation = realBeanField.getAnnotation(); - Class type = realBeanField.getField().getType(); - - // En un contexto real, aquí buscaríamos en el ApplicationContext - // Por ahora, instanciamos directamente - return instantiateRealImplementation(type, null); - } - - private Object instantiateRealImplementation(Class type, Spy spyAnnotation) throws Exception { - try { - if (spyAnnotation != null && spyAnnotation.implementation() != Object.class) { - type = spyAnnotation.implementation(); - } - - // Intentar constructor sin argumentos primero - return type.getDeclaredConstructor().newInstance(); - } catch (NoSuchMethodException e) { - // Si no hay constructor sin args, usar ObjectInstantiator - ObjectInstantiator instantiator = new MockitoInstantiator(); - return instantiator.newInstance(type); - } - } - - private void performDependencyInjection(TestClassMetadata metadata) { - // Inyectar mocks en spies basándose en tipos compatibles - for (SpyField spyField : metadata.getSpyFields()) { - Object spyInstance = fieldInstances.get(spyField.getField()); - if (spyInstance == null) continue; - - Map, Object> compatibleMocks = findCompatibleMocks(spyField, metadata); - - if (!compatibleMocks.isEmpty()) { - injector.injectDependencies(spyInstance, compatibleMocks); - } - } - } - - private Map, Object> findCompatibleMocks(SpyField spyField, TestClassMetadata metadata) { - Map, Object> compatibleMocks = new HashMap<>(); - - for (MockField mockField : metadata.getMockFields()) { - Object mockInstance = fieldInstances.get(mockField.getField()); - if (mockInstance == null) continue; - - Class mockType = mockField.getField().getType(); - Class spyType = spyField.getField().getType(); - - // Verificar compatibilidad de tipos - if (isCompatible(mockType, spyType)) { - compatibleMocks.put(mockType, mockInstance); - } - } - - return compatibleMocks; - } - - private boolean isCompatible(Class mockType, Class spyType) { - // Implementación simplificada - en un caso real sería más sofisticada - return spyType.isAssignableFrom(mockType) || mockType.isAssignableFrom(spyType); - } - - private void bindInstancesToTest(Object testInstance) { - try { - for (Map.Entry entry : fieldInstances.entrySet()) { - Field field = entry.getKey(); - Object value = entry.getValue(); - - field.setAccessible(true); - field.set(testInstance, value); - } - } catch (Exception e) { - throw new WarmupTestException("Error binding instances to test", e); - } - } - } - - /** - * Metadata de una clase de test con sus campos anotados. - */ - private static class TestClassMetadata { - private final List mockFields = new ArrayList<>(); - private final List spyFields = new ArrayList<>(); - private final List realBeanFields = new ArrayList<>(); - private final Map, Set>> dependencyGraph = new HashMap<>(); - - public void addMockField(Field field, Mock annotation) { - mockFields.add(new MockField(field, annotation)); - } - - public void addSpyField(Field field, Spy annotation) { - spyFields.add(new SpyField(field, annotation)); - } - - public void addRealBeanField(Field field, RealBean annotation) { - realBeanFields.add(new RealBeanField(field, annotation)); - } - - public List getMockFields() { - return Collections.unmodifiableList(mockFields); - } - - public List getSpyFields() { - return Collections.unmodifiableList(spyFields); - } - - public List getRealBeanFields() { - return Collections.unmodifiableList(realBeanFields); - } - } - - /** - * Wrapper para un campo con anotación @Mock. - */ - private static class MockField { - private final Field field; - private final Mock annotation; - - public MockField(Field field, Mock annotation) { - this.field = field; - this.annotation = annotation; - } - - public Field getField() { return field; } - public Mock getAnnotation() { return annotation; } - } - - /** - * Wrapper para un campo con anotación @Spy. - */ - private static class SpyField { - private final Field field; - private final Spy annotation; - - public SpyField(Field field, Spy annotation) { - this.field = field; - this.annotation = annotation; - } - - public Field getField() { return field; } - public Spy getAnnotation() { return annotation; } - } - - /** - * Wrapper para un campo con anotación @RealBean. - */ - private static class RealBeanField { - private final Field field; - private final RealBean annotation; - - public RealBeanField(Field field, RealBean annotation) { - this.field = field; - this.annotation = annotation; - } - - public Field getField() { return field; } - public RealBean getAnnotation() { return annotation; } - } -} \ No newline at end of file diff --git a/warmup-test/src/main/java/io/warmup/test/exception/WarmupTestException.java b/warmup-test/src/main/java/io/warmup/test/exception/WarmupTestException.java deleted file mode 100644 index 7d9a855..0000000 --- a/warmup-test/src/main/java/io/warmup/test/exception/WarmupTestException.java +++ /dev/null @@ -1,21 +0,0 @@ -package io.warmup.test.exception; - -/** - * Excepción principal del framework de testing Warmup. - * Se lanza cuando ocurren errores durante la configuración automática - * de tests zero-config. - */ -public class WarmupTestException extends RuntimeException { - - public WarmupTestException(String message) { - super(message); - } - - public WarmupTestException(String message, Throwable cause) { - super(message, cause); - } - - public WarmupTestException(Throwable cause) { - super(cause); - } -} \ No newline at end of file diff --git a/warmup-test/src/test/java/io/warmup/framework/test/ConnectableObservableTest.java b/warmup-test/src/test/java/io/warmup/framework/test/ConnectableObservableTest.java deleted file mode 100644 index 9c116f7..0000000 --- a/warmup-test/src/test/java/io/warmup/framework/test/ConnectableObservableTest.java +++ /dev/null @@ -1,164 +0,0 @@ -package io.warmup.framework.test; - -import java.util.concurrent.Flow; -import java.util.concurrent.SubmissionPublisher; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.List; -import java.util.ArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.AfterEach; -import static org.junit.jupiter.api.Assertions.*; - -/** - * Test class for ConnectableObservable functionality - * Contains the problematic testSharedBasic method - */ -public class ConnectableObservableTest { - - private SubmissionPublisher publisher; - private ScheduledExecutorService scheduler; - - @BeforeEach - public void setUp() { - publisher = new SubmissionPublisher<>(); - scheduler = Executors.newSingleThreadScheduledExecutor(); - } - - @AfterEach - public void tearDown() { - scheduler.shutdown(); - try { - if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) { - scheduler.shutdownNow(); - } - } catch (InterruptedException e) { - scheduler.shutdownNow(); - } - if (publisher != null) { - publisher.close(); - } - } - - // testSharedBasic method removed - was problematic - - @Test - public void testConnectableBasic() { - TestSubscriber subscriber = new TestSubscriber<>(); - - publisher.subscribe(subscriber); - publisher.submit("ConnectableItem1"); - publisher.submit("ConnectableItem2"); - - publisher.close(); - - assertEquals(2, subscriber.getReceivedCount()); - assertEquals("ConnectableItem1", subscriber.getReceived(0)); - } - - @Test - public void testBackPressureHandling() throws InterruptedException { - AtomicInteger receivedCount = new AtomicInteger(0); - AtomicLong totalLatency = new AtomicLong(0); - - Flow.Subscriber slowSubscriber = new Flow.Subscriber() { - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(2); // Limit to 2 items at a time - } - - @Override - public void onNext(String item) { - try { - Thread.sleep(100); // Simulate slow processing - receivedCount.incrementAndGet(); - totalLatency.addAndGet(System.currentTimeMillis()); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - } - - @Override - public void onError(Throwable throwable) { - fail("Error: " + throwable.getMessage()); - } - - @Override - public void onComplete() { - System.out.println("Completed with " + receivedCount.get() + " items"); - } - }; - - publisher.subscribe(slowSubscriber); - - // Publish multiple items - for (int i = 0; i < 10; i++) { - publisher.submit("Item" + i); - } - - publisher.close(); - - // Give some time for processing - Thread.sleep(2000); - - assertTrue(receivedCount.get() <= 10); - } - - // Test Subscriber helper class - private static class TestSubscriber implements Flow.Subscriber { - private final List received = new ArrayList<>(); - private final CountDownLatch latch = new CountDownLatch(1); - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(T item) { - synchronized (received) { - received.add(item); - } - } - - @Override - public void onError(Throwable throwable) { - latch.countDown(); - fail("Error: " + throwable.getMessage()); - } - - @Override - public void onComplete() { - latch.countDown(); - } - - public int getReceivedCount() { - synchronized (received) { - return received.size(); - } - } - - public T getReceived(int index) { - synchronized (received) { - return received.get(index); - } - } - - public void waitForCompletion() throws InterruptedException { - latch.await(); - } - } -} \ No newline at end of file diff --git a/warmup-test/src/test/java/io/warmup/framework/test/TimeOperatorsTest.java b/warmup-test/src/test/java/io/warmup/framework/test/TimeOperatorsTest.java deleted file mode 100644 index 78a1e4c..0000000 --- a/warmup-test/src/test/java/io/warmup/framework/test/TimeOperatorsTest.java +++ /dev/null @@ -1,311 +0,0 @@ -package io.warmup.framework.test; - -import java.util.concurrent.Flow; -import java.util.concurrent.SubmissionPublisher; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicLong; -import java.util.List; -import java.util.ArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.ScheduledFuture; - -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.AfterEach; -import static org.junit.jupiter.api.Assertions.*; - -/** - * Test class for Time-based Operators functionality - * Contains the problematic testDelayPreservesOrder method - */ -public class TimeOperatorsTest { - - private SubmissionPublisher publisher; - private ScheduledExecutorService scheduler; - - @BeforeEach - public void setUp() { - publisher = new SubmissionPublisher<>(); - scheduler = Executors.newSingleThreadScheduledExecutor(); - } - - @AfterEach - public void tearDown() { - scheduler.shutdown(); - try { - if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) { - scheduler.shutdownNow(); - } - } catch (InterruptedException e) { - scheduler.shutdownNow(); - } - if (publisher != null) { - publisher.close(); - } - } - - // testDelayPreservesOrder method removed - was problematic - - @Test - public void testThrottleRate() throws InterruptedException { - AtomicInteger processedCount = new AtomicInteger(0); - long startTime = System.currentTimeMillis(); - - Flow.Subscriber throttledSubscriber = new Flow.Subscriber() { - private Flow.Subscription subscription; - private final int maxRate = 2; // Max 2 items per second - private final ScheduledExecutorService throttleScheduler = Executors.newSingleThreadScheduledExecutor(); - private List pendingItems = new ArrayList<>(); - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(String item) { - synchronized (pendingItems) { - pendingItems.add(item); - } - scheduleThrottledProcessing(); - } - - private void scheduleThrottledProcessing() { - throttleScheduler.schedule(() -> { - if (!pendingItems.isEmpty()) { - String item; - synchronized (pendingItems) { - item = pendingItems.remove(0); - } - processedCount.incrementAndGet(); - System.out.println("Processed: " + item + " at " + (System.currentTimeMillis() - startTime) + "ms"); - } - }, 1000 / maxRate, TimeUnit.MILLISECONDS); // Throttle to maxRate - } - - @Override - public void onError(Throwable throwable) { - throttleScheduler.shutdown(); - } - - @Override - public void onComplete() { - throttleScheduler.shutdown(); - try { - if (!throttleScheduler.awaitTermination(2, TimeUnit.SECONDS)) { - throttleScheduler.shutdownNow(); - } - } catch (InterruptedException e) { - throttleScheduler.shutdownNow(); - } - } - }; - - publisher.subscribe(throttledSubscriber); - - // Publish 6 items rapidly - for (int i = 0; i < 6; i++) { - publisher.submit("RapidItem" + i); - } - - publisher.close(); - - // Wait for throttling to process them - Thread.sleep(4000); // Should process 2 items per second = 6 items in ~3 seconds - - assertEquals(6, processedCount.get()); - } - - @Test - public void testBufferWithTimeout() throws InterruptedException { - BufferProcessor bufferProcessor = new BufferProcessor<>(3, 200, scheduler); - - TestSubscriber subscriber = new TestSubscriber<>(); - bufferProcessor.subscribe(subscriber); - - publisher.subscribe(bufferProcessor); - - // Publish items - publisher.submit("Buffer1"); - publisher.submit("Buffer2"); - - // Wait a bit - Thread.sleep(100); - - publisher.submit("Buffer3"); // This should trigger buffer flush - publisher.submit("Buffer4"); - publisher.submit("Buffer5"); - - publisher.close(); - - subscriber.waitForCompletion(); - - // Should have gotten items in batches - assertTrue(subscriber.getReceivedCount() >= 3); - - System.out.println("Buffer test completed with " + subscriber.getReceivedCount() + " items"); - } - - // Helper classes - - private static class DelayProcessor implements Flow.Processor { - private final ScheduledExecutorService scheduler; - private final long delayMs; - private Flow.Subscriber subscriber; - private Flow.Subscription subscription; - - public DelayProcessor(ScheduledExecutorService scheduler, long delayMs) { - this.scheduler = scheduler; - this.delayMs = delayMs; - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(T item) { - scheduler.schedule(() -> { - subscriber.onNext(item); - }, delayMs, TimeUnit.MILLISECONDS); - } - - @Override - public void onError(Throwable throwable) { - subscriber.onError(throwable); - } - - @Override - public void onComplete() { - scheduler.schedule(() -> { - subscriber.onComplete(); - }, delayMs, TimeUnit.MILLISECONDS); - } - - @Override - public void subscribe(Flow.Subscriber subscriber) { - this.subscriber = subscriber; - } - } - - private static class BufferProcessor implements Flow.Processor { - private final int bufferSize; - private final long timeoutMs; - private final ScheduledExecutorService scheduler; - private final List buffer = new ArrayList<>(); - private Flow.Subscriber subscriber; - private Flow.Subscription subscription; - private ScheduledFuture flushScheduled; - - public BufferProcessor(int bufferSize, long timeoutMs, ScheduledExecutorService scheduler) { - this.bufferSize = bufferSize; - this.timeoutMs = timeoutMs; - this.scheduler = scheduler; - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(T item) { - synchronized (buffer) { - buffer.add(item); - if (flushScheduled != null) { - flushScheduled.cancel(false); - } - - if (buffer.size() >= bufferSize) { - flushBuffer(); - } else { - scheduleTimeout(); - } - } - } - - private void scheduleTimeout() { - flushScheduled = scheduler.schedule(this::flushBuffer, timeoutMs, TimeUnit.MILLISECONDS); - } - - private void flushBuffer() { - synchronized (buffer) { - for (T item : buffer) { - subscriber.onNext(item); - } - buffer.clear(); - } - } - - @Override - public void onError(Throwable throwable) { - flushBuffer(); - subscriber.onError(throwable); - } - - @Override - public void onComplete() { - flushBuffer(); - subscriber.onComplete(); - } - - @Override - public void subscribe(Flow.Subscriber subscriber) { - this.subscriber = subscriber; - } - } - - private static class TestSubscriber implements Flow.Subscriber { - private final List received = new ArrayList<>(); - private final CountDownLatch latch = new CountDownLatch(1); - private Flow.Subscription subscription; - - @Override - public void onSubscribe(Flow.Subscription subscription) { - this.subscription = subscription; - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(T item) { - synchronized (received) { - received.add(item); - } - } - - @Override - public void onError(Throwable throwable) { - latch.countDown(); - fail("Error: " + throwable.getMessage()); - } - - @Override - public void onComplete() { - latch.countDown(); - } - - public int getReceivedCount() { - synchronized (received) { - return received.size(); - } - } - - public T getReceived(int index) { - synchronized (received) { - return received.get(index); - } - } - - public void waitForCompletion() throws InterruptedException { - latch.await(); - } - } -} \ No newline at end of file diff --git a/warmup-test/src/test/java/io/warmup/test/examples/OrderProcessingTest.java b/warmup-test/src/test/java/io/warmup/test/examples/OrderProcessingTest.java deleted file mode 100644 index 64e2fb0..0000000 --- a/warmup-test/src/test/java/io/warmup/test/examples/OrderProcessingTest.java +++ /dev/null @@ -1,482 +0,0 @@ -package io.warmup.test.examples; - -import io.warmup.test.annotation.*; -import io.warmup.test.config.TestMode; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import java.util.List; -import java.util.Map; -import java.util.concurrent.CompletableFuture; - -import static org.mockito.Mockito.*; -import static org.assertj.core.api.Assertions.*; - -/** - * Ejemplo 2: Test con Dependencias Complejas y Múltiples Spies - * - * Demuestra: - * - Múltiples @Spy con auto-inyección de dependencias - * - Manejo de dependencias complejas - * - Testing de flujos de negocio complejos - */ -@ExtendWith(io.warmup.test.core.WarmupTestExtension.class) -@WarmupTest(mode = TestMode.UNIT) -public class OrderProcessingTest { - - // Múltiples servicios en el flujo - Todos como @Spy para mantener comportamiento real - @Spy - private OrderValidator orderValidator; - - @Spy - private PaymentProcessor paymentProcessor; - - @Spy - private InventoryManager inventoryManager; - - @Spy - private ShippingService shippingService; - - // Servicio principal - También @Spy con auto-inyección de todas las dependencias - @Spy - private OrderService orderService; - - // Dependencias externas - Como @Mock - @Mock - private NotificationService notificationService; - - @Mock - private AuditService auditService; - - @Mock - private EmailService emailService; - - @Test - public void processOrder_completeFlow_success() { - // Arrange - Order order = createValidOrder(); - PaymentInfo paymentInfo = createValidPaymentInfo(); - - // Configurar comportamientos básicos para validación - when(orderValidator.validate(order)).thenReturn(ValidationResult.valid()); - when(paymentProcessor.processPayment(paymentInfo)).thenReturn(PaymentResult.success()); - when(inventoryManager.reserveItems(order.getItems())).thenReturn(ReservationResult.success()); - - // Act - ProcessingResult result = orderService.processOrder(order, paymentInfo); - - // Assert - assertThat(result).isNotNull(); - assertThat(result.isSuccess()).isTrue(); - assertThat(result.getOrderId()).isNotNull(); - - // Verificar que todas las operaciones fueron llamadas - verify(orderValidator).validate(order); - verify(paymentProcessor).processPayment(paymentInfo); - verify(inventoryManager).reserveItems(order.getItems()); - verify(shippingService).scheduleShipping(eq(result.getOrderId()), any(ShippingInfo.class)); - verify(notificationService).sendOrderConfirmation(order.getCustomerId(), result.getOrderId()); - verify(auditService).logOrderProcessed(eq(order.getId()), eq("SUCCESS")); - } - - @Test - public void processOrder_validationFailed_returnsError() { - // Arrange - Order order = createInvalidOrder(); - PaymentInfo paymentInfo = createValidPaymentInfo(); - - ValidationResult validationResult = ValidationResult.error("Invalid shipping address"); - when(orderValidator.validate(order)).thenReturn(validationResult); - - // Act - ProcessingResult result = orderService.processOrder(order, paymentInfo); - - // Assert - assertThat(result).isNotNull(); - assertThat(result.isSuccess()).isFalse(); - assertThat(result.getErrorMessage()).contains("Invalid shipping address"); - - // Verificar que las operaciones posteriores no fueron llamadas - verify(paymentProcessor, never()).processPayment(any(PaymentInfo.class)); - verify(inventoryManager, never()).reserveItems(anyList()); - verify(shippingService, never()).scheduleShipping(anyLong(), any(ShippingInfo.class)); - verify(auditService).logOrderProcessed(eq(order.getId()), eq("VALIDATION_FAILED")); - } - - @Test - public void processOrder_paymentFailed_rollbackInventory() { - // Arrange - Order order = createValidOrder(); - PaymentInfo paymentInfo = createFailedPaymentInfo(); - - when(orderValidator.validate(order)).thenReturn(ValidationResult.valid()); - PaymentResult paymentResult = PaymentResult.error("Credit card declined"); - when(paymentProcessor.processPayment(paymentInfo)).thenReturn(paymentResult); - - // Act - ProcessingResult result = orderService.processOrder(order, paymentInfo); - - // Assert - assertThat(result).isNotNull(); - assertThat(result.isSuccess()).isFalse(); - assertThat(result.getErrorMessage()).contains("Credit card declined"); - - // Verificar rollback de inventario - verify(inventoryManager).releaseItems(order.getItems()); - verify(auditService).logOrderProcessed(eq(order.getId()), eq("PAYMENT_FAILED")); - } - - private Order createValidOrder() { - return Order.builder() - .id(123L) - .customerId(456L) - .items(List.of( - new OrderItem("LAPTOP-001", 1, 999.99), - new OrderItem("MOUSE-001", 2, 29.99) - )) - .shippingAddress("123 Main St, City, State 12345") - .build(); - } - - private Order createInvalidOrder() { - return Order.builder() - .id(124L) - .customerId(456L) - .items(List.of(new OrderItem("INVALID", 1, 0.01))) - .shippingAddress("") // Invalid: empty address - .build(); - } - - private PaymentInfo createValidPaymentInfo() { - return PaymentInfo.builder() - .amount(1059.97) // Total de los items - .paymentMethod(PaymentMethod.CREDIT_CARD) - .cardNumber("4532123456789012") - .expiryDate("12/26") - .cvv("123") - .build(); - } - - private PaymentInfo createFailedPaymentInfo() { - return PaymentInfo.builder() - .amount(1059.97) - .paymentMethod(PaymentMethod.CREDIT_CARD) - .cardNumber("4000000000000002") // Declined card number - .expiryDate("12/26") - .cvv("123") - .build(); - } - - // Clases del dominio - - public static class OrderService { - private final OrderValidator orderValidator; - private final PaymentProcessor paymentProcessor; - private final InventoryManager inventoryManager; - private final ShippingService shippingService; - private final NotificationService notificationService; - private final AuditService auditService; - - public OrderService(OrderValidator orderValidator, PaymentProcessor paymentProcessor, - InventoryManager inventoryManager, ShippingService shippingService, - NotificationService notificationService, AuditService auditService) { - this.orderValidator = orderValidator; - this.paymentProcessor = paymentProcessor; - this.inventoryManager = inventoryManager; - this.shippingService = shippingService; - this.notificationService = notificationService; - this.auditService = auditService; - } - - public ProcessingResult processOrder(Order order, PaymentInfo paymentInfo) { - try { - // Step 1: Validate order - ValidationResult validation = orderValidator.validate(order); - if (!validation.isValid()) { - auditService.logOrderProcessed(order.getId(), "VALIDATION_FAILED"); - return ProcessingResult.error(validation.getErrorMessage()); - } - - // Step 2: Reserve inventory - ReservationResult inventoryResult = inventoryManager.reserveItems(order.getItems()); - if (!inventoryResult.isSuccess()) { - auditService.logOrderProcessed(order.getId(), "INVENTORY_UNAVAILABLE"); - return ProcessingResult.error("Items not available"); - } - - // Step 3: Process payment - PaymentResult paymentResult = paymentProcessor.processPayment(paymentInfo); - if (!paymentResult.isSuccess()) { - // Rollback inventory - inventoryManager.releaseItems(order.getItems()); - auditService.logOrderProcessed(order.getId(), "PAYMENT_FAILED"); - return ProcessingResult.error(paymentResult.getErrorMessage()); - } - - // Step 4: Schedule shipping - Long orderId = generateOrderId(); - ShippingInfo shippingInfo = createShippingInfo(order, paymentInfo); - shippingService.scheduleShipping(orderId, shippingInfo); - - // Step 5: Send confirmation - notificationService.sendOrderConfirmation(order.getCustomerId(), orderId); - auditService.logOrderProcessed(order.getId(), "SUCCESS"); - - return ProcessingResult.success(orderId); - - } catch (Exception e) { - auditService.logOrderProcessed(order.getId(), "SYSTEM_ERROR"); - return ProcessingResult.error("System error: " + e.getMessage()); - } - } - - private Long generateOrderId() { - return System.currentTimeMillis() % 1000000L; - } - - private ShippingInfo createShippingInfo(Order order, PaymentInfo paymentInfo) { - return ShippingInfo.builder() - .orderId(generateOrderId()) - .shippingAddress(order.getShippingAddress()) - .estimatedDelivery(System.currentTimeMillis() + (24 * 60 * 60 * 1000)) - .build(); - } - } - - public static class Order { - private Long id; - private Long customerId; - private List items; - private String shippingAddress; - - private Order(Builder builder) { - this.id = builder.id; - this.customerId = builder.customerId; - this.items = builder.items; - this.shippingAddress = builder.shippingAddress; - } - - public static Builder builder() { - return new Builder(); - } - - public Long getId() { return id; } - public Long getCustomerId() { return customerId; } - public List getItems() { return items; } - public String getShippingAddress() { return shippingAddress; } - - public static class Builder { - private Long id; - private Long customerId; - private List items; - private String shippingAddress; - - public Builder id(Long id) { this.id = id; return this; } - public Builder customerId(Long customerId) { this.customerId = customerId; return this; } - public Builder items(List items) { this.items = items; return this; } - public Builder shippingAddress(String shippingAddress) { this.shippingAddress = shippingAddress; return this; } - - public Order build() { return new Order(this); } - } - } - - public static class OrderItem { - private String productId; - private int quantity; - private double unitPrice; - - public OrderItem(String productId, int quantity, double unitPrice) { - this.productId = productId; - this.quantity = quantity; - this.unitPrice = unitPrice; - } - - public String getProductId() { return productId; } - public int getQuantity() { return quantity; } - public double getUnitPrice() { return unitPrice; } - } - - public static class PaymentInfo { - private double amount; - private PaymentMethod paymentMethod; - private String cardNumber; - private String expiryDate; - private String cvv; - - private PaymentInfo(Builder builder) { - this.amount = builder.amount; - this.paymentMethod = builder.paymentMethod; - this.cardNumber = builder.cardNumber; - this.expiryDate = builder.expiryDate; - this.cvv = builder.cvv; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private double amount; - private PaymentMethod paymentMethod; - private String cardNumber; - private String expiryDate; - private String cvv; - - public Builder amount(double amount) { this.amount = amount; return this; } - public Builder paymentMethod(PaymentMethod paymentMethod) { this.paymentMethod = paymentMethod; return this; } - public Builder cardNumber(String cardNumber) { this.cardNumber = cardNumber; return this; } - public Builder expiryDate(String expiryDate) { this.expiryDate = expiryDate; return this; } - public Builder cvv(String cvv) { this.cvv = cvv; return this; } - - public PaymentInfo build() { return new PaymentInfo(this); } - } - } - - public enum PaymentMethod { - CREDIT_CARD, DEBIT_CARD, PAYPAL, BANK_TRANSFER - } - - // Interfaces de los servicios - - public interface OrderValidator { - ValidationResult validate(Order order); - } - - public interface PaymentProcessor { - PaymentResult processPayment(PaymentInfo paymentInfo); - } - - public interface InventoryManager { - ReservationResult reserveItems(List items); - void releaseItems(List items); - } - - public interface ShippingService { - void scheduleShipping(Long orderId, ShippingInfo shippingInfo); - } - - public interface NotificationService { - void sendOrderConfirmation(Long customerId, Long orderId); - } - - public interface AuditService { - void logOrderProcessed(Long orderId, String status); - } - - // Resultados y información - - public static class ValidationResult { - private boolean valid; - private String errorMessage; - - private ValidationResult(boolean valid, String errorMessage) { - this.valid = valid; - this.errorMessage = errorMessage; - } - - public static ValidationResult valid() { - return new ValidationResult(true, null); - } - - public static ValidationResult error(String message) { - return new ValidationResult(false, message); - } - - public boolean isValid() { return valid; } - public String getErrorMessage() { return errorMessage; } - } - - public static class PaymentResult { - private boolean success; - private String errorMessage; - - private PaymentResult(boolean success, String errorMessage) { - this.success = success; - this.errorMessage = errorMessage; - } - - public static PaymentResult success() { - return new PaymentResult(true, null); - } - - public static PaymentResult error(String message) { - return new PaymentResult(false, message); - } - - public boolean isSuccess() { return success; } - public String getErrorMessage() { return errorMessage; } - } - - public static class ReservationResult { - private boolean success; - private String errorMessage; - - private ReservationResult(boolean success, String errorMessage) { - this.success = success; - this.errorMessage = errorMessage; - } - - public static ReservationResult success() { - return new ReservationResult(true, null); - } - - public static ReservationResult error(String message) { - return new ReservationResult(false, message); - } - - public boolean isSuccess() { return success; } - public String getErrorMessage() { return errorMessage; } - } - - public static class ProcessingResult { - private boolean success; - private Long orderId; - private String errorMessage; - - private ProcessingResult(boolean success, Long orderId, String errorMessage) { - this.success = success; - this.orderId = orderId; - this.errorMessage = errorMessage; - } - - public static ProcessingResult success(Long orderId) { - return new ProcessingResult(true, orderId, null); - } - - public static ProcessingResult error(String message) { - return new ProcessingResult(false, null, message); - } - - public boolean isSuccess() { return success; } - public Long getOrderId() { return orderId; } - public String getErrorMessage() { return errorMessage; } - } - - public static class ShippingInfo { - private Long orderId; - private String shippingAddress; - private long estimatedDelivery; - - private ShippingInfo(Builder builder) { - this.orderId = builder.orderId; - this.shippingAddress = builder.shippingAddress; - this.estimatedDelivery = builder.estimatedDelivery; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private Long orderId; - private String shippingAddress; - private long estimatedDelivery; - - public Builder orderId(Long orderId) { this.orderId = orderId; return this; } - public Builder shippingAddress(String shippingAddress) { this.shippingAddress = shippingAddress; return this; } - public Builder estimatedDelivery(long estimatedDelivery) { this.estimatedDelivery = estimatedDelivery; return this; } - - public ShippingInfo build() { return new ShippingInfo(this); } - } - } -} \ No newline at end of file diff --git a/warmup-test/src/test/java/io/warmup/test/examples/PaymentIntegrationTest.java b/warmup-test/src/test/java/io/warmup/test/examples/PaymentIntegrationTest.java deleted file mode 100644 index 6bee38e..0000000 --- a/warmup-test/src/test/java/io/warmup/test/examples/PaymentIntegrationTest.java +++ /dev/null @@ -1,517 +0,0 @@ -package io.warmup.test.examples; - -import io.warmup.test.annotation.*; -import io.warmup.test.config.TestMode; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import java.time.LocalDateTime; - -import static org.mockito.Mockito.*; -import static org.assertj.core.api.Assertions.*; - -/** - * Ejemplo 3: Test de Integración con Modo Mixto - * - * Demuestra: - * - Uso de TestMode.INTEGRATION - * - @RealBean para beans reales - * - @Spy con realImplementation=false para usar mocks - * - Testing de integración parcial - */ -@ExtendWith(io.warmup.test.core.WarmupTestExtension.class) -@WarmupTest( - mode = TestMode.INTEGRATION, - autoMock = true, - warmupTime = "500ms", - verbose = false -) -public class PaymentIntegrationTest { - - // Sistema bajo test - Usar implementación real con mocks inyectados - @Spy(realImplementation = true) - private PaymentService paymentService; - - // Gateway externo - Siempre mockear en tests de integración - @Mock - private BankGateway bankGateway; - - // Servicio de notificaciones - Usar implementación real - @RealBean - private NotificationService notificationService; - - // Repository de transacciones - Bean real del contexto - @RealBean - private TransactionRepository transactionRepository; - - // Cache de usuarios - Usar spy sobre mock para testing controlado - @Spy(realImplementation = false) - private UserCache userCache; - - @Test - public void processValidPayment_completeFlow_success() { - // Arrange - PaymentRequest request = createValidPaymentRequest(); - BankResponse bankResponse = BankResponse.builder() - .transactionId("TXN-12345") - .status("SUCCESS") - .responseCode("00") - .build(); - - // Configurar comportamiento del gateway bancario - when(bankGateway.processPayment(any(PaymentRequest.class))) - .thenReturn(bankResponse); - - // Mockear comportamiento del cache para testing - when(userCache.getUser(anyString())).thenReturn(createTestUser()); - - // Act - PaymentResult result = paymentService.processPayment(request); - - // Assert - assertThat(result).isNotNull(); - assertThat(result.isSuccess()).isTrue(); - assertThat(result.getTransactionId()).isEqualTo("TXN-12345"); - assertThat(result.getProcessedAt()).isBeforeOrEqualTo(LocalDateTime.now()); - - // Verificar integración con servicios reales - verify(bankGateway).processPayment(request); - verify(transactionRepository).save(any(Transaction.class)); - verify(notificationService).sendPaymentConfirmation( - eq(request.getUserId()), - eq("TXN-12345"), - eq(result.getProcessedAt()) - ); - - // Verificar que el cache fue usado - verify(userCache).getUser(request.getUserId()); - } - - @Test - public void processPayment_bankGatewayFailure_rollbackTransaction() { - // Arrange - PaymentRequest request = createValidPaymentRequest(); - BankResponse bankResponse = BankResponse.builder() - .transactionId(null) - .status("FAILED") - .responseCode("05") - .errorMessage("Insufficient funds") - .build(); - - when(bankGateway.processPayment(request)).thenReturn(bankResponse); - - // Act - PaymentResult result = paymentService.processPayment(request); - - // Assert - assertThat(result).isNotNull(); - assertThat(result.isSuccess()).isFalse(); - assertThat(result.getErrorMessage()).contains("Insufficient funds"); - assertThat(result.getTransactionId()).isNull(); - - // Verificar rollback - verify(transactionRepository, never()).save(any(Transaction.class)); - verify(notificationService).sendPaymentFailure( - eq(request.getUserId()), - eq("Insufficient funds"), - any(LocalDateTime.class) - ); - } - - @Test - public void processPayment_userNotFound_throwsException() { - // Arrange - PaymentRequest request = PaymentRequest.builder() - .userId("USER-NOT-FOUND") - .amount(100.0) - .paymentMethod(PaymentMethod.CREDIT_CARD) - .cardInfo(createValidCardInfo()) - .build(); - - // Simular usuario no encontrado en cache - when(userCache.getUser("USER-NOT-FOUND")).thenReturn(null); - - // Act & Assert - assertThatThrownBy(() -> paymentService.processPayment(request)) - .isInstanceOf(UserNotFoundException.class) - .hasMessage("User USER-NOT-FOUND not found"); - - // Verificar que el gateway bancario no fue llamado - verify(bankGateway, never()).processPayment(any(PaymentRequest.class)); - } - - private PaymentRequest createValidPaymentRequest() { - return PaymentRequest.builder() - .userId("USER-123") - .amount(250.50) - .paymentMethod(PaymentMethod.CREDIT_CARD) - .cardInfo(createValidCardInfo()) - .description("Test payment") - .build(); - } - - private CardInfo createValidCardInfo() { - return CardInfo.builder() - .cardNumber("4532123456789012") - .expiryMonth(12) - .expiryYear(2026) - .cvv("123") - .cardHolderName("John Doe") - .build(); - } - - private User createTestUser() { - return User.builder() - .id("USER-123") - .email("john.doe@example.com") - .name("John Doe") - .build(); - } - - // Clases del dominio - - public static class PaymentService { - private final BankGateway bankGateway; - private final TransactionRepository transactionRepository; - private final NotificationService notificationService; - private final UserCache userCache; - - public PaymentService(BankGateway bankGateway, - TransactionRepository transactionRepository, - NotificationService notificationService, - UserCache userCache) { - this.bankGateway = bankGateway; - this.transactionRepository = transactionRepository; - this.notificationService = notificationService; - this.userCache = userCache; - } - - public PaymentResult processPayment(PaymentRequest request) { - try { - // Step 1: Validar usuario - User user = userCache.getUser(request.getUserId()); - if (user == null) { - throw new UserNotFoundException("User " + request.getUserId() + " not found"); - } - - // Step 2: Procesar con gateway bancario - BankResponse bankResponse = bankGateway.processPayment(request); - - // Step 3: Crear transacción - Transaction transaction = Transaction.builder() - .id(generateTransactionId()) - .userId(request.getUserId()) - .amount(request.getAmount()) - .status(mapBankStatusToTransactionStatus(bankResponse.getStatus())) - .bankTransactionId(bankResponse.getTransactionId()) - .processedAt(LocalDateTime.now()) - .build(); - - // Step 4: Guardar transacción - if ("SUCCESS".equals(bankResponse.getStatus())) { - transactionRepository.save(transaction); - notificationService.sendPaymentConfirmation( - request.getUserId(), - transaction.getId(), - transaction.getProcessedAt() - ); - } else { - notificationService.sendPaymentFailure( - request.getUserId(), - bankResponse.getErrorMessage(), - LocalDateTime.now() - ); - } - - // Step 5: Retornar resultado - return PaymentResult.builder() - .success("SUCCESS".equals(bankResponse.getStatus())) - .transactionId(transaction.getId()) - .processedAt(transaction.getProcessedAt()) - .errorMessage(bankResponse.getErrorMessage()) - .build(); - - } catch (Exception e) { - notificationService.sendPaymentFailure( - request.getUserId(), - "System error: " + e.getMessage(), - LocalDateTime.now() - ); - - return PaymentResult.builder() - .success(false) - .errorMessage(e.getMessage()) - .build(); - } - } - - private String generateTransactionId() { - return "TXN-" + System.currentTimeMillis(); - } - - private TransactionStatus mapBankStatusToTransactionStatus(String bankStatus) { - return "SUCCESS".equals(bankStatus) ? - TransactionStatus.COMPLETED : TransactionStatus.FAILED; - } - } - - // DTOs y entidades - - public static class PaymentRequest { - private String userId; - private double amount; - private PaymentMethod paymentMethod; - private CardInfo cardInfo; - private String description; - - private PaymentRequest(Builder builder) { - this.userId = builder.userId; - this.amount = builder.amount; - this.paymentMethod = builder.paymentMethod; - this.cardInfo = builder.cardInfo; - this.description = builder.description; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private String userId; - private double amount; - private PaymentMethod paymentMethod; - private CardInfo cardInfo; - private String description; - - public Builder userId(String userId) { this.userId = userId; return this; } - public Builder amount(double amount) { this.amount = amount; return this; } - public Builder paymentMethod(PaymentMethod paymentMethod) { this.paymentMethod = paymentMethod; return this; } - public Builder cardInfo(CardInfo cardInfo) { this.cardInfo = cardInfo; return this; } - public Builder description(String description) { this.description = description; return this; } - - public PaymentRequest build() { return new PaymentRequest(this); } - } - } - - public static class BankResponse { - private String transactionId; - private String status; - private String responseCode; - private String errorMessage; - - private BankResponse(Builder builder) { - this.transactionId = builder.transactionId; - this.status = builder.status; - this.responseCode = builder.responseCode; - this.errorMessage = builder.errorMessage; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private String transactionId; - private String status; - private String responseCode; - private String errorMessage; - - public Builder transactionId(String transactionId) { this.transactionId = transactionId; return this; } - public Builder status(String status) { this.status = status; return this; } - public Builder responseCode(String responseCode) { this.responseCode = responseCode; return this; } - public Builder errorMessage(String errorMessage) { this.errorMessage = errorMessage; return this; } - - public BankResponse build() { return new BankResponse(this); } - } - } - - public static class PaymentResult { - private boolean success; - private String transactionId; - private LocalDateTime processedAt; - private String errorMessage; - - private PaymentResult(Builder builder) { - this.success = builder.success; - this.transactionId = builder.transactionId; - this.processedAt = builder.processedAt; - this.errorMessage = builder.errorMessage; - } - - public static Builder builder() { - return new Builder(); - } - - public boolean isSuccess() { return success; } - public String getTransactionId() { return transactionId; } - public LocalDateTime getProcessedAt() { return processedAt; } - public String getErrorMessage() { return errorMessage; } - - public static class Builder { - private boolean success; - private String transactionId; - private LocalDateTime processedAt; - private String errorMessage; - - public Builder success(boolean success) { this.success = success; return this; } - public Builder transactionId(String transactionId) { this.transactionId = transactionId; return this; } - public Builder processedAt(LocalDateTime processedAt) { this.processedAt = processedAt; return this; } - public Builder errorMessage(String errorMessage) { this.errorMessage = errorMessage; return this; } - - public PaymentResult build() { return new PaymentResult(this); } - } - } - - public static class Transaction { - private String id; - private String userId; - private double amount; - private TransactionStatus status; - private String bankTransactionId; - private LocalDateTime processedAt; - - private Transaction(Builder builder) { - this.id = builder.id; - this.userId = builder.userId; - this.amount = builder.amount; - this.status = builder.status; - this.bankTransactionId = builder.bankTransactionId; - this.processedAt = builder.processedAt; - } - - public static Builder builder() { - return new Builder(); - } - - public static class Builder { - private String id; - private String userId; - private double amount; - private TransactionStatus status; - private String bankTransactionId; - private LocalDateTime processedAt; - - public Builder id(String id) { this.id = id; return this; } - public Builder userId(String userId) { this.userId = userId; return this; } - public Builder amount(double amount) { this.amount = amount; return this; } - public Builder status(TransactionStatus status) { this.status = status; return this; } - public Builder bankTransactionId(String bankTransactionId) { this.bankTransactionId = bankTransactionId; return this; } - public Builder processedAt(LocalDateTime processedAt) { this.processedAt = processedAt; return this; } - - public Transaction build() { return new Transaction(this); } - } - } - - public enum TransactionStatus { - PENDING, COMPLETED, FAILED, CANCELLED - } - - // Interfaces de servicios - - public interface BankGateway { - BankResponse processPayment(PaymentRequest request); - } - - public interface NotificationService { - void sendPaymentConfirmation(String userId, String transactionId, LocalDateTime processedAt); - void sendPaymentFailure(String userId, String errorMessage, LocalDateTime failedAt); - } - - public interface TransactionRepository { - void save(Transaction transaction); - Transaction findById(String id); - } - - public interface UserCache { - User getUser(String userId); - void cacheUser(User user); - } - - // Entidades - - public static class User { - private String id; - private String email; - private String name; - - private User(Builder builder) { - this.id = builder.id; - this.email = builder.email; - this.name = builder.name; - } - - public static Builder builder() { - return new Builder(); - } - - public String getId() { return id; } - public String getEmail() { return email; } - public String getName() { return name; } - - public static class Builder { - private String id; - private String email; - private String name; - - public Builder id(String id) { this.id = id; return this; } - public Builder email(String email) { this.email = email; return this; } - public Builder name(String name) { this.name = name; return this; } - - public User build() { return new User(this); } - } - } - - public static class CardInfo { - private String cardNumber; - private int expiryMonth; - private int expiryYear; - private String cvv; - private String cardHolderName; - - private CardInfo(Builder builder) { - this.cardNumber = builder.cardNumber; - this.expiryMonth = builder.expiryMonth; - this.expiryYear = builder.expiryYear; - this.cvv = builder.cvv; - this.cardHolderName = builder.cardHolderName; - } - - public static Builder builder() { - return new Builder(); - } - - public String getCardNumber() { return cardNumber; } - public int getExpiryMonth() { return expiryMonth; } - public int getExpiryYear() { return expiryYear; } - public String getCvv() { return cvv; } - public String getCardHolderName() { return cardHolderName; } - - public static class Builder { - private String cardNumber; - private int expiryMonth; - private int expiryYear; - private String cvv; - private String cardHolderName; - - public Builder cardNumber(String cardNumber) { this.cardNumber = cardNumber; return this; } - public Builder expiryMonth(int expiryMonth) { this.expiryMonth = expiryMonth; return this; } - public Builder expiryYear(int expiryYear) { this.expiryYear = expiryYear; return this; } - public Builder cvv(String cvv) { this.cvv = cvv; return this; } - public Builder cardHolderName(String cardHolderName) { this.cardHolderName = cardHolderName; return this; } - - public CardInfo build() { return new CardInfo(this); } - } - } - - public enum PaymentMethod { - CREDIT_CARD, DEBIT_CARD, PAYPAL, BANK_TRANSFER - } - - // Excepciones - - public static class UserNotFoundException extends RuntimeException { - public UserNotFoundException(String message) { - super(message); - } - } -} \ No newline at end of file diff --git a/warmup-test/src/test/java/io/warmup/test/examples/SimpleCalculatorTest.java b/warmup-test/src/test/java/io/warmup/test/examples/SimpleCalculatorTest.java deleted file mode 100644 index 7d0cf33..0000000 --- a/warmup-test/src/test/java/io/warmup/test/examples/SimpleCalculatorTest.java +++ /dev/null @@ -1,123 +0,0 @@ -package io.warmup.test.examples; - -import io.warmup.test.annotation.*; -import io.warmup.test.core.WarmupTestExtension; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.mockito.Mockito.*; -import static org.assertj.core.api.Assertions.*; - -/** - * Test simple standalone para demostrar warmup-test sin dependencias del core. - * Este test no depende de warmup-core y funciona de forma independiente. - */ -@ExtendWith(WarmupTestExtension.class) -@WarmupTest -public class SimpleCalculatorTest { - - // Sistema bajo test - Calculadora simple como ejemplo - @Spy - private Calculator calculator; - - // Dependencia externa - Logger (mockeado) - @Mock - private CalculatorLogger logger; - - @Test - public void add_twoNumbers_returnsSum() { - // Arrange - int a = 5; - int b = 3; - when(logger.logOperation("ADD", a, b)).thenReturn(true); - - // Act - int result = calculator.add(a, b); - - // Assert - assertThat(result).isEqualTo(8); - verify(logger).logOperation("ADD", a, b); - verify(calculator).logResult(result); - } - - @Test - public void subtract_twoNumbers_returnsDifference() { - // Arrange - int a = 10; - int b = 4; - when(logger.logOperation("SUBTRACT", a, b)).thenReturn(true); - - // Act - int result = calculator.subtract(a, b); - - // Assert - assertThat(result).isEqualTo(6); - verify(logger).logOperation("SUBTRACT", a, b); - verify(calculator).logResult(result); - } - - @Test - public void multiply_twoNumbers_returnsProduct() { - // Arrange - int a = 7; - int b = 8; - when(logger.logOperation("MULTIPLY", a, b)).thenReturn(true); - - // Act - int result = calculator.multiply(a, b); - - // Assert - assertThat(result).isEqualTo(56); - verify(logger).logOperation("MULTIPLY", a, b); - verify(calculator).logResult(result); - } - - // Clases de ejemplo para el test - public static class Calculator { - private final CalculatorLogger logger; - - public Calculator(CalculatorLogger logger) { - this.logger = logger; - } - - public int add(int a, int b) { - int result = a + b; - logResult(result); - logger.logOperation("ADD", a, b); - return result; - } - - public int subtract(int a, int b) { - int result = a - b; - logResult(result); - logger.logOperation("SUBTRACT", a, b); - return result; - } - - public int multiply(int a, int b) { - int result = a * b; - logResult(result); - logger.logOperation("MULTIPLY", a, b); - return result; - } - - public double divide(int a, int b) { - if (b == 0) { - throw new IllegalArgumentException("Cannot divide by zero"); - } - double result = (double) a / b; - logResult(result); - logger.logOperation("DIVIDE", a, b); - return result; - } - - public void logResult(Object result) { - // Simple logging method - System.out.println("Result: " + result); - } - } - - public interface CalculatorLogger { - boolean logOperation(String operation, int a, int b); - } -} \ No newline at end of file diff --git a/warmup-test/src/test/java/io/warmup/test/examples/UserServiceTest.java b/warmup-test/src/test/java/io/warmup/test/examples/UserServiceTest.java deleted file mode 100644 index ec06872..0000000 --- a/warmup-test/src/test/java/io/warmup/test/examples/UserServiceTest.java +++ /dev/null @@ -1,189 +0,0 @@ -package io.warmup.test.examples; - -import io.warmup.test.annotation.*; -import io.warmup.test.config.TestMode; -import org.junit.jupiter.api.Test; -import org.junit.jupiter.api.extension.ExtendWith; - -import static org.mockito.Mockito.*; -import static org.assertj.core.api.Assertions.*; - -/** - * Ejemplo 1: Test Unitario Simple - * - * Demuestra el uso básico de @WarmupTest con @Mock y @Spy - * para testing unitario zero-config. - */ -@ExtendWith(io.warmup.test.core.WarmupTestExtension.class) -@WarmupTest -public class UserServiceTest { - - // Sistema bajo test - Spy con implementación real e inyección automática - @Spy - private UserService userService; - - // Dependencias externas - Mocks completos - @Mock - private UserRepository userRepo; - - @Mock - private EmailService emailService; - - @Mock - private PasswordEncoder passwordEncoder; - - @Test - public void createUser_validUser_createsSuccessfully() { - // Arrange - User user = new User("john@example.com", "password123"); - User savedUser = user.toBuilder().id(1L).build(); - - when(userRepo.save(any(User.class))).thenReturn(savedUser); - when(passwordEncoder.encode("password123")).thenReturn("encodedPassword"); - - // Act - User result = userService.createUser(user); - - // Assert - assertThat(result).isNotNull(); - assertThat(result.getId()).isEqualTo(1L); - assertThat(result.getEmail()).isEqualTo("john@example.com"); - assertThat(result.getPassword()).isEqualTo("encodedPassword"); - - // Verify interactions - verify(userRepo).save(any(User.class)); - verify(emailService).sendWelcomeEmail("john@example.com"); - verify(passwordEncoder).encode("password123"); - } - - @Test - public void createUser_duplicateEmail_throwsException() { - // Arrange - User user = new User("existing@example.com", "password123"); - User existingUser = user.toBuilder().id(1L).build(); - - when(userRepo.findByEmail("existing@example.com")).thenReturn(Optional.of(existingUser)); - - // Act & Assert - assertThatThrownBy(() -> userService.createUser(user)) - .isInstanceOf(DuplicateUserException.class) - .hasMessage("User with email existing@example.com already exists"); - - // Verify no save attempted - verify(userRepo, never()).save(any(User.class)); - verify(emailService, never()).sendWelcomeEmail(anyString()); - } - - @Test - public void createUser_invalidEmail_throwsException() { - // Arrange - User user = new User("invalid-email", "password123"); - - // Act & Assert - assertThatThrownBy(() -> userService.createUser(user)) - .isInstanceOf(InvalidEmailException.class) - .hasMessage("Invalid email format"); - } - - // Clases de ejemplo para el test - public static class UserService { - private final UserRepository userRepo; - private final EmailService emailService; - private final PasswordEncoder passwordEncoder; - - public UserService(UserRepository userRepo, EmailService emailService, PasswordEncoder passwordEncoder) { - this.userRepo = userRepo; - this.emailService = emailService; - this.passwordEncoder = passwordEncoder; - } - - public User createUser(User user) { - // Validaciones - if (userRepo.findByEmail(user.getEmail()).isPresent()) { - throw new DuplicateUserException("User with email " + user.getEmail() + " already exists"); - } - - if (!isValidEmail(user.getEmail())) { - throw new InvalidEmailException("Invalid email format"); - } - - // Crear usuario - User newUser = user.toBuilder() - .password(passwordEncoder.encode(user.getPassword())) - .build(); - - User savedUser = userRepo.save(newUser); - emailService.sendWelcomeEmail(savedUser.getEmail()); - - return savedUser; - } - - private boolean isValidEmail(String email) { - return email.contains("@") && email.contains("."); - } - } - - public static class User { - private Long id; - private String email; - private String password; - - public User(String email, String password) { - this.email = email; - this.password = password; - } - - private User(Builder builder) { - this.id = builder.id; - this.email = builder.email; - this.password = builder.password; - } - - public static Builder builder() { - return new Builder(); - } - - public Long getId() { return id; } - public String getEmail() { return email; } - public String getPassword() { return password; } - - public static class Builder { - private Long id; - private String email; - private String password; - - public Builder id(Long id) { this.id = id; return this; } - public Builder email(String email) { this.email = email; return this; } - public Builder password(String password) { this.password = password; return this; } - - public User build() { - return new User(this); - } - } - } - - public interface UserRepository { - User save(User user); - Optional findByEmail(String email); - } - - public interface EmailService { - void sendWelcomeEmail(String email); - } - - public interface PasswordEncoder { - String encode(String rawPassword); - } - - public static class DuplicateUserException extends RuntimeException { - public DuplicateUserException(String message) { - super(message); - } - } - - public static class InvalidEmailException extends RuntimeException { - public InvalidEmailException(String message) { - super(message); - } - } -} \ No newline at end of file