diff --git a/.github/workflows/check-for-issue.yml b/.github/workflows/check-for-issue.yml index 3ddec8cbf1..4bb511006b 100644 --- a/.github/workflows/check-for-issue.yml +++ b/.github/workflows/check-for-issue.yml @@ -1,4 +1,4 @@ -name: Check for issue for blogs +name: Check for blog issue on: pull_request: @@ -27,23 +27,26 @@ jobs: echo "is_new_blog=false" >> $GITHUB_OUTPUT fi - - name: Get PR body + - name: Add blog process comment if: steps.check-new-blog.outputs.is_new_blog == 'true' - id: pr-body - run: | - body="${{ github.event.pull_request.body }}" - echo "body=${body}" >> $GITHUB_OUTPUT + uses: peter-evans/create-or-update-comment@v3 + with: + token: ${{ secrets.GITHUB_TOKEN }} + issue-number: ${{ github.event.pull_request.number }} + body: | + The blog process is Submit a PR -> (Optional) Peer review -> Doc review -> Editorial review -> Marketing review -> Published. - name: Check for linked issues if: steps.check-new-blog.outputs.is_new_blog == 'true' id: check-issues run: | - body="${{ github.event.pull_request.body }}" - if echo "$body" | grep -iE "(closes|fixes|resolves|references|ref|close|fix|resolve) #[0-9]+"; then + echo "${{ github.event.pull_request.body }}" > pr_body.txt + if grep -iE "(closes|fixes|resolves|references|ref|close|fix|resolve) #[0-9]+" pr_body.txt > /dev/null; then echo "has_issue=true" >> $GITHUB_OUTPUT else echo "has_issue=false" >> $GITHUB_OUTPUT fi + rm pr_body.txt - name: Comment if no linked issue if: steps.check-new-blog.outputs.is_new_blog == 'true' && steps.check-issues.outputs.has_issue == 'false' @@ -59,4 +62,4 @@ jobs: - Fixes #issue-number - Resolves #issue-number - If there isn't an issue yet, please [create one](https://github.com/opensearch-project/project-website/issues/new?template=blog_post.yml) and then link it to this PR. \ No newline at end of file + If there isn't an issue yet, please [create one](https://github.com/opensearch-project/project-website/issues/new?template=blog_post.yml) and then link it to this PR. diff --git a/_community_members/cwperks.md b/_community_members/cwperks.md index 532d3844d7..20de6fda59 100644 --- a/_community_members/cwperks.md +++ b/_community_members/cwperks.md @@ -21,4 +21,4 @@ permalink: '/community/members/craig-perkins.html' redirect_from: '/authors/craigperkins/' --- -**Dave Lago** is an AWS Software Development Engineer working on the OpenSearch project. +**Craig Perkins** is an AWS Software Development Engineer working on the OpenSearch Project. diff --git a/_community_members/kumargu.md b/_community_members/kumargu.md index 8531edbb9e..098b912b7b 100644 --- a/_community_members/kumargu.md +++ b/_community_members/kumargu.md @@ -1,7 +1,7 @@ --- name: Gulshan Kumar short_name: kumargu -photo: '/assets/media/community/members/kumargu.jpg' +photo: '/assets/media/community/members/kumargu.png' title: 'OpenSearch Community Member: Gulshan Kumar' primary_title: Gulshan Kumar breadcrumbs: diff --git a/_community_members/san81.md b/_community_members/san81.md new file mode 100755 index 0000000000..8da4be541e --- /dev/null +++ b/_community_members/san81.md @@ -0,0 +1,34 @@ +--- +short_name: 'san81' +name: 'Santhosh Gandhe' +photo: '/assets/media/community/members/san81.jpg' +job_title_and_company: 'Software Development Engineer at AWS - OpenSearch' +primary_title: 'Santhosh Gandhe' +title: 'OpenSearch Community Member: Santhosh Gandhe' +breadcrumbs: + icon: community + items: + - title: Community + url: /community/index.html + - title: Members + url: /community/members/index.html + - title: "Santhosh Gandhe's Profile" + url: '/community/members/santhsoh-gandhe.html' +keynote_speaker: false +session_track: + - conference_id: "2024-north-america" + name: "Community" + +linkedin: 'santhosh-gandhe-6314538' +github: 'san81' +permalink: '/community/members/santhosh-gandhe.html' + +personas: + - author +conference_id: + - "2024-north-america" +redirect_from: '/authors/san81/' +--- + +Santhosh is a software engineer working on observability in OpenSearch at Amazon Web Services. He is a contributor on the Data Prepper project. Prior to working at Amazon, he was a senior software engineer at Wayfair, helped build their Advertising Bidding platform. + diff --git a/_community_members/will-hwang.md b/_community_members/will-hwang.md new file mode 100644 index 0000000000..71c8e6146d --- /dev/null +++ b/_community_members/will-hwang.md @@ -0,0 +1,24 @@ +--- +name: Will Hwang +short_name: will-hwang +photo: "/assets/media/community/members/will-hwang.jpg" +title: 'OpenSearch Community Member: Will Hwang' +primary_title: Will Hwang +breadcrumbs: + icon: community + items: + - title: Community + url: /community/index.html + - title: Members + url: /community/members/index.html + - title: 'Will Hwang's Profile' + url: '/community/members/will-hwang.html' +github: will-hwang +job_title_and_company: 'Software Engineer at Amazon Web Services' +personas: + - author +permalink: '/community/members/will-hwang.html' +redirect_from: '/authors/will-hwang/' +--- + +**Will Hwang** is a Software Engineer at AWS who focuses on neural search development in OpenSearch. \ No newline at end of file diff --git a/_posts/2019-09-10-Check-out-earlier-blogposts-on-Open-Distro-for-Elasticsearch.markdown b/_posts/2019-09-10-Check-out-earlier-blogposts-on-Open-Distro-for-Elasticsearch.markdown index 914c53da9d..1193a0ed89 100644 --- a/_posts/2019-09-10-Check-out-earlier-blogposts-on-Open-Distro-for-Elasticsearch.markdown +++ b/_posts/2019-09-10-Check-out-earlier-blogposts-on-Open-Distro-for-Elasticsearch.markdown @@ -15,6 +15,8 @@ redirect_from: /blog/odfe-updates/2019/09/Check-out-earlier-blogposts-on-Open-Di --- Hi Open Distro blog readers, + + Check out earlier blogs posts for Open Distro for Elasticsearch which were published on the AWSOpen blog. Going forward, bookmark the Open Distro blog as your source for in-depth, technical articles on the project. You’ll find how-tos, release notes, case studies, event announcements, and if you’re inspired to contribute, your own content, too! Add Single Sign-On (SSO) to Open Distro for Elasticsearch Kibana Using SAML and Okta diff --git a/_posts/2025-04-21-OpenSearch-Becnhmark--An-Update.md b/_posts/2025-04-21-OpenSearch-Becnhmark--An-Update.md index 36370ead0f..3ecc8482ba 100644 --- a/_posts/2025-04-21-OpenSearch-Becnhmark--An-Update.md +++ b/_posts/2025-04-21-OpenSearch-Becnhmark--An-Update.md @@ -1,8 +1,8 @@ --- layout: post -title: OpenSearch Benchmark: An update +title: "OpenSearch Benchmark: An update" authors: -- govkamat + - govkamat date: 2025-05-12 12:30:00 -0600 categories: - community diff --git a/_posts/2025-04-24-Announcing-Data-Prepper-2.11.md b/_posts/2025-04-24-Announcing-Data-Prepper-2.11.md index f83ab36538..ade10fb3bf 100644 --- a/_posts/2025-04-24-Announcing-Data-Prepper-2.11.md +++ b/_posts/2025-04-24-Announcing-Data-Prepper-2.11.md @@ -1,11 +1,11 @@ --- layout: post -title: 'Announcing OpenSearch Data Prepper 2.11: Supercharged OpenTelemetry and even more sources' +title: "Announcing OpenSearch Data Prepper 2.11: Supercharged OpenTelemetry and even more sources" authors: -- san81 -- kkondaka -- dvenable -- oeyh + - san81 + - kkondaka + - dvenable + - oeyh date: 2025-04-17 12:30:00 -0600 categories: - releases @@ -83,8 +83,8 @@ jira-pipeline: hosts: ["<>"] authentication: basic: - username: ${{aws_secrets:jira-account-credentials:jiraId}} - password: ${{aws_secrets:jira-account-credentials:jiraCredential}} + username: {%raw%}${{aws_secrets:jira-account-credentials:jiraId}}{%endraw %} + password: {%raw%}${{aws_secrets:jira-account-credentials:jiraCredential}}{%endraw %} filter: project: key: @@ -132,8 +132,8 @@ confluence-pipeline: hosts: ["<>"] authentication: basic: - username: ${{aws_secrets:confluence-account-credentials:confluenceId}} - password: ${{aws_secrets:confluence-account-credentials:confluenceCredential}} + username: ${%raw %}{{aws_secrets:confluence-account-credentials:confluenceId}}{%endraw %} + password: ${%raw %}{{aws_secrets:confluence-account-credentials:confluenceCredential}}{%endraw %} filter: space: key: @@ -185,8 +185,8 @@ aurora-mysql-pipeline: sts_role_arn: "arn:aws:iam::123456789012:role/PipelineRole" region: "us-east-1" authentication: - username: ${{aws_secrets:secret:username}} - password: ${{aws_secrets:secret:password}} + username: ${%raw %}{{aws_secrets:secret:username}}{%endraw %} + password: ${%raw %}{{aws_secrets:secret:password}}{%endraw %} ``` ## Amazon SQS as a source diff --git a/_posts/2025-05-08-opensearch-performance-3.0.md b/_posts/2025-05-08-opensearch-performance-3.0.md new file mode 100644 index 0000000000..52d3238ed2 --- /dev/null +++ b/_posts/2025-05-08-opensearch-performance-3.0.md @@ -0,0 +1,1013 @@ +--- +layout: post +title: "OpenSearch Project update: Performance progress in OpenSearch 3.0" +layout: post +authors: + - sisurab + - pallp + - vamshin + - seanzheng + - kolchfa +date: 2025-05-14 +categories: + - technical-posts + - community +meta_keywords: OpenSearch 3.0, query performance improvement, Lucene 10, concurrent segment search, star-tree index, vector search performance, AI/ML workloads, indexing throughput, neural sparse search, OpenSearch benchmark +meta_description: OpenSearch 3.0 delivers major performance improvements, including 10x faster search queries, 2.5x vector search boost, and GPU acceleration. Learn about key enhancements and the future roadmap. +has_science_table: true +excerpt: Learn more about the strategic enhancements and performance features that OpenSearch has delivered up to version 3.0. +featured_blog_post: false +featured_image: false +#additional_author_info: We sincerely appreciate the contributions to this blog from Anandhi Bumstead, Carl Meadows, Jon Handler, Dagney Braun, Michael Froh, Kunal Khatua, Andrew Ross, Harsha Vamsi, Bowen Lan, Rishabh Kumar Maurya, Sandesh Kumar, Marc Handalian, Rishabh Singh, Govind Kamat, Martin Gaievski, and Minal Shah. +--- + +[OpenSearch 3.0](https://opensearch.org/blog/unveiling-opensearch-3-0/) marks a major milestone in the project's ongoing performance journey and the first major release since 2.0 in April 2022. Building on the enhancements of the 2.x series, the 3.0 release integrates **Apache Lucene 10** and upgrades the Java runtime to **JDK 21**, bringing significant improvements to search throughput, indexing and query latency, and vector processing. With a **10x search performance boost** and **2.5x vector search performance boost**, Lucene 10 continues to be our strategic search library, and its latest version delivers measurable gains over earlier releases (baselined against 1.x) through enhanced query execution, skip-based filtering, and segment-level concurrency. + +This post provides a detailed update on OpenSearch 3.0's performance, focusing on search queries, indexing throughput, artificial intelligence and machine learning (AI/ML) use cases, and vector search workloads. We'll highlight measurable impacts, as observed in our benchmarks, and explain how new Lucene 10 features, such as concurrent segment search, query optimizations, doc-value skip lists, and prefetch APIs, contribute to future [OpenSearch roadmaps](https://github.com/orgs/opensearch-project/projects/206). All results are supported by benchmark data, in keeping with our focus on community transparency and real-world impact. + +## Query performance improvements in OpenSearch 3.0 + +OpenSearch 3.0 continues the steady performance gains achieved throughout the 2.x line, as shown in the following graph. Compared to OpenSearch 1.3, query latency in OpenSearch 3.0 has been reduced by about **90%** (geometric mean across key query types), meaning queries are on average over **10x faster** than in 1.3. Even compared to more recent 2.x versions, 3.0's query operations are about **24% faster** than 2.19 (the last 2.x release) on the [OpenSearch Big5 workload](https://github.com/opensearch-project/opensearch-benchmark-workloads/tree/main/big5). + +![OpenSearch latency performance graph 3.0](/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/OpenSearch_latency_performance.png){:style="width: 100%; max-width: 800px; height: auto; text-align: center"} + +The following table summarizes latency benchmarks across versions 1.3.18, 2.x, and 3.0. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Big 5 areas mean latency, msQuery type1.3.182.72.112.122.132.142.152.162.172.182.193.0 GA
Text queries59.5147.9141.0527.2927.6127.8527.3921.721.7722.318.228.3
Sorting17.7311.248.147.997.537.477.787.227.269.987.967.03
Terms aggregations609.43135113161228291293113112113111.74112.0879.72
Range queries26.0823.1216.9118.7117.3317.3918.513.173.173.553.672.68
Date histograms606852495168469357146157164160163.58159.5785.21
Aggregate (geo mean)159.04154.59130.974.8551.8443.4437.0724.6624.6327.0421.2116.04
Speedup factor, compared to OS 1.3 (geo mean)N/A1.031.212.123.073.664.296.456.465.887.509.92
Relative latency, compared to OS 1.3 (geo mean)N/A97.2082.3147.0632.6027.3123.3115.5115.4917.0013.3410.09
+ +*Row 7 shows Big5 benchmark mean latency (ms) by OpenSearch version. Lower is better.* +*Rows 8 and 9 show speedup factor and latency relative to the 1.3 baseline.* + +The OpenSearch 3.0 release brings search performance gains in two main areas: + +1. **Out-of-the-box improvements in Lucene 10**: Lucene 10 introduces hardware-level enhancements such as SIMD-accelerated vector scoring and more efficient postings decoding, which immediately benefit query performance and require no configuration changes. For example, minute-level date histogram aggregations run up to **60% faster**, `search_after` queries improve by **20--24%**, and scroll queries show modest latency reductions because of low-level enhancements in both Lucene 10 and JDK 21. +1. **OpenSearch-specific engine optimizations**: Since our [previous update](https://opensearch.org/blog/opensearch-performance-2.17/), the OpenSearch community implemented multiple targeted optimizations in versions 2.18, 2.19, and 3.0. These include cost-based query planning, optimized handling for high-frequency terms queries, restoration of a time-series sort optimization lost with the Lucene 10 upgrade, aggregation engine improvements, request cache concurrency enhancements, and resolution of Lucene-induced regressions (for example, sort and merge slowdowns). Additionally, OpenSearch 3.0 introduces **auto-enabled concurrent segment search**, which selectively parallelizes expensive queries, delivering double-digit latency reductions on operations like `date_histogram` and `terms` aggregations. + +## Key performance highlights + +The following sections describe key performance highlights in OpenSearch 3.0. + +### Lucene 10 improvements + +The Lucene 10 upgrade introduced out-of-the-box speedups using SIMD vectorization and improved input/output patterns. OpenSearch 3.0 inherits these benefits, with complex query-string searches showing **~24% lower p50 latency** compared to 2.19 ([issue #17385](https://github.com/opensearch-project/OpenSearch/issues/17385)). Other operations, like high-cardinality aggregations, improved by **~10--20%** solely because of the engine change. Additionally, OpenSearch addressed several regressions caused by the Lucene 10 transition, including performance drops in `composite_terms` operations on keyword fields ([#17387](https://github.com/opensearch-project/OpenSearch/issues/17387), [#17388](https://github.com/opensearch-project/OpenSearch/issues/17388)). With these fixes, keyword-heavy filters and aggregations in OpenSearch 3.0 now perform as well as, or better than, their counterparts in the 2.x series. + +### Query operation improvements (compared to OpenSearch 1.3.18 and 2.17) + +To further accelerate query execution, OpenSearch introduced targeted optimizations across core operations: + +* **Text queries**: The median latency for full-text queries is ~8 ms in 3.0 compared to ~60 ms in 1.3 (**~87% faster**). In 2.19, most gains were achieved through cost-based filter planning and early clause elimination. Further, Boolean scorer improvements helped reduce tail latencies in 3.0. Compared to 2.17 (~21.7 ms), this is a **~3x speedup** ([#17385](https://github.com/opensearch-project/OpenSearch/issues/17385)). +* **Terms aggregations**: Latency dropped from ~609 ms in 1.3 to ~80 ms in 3.0 (**~85% faster**; **~30% compared to 2.17**). Improvements include optimized global ordinals, smarter doc values access, and execution hints for controlling cardinality aggregation memory usage ([#17657](https://github.com/opensearch-project/OpenSearch/pull/17657)). Approximate filtering for range constraints also reduced scan costs in observability use cases. +* **Sort queries**: Sorted queries are **~60% faster** than in 1.3 and **~5--10% faster** than in 2.17. OpenSearch 3.0 restored Lucene's time-series sort optimization by correctly invoking the new `searchAfterPartition()` API ([PR #17329](https://github.com/opensearch-project/OpenSearch/pull/17329)) and resolving regressions in `desc_sort_timestamp` queries ([#17404](https://github.com/opensearch-project/OpenSearch/issues/17404)). +* **Date histograms**: Latency fell from ~6s in 1.3 to ~146 ms in 3.0, with lows of ~85 ms using concurrency (up to **60x faster**). Gains come from block skipping, segment-level parallelism, and [sub-agg optimizations](https://github.com/opensearch-project/OpenSearch/pull/17447) (for example, pushing filters inside range-auto-date aggs). 3.0 is up to **~50% faster than 2.19** in this category. +* **Range queries**: Range filters now run in ~2.75 ms, down from ~26 ms in 1.3 (**~89% faster**) and **~25% faster than 2.19**. OpenSearch's [range approximation framework](https://github.com/opensearch-project/OpenSearch/issues/16682) became generally available in 3.0, delivering gains through more efficient use of doc values and by skipping over non-matching blocks, further lowering scan costs. + +### Star-tree index for log analytics + +Introduced in 2.19, the **[star-tree aggregator](https://github.com/opensearch-project/opensearch-build/blob/main/release-notes/opensearch-release-notes-2.19.0.md)** enables pre-aggregated metric and filtered terms queries. In eligible use cases, this reduces query compute by up to **100x** and cache usage by **~30x**. 3.0 extends support to multi-level and numeric terms aggregations (with [sorted bucket elimination](https://github.com/opensearch-project/OpenSearch/pull/17671)), achieving **~15–20% lower latency** over 2.19 in benchmarks. + +### Concurrent segment search (auto mode) + +OpenSearch 3.0 defaults to **concurrent segment search in the `auto` mode**, allowing the engine to choose between sequential and parallel segment execution per query. Expensive aggregations (for example, `terms` or `date_histogram`) run in parallel, while lightweight queries stay single-threaded to avoid overhead. On an 8-vCPU cluster, this yielded **~35% lower latency on date histograms**, **15%+ on terms aggregations**, and showed an **~8% aggregate gain** across the Big5. Text queries stayed flat (for example, 8.22 ms sequential compared to 8.93 ms auto), confirming that the selector works as intended without regression. + + +## AI/ML and vector search performance improvements + +OpenSearch 3.0 builds on the vector engine enhancements introduced in the 2.x series, continuing to improve performance, memory efficiency, and configurability for both exact k-NN and approximate k-NN (ANN) search. These capabilities are critical for workloads running semantic search and generative AI. + +### GPU acceleration for vector index builds + +The introduction of GPU acceleration for vector indexing in OpenSearch represents a major advancement in supporting large-scale AI workloads. Benchmarks showed that GPU acceleration **improved indexing speed by 9.3x and reduced costs by 3.75x** compared to CPU-based solutions. This dramatically reduces the time required for billion-scale index builds from days to just hours. The decoupled design, which separates the GPU-powered index build service from the main OpenSearch cluster, provides flexibility to evolve the components independently and enables seamless adoption across cloud and on-premises environments. By using the CAGRA algorithm from NVIDIA's cuVS library and supporting GPU-CPU index interoperability, OpenSearch delivers a robust, scalable vector search solution with built-in fault tolerance and fallback mechanisms for production reliability. For more information, see [this blog post](https://opensearch.org/blog/GPU-Accelerated-Vector-Search-OpenSearch-New-Frontier/) and the [RFC](https://github.com/opensearch-project/k-NN/issues/2293). + +### Derived source (3x storage reduction) + +In OpenSearch 3.0, derived source for vectors is enabled by default for all vector indexes. By removing the redundant storage of the `_source` field, using derived source for vectors results in a **3x reduction in storage** across all engines tested (Faiss, Lucene, and NMSLIB), as shown in the following graph. + +![3x storage reduction](/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/vector-search-store.png) + +This storage optimization also has a significant impact on performance, with a **30x improvement** in p90 cold start query latencies for the Lucene engine, as shown in the following graph. + +![30x improvement in p90 cold start query latencies for the Lucene engine](/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/cold-start-query.png) + +This feature also saw strong improvements in merge time reduction: up to 40% across all engines, as shown in the following graph. + +![Force merge improvements](/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/force-merge.png) + +These substantial gains in both storage efficiency and query performance demonstrate the value of using derived source for vectors when operating OpenSearch as a high-scale vector search engine. The transparent nature of this feature, which preserves critical functionality like reindexing and field-based updates, makes it available to a wide range of users looking to optimize their vector search workloads in OpenSearch. For more information, see the [RFC](https://github.com/opensearch-project/k-NN/issues/2377). + +For benchmarking tests, see the [nightly benchmarks](https://benchmarks.opensearch.org/app/home). Benchmarks are run against a 10M/768D dataset. + +### Vector search performance boost of up to 2.5x + +Concurrent segment search is [now enabled by default](https://github.com/opensearch-project/OpenSearch/pull/17978) for all vector search use cases. Concurrent segment search boosts vector query performance by up to **2.5x** with no impact on recall through parallelizing search queries across multiple threads. Additionally, changes to the floor segment size setting in the merge policy create more balanced segments and [improve tail latencies](https://github.com/opensearch-project/k-NN/pull/2623#issuecomment-2749056885) by up to **20%**. This performance boost is applicable to both in-memory and disk-optimized indexes. + +**Service time comparison** + +The following table compares 90th percentile (p90) service times, in milliseconds, across different k-NN engines with various concurrent segment search configurations. + +|k-NN engine |Concurrent segment search disabled |Concurrent segment search enabled (Lucene default number of slices) |% Improvement |Concurrent segment search with `max_slice_count` = 2 |% Improvement |Concurrent segment search with `max_slice_count` = 4 |% Improvement |Concurrent segment search with `max_slice_count` = 8 |% Improvement | +|--- |--- |--- |--- |--- |--- |--- |--- |--- |--- | +|Lucene |37 |15 |59.5 |16 |56.8 |15.9 |57 |16 |56.8 | +|--- |--- |--- |--- |--- |--- |--- |--- |--- |--- | +|NMSLIB |35 |14 |60 |23 |34.3 |15 |57.1 |12 |65.7 | +|Faiss |37 |14 |62.2 |22 |40.5 |15 |59.5 |16 |56.8 | + +### Embedding processor optimization + +In OpenSearch 3.0, we added `skip_existing` support in the `text_embedding` processor to improve embedding ingestion performance. Previously, the processor made ML inference calls regardless of whether it was adding new embeddings or updating existing embeddings. With this feature, users now have an option to configure the processor so that it skips inference calls when the target embedding field is not changed. This feature applies to both dense embeddings and sparse embeddings. By skipping the inference calls, this optimization can reduce ingestion latencies by up to **70% for text embeddings**, **40% for text/image embeddings**, and **80% for sparse text embeddings**. + +### Pruning for neural sparse search + +Neural sparse search is a semantic search technique built on the native Lucene inverted index. It encodes documents and queries into sparse vectors, in which each entry represents a token and its corresponding semantic weight. Because the encoding process expands tokens with semantic weights during encoding, the number of tokens in the sparse vectors is often higher than in the original text. These vectors also follow a long-tail distribution: many tokens have low semantic importance but still consume significant storage. As a result, index sizes produced by sparse models can be 4 to 7 times larger than those generated by BM25. Introduced in OpenSearch 2.19, pruning helps address this issue by removing tokens with relatively low weights during ingestion and search. Depending on the strategy used, pruning can reduce index size by up to **60%** with only about a 1% impact on search relevance. + +## Indexing and ingestion performance + +OpenSearch 3.0 maintains the indexing throughput of the 2.x series while integrating updates from Lucene 10. In benchmark tests indexing 70 million documents (60 GB) on an r5.xlarge node, version 3.0 sustained a throughput of approximately 20,000 documents per second, matching the performance of OpenSearch 2.19 under identical bulk ingestion conditions. Ingestion time and segment counts were also comparable after normalizing for segment merges, indicating that the format changes introduced by Lucene 10 add minimal overhead for typical workloads. + +OpenSearch 3.0 enables support for sparse doc values introduced in Lucene 10. When indexes are sorted (for example, by timestamp) Lucene builds skip lists that accelerate range queries and aggregations. While this introduces minor indexing overhead, it significantly improves query efficiency. In time-series benchmarks, enabling sparse doc values had no impact on ingestion speed while improving date-based query performance. + +Segment merging behavior remains stable in OpenSearch 3.0, with a few updated defaults to better utilize modern hardware. Force merge now uses [1/4th of machine cores instead of 1](https://github.com/opensearch-project/OpenSearch/pull/17255), the default floor segment size has increased from [4 MB to 16 MB](https://github.com/opensearch-project/OpenSearch/pull/17699), and maxMergeAtOnce changed from 10 to 30, which is aligned with the Lucene 10 defaults. Additionally, maxMergeAtOnce is now available [as a cluster-level setting](https://github.com/opensearch-project/OpenSearch/pull/17774) for custom tuning. While one extra segment was observed after ingestion in 3.0 (20 compared to 19 in 2.19), forced merges equalized the results without increasing CPU usage or garbage collection overhead. All other aspects of the merge policy remain unchanged. + +Vector indexing also saw significant improvements in OpenSearch 3.0. By using Lucene's `KnnVectorsFormat`, 3.0 supports incremental HNSW graph merging, which reduces memory usage and eliminates the need for full graph rebuilds. This enhancement lowered the memory footprint and reduced vector index build time by **~30%** compared to version 1.3. Combined with earlier optimizations such as byte compression, OpenSearch 3.0 can index large vector datasets using up to **85% less memory** than earlier releases. + +In summary, OpenSearch 3.0 maintains the indexing performance of the 2.x series while delivering improved memory efficiency and incorporating Lucene 10 enhancements that boost query performance without impacting ingestion speed. + + +## Roadmap for OpenSearch 3.1 and beyond + +Performance continues to be a central focus for the OpenSearch Project. Based on the [public roadmap](https://github.com/orgs/opensearch-project/projects/206/views/20) and upcoming 3.1 release, several initiatives are underway: + +* **[Building on Lucene 10](https://github.com/opensearch-project/OpenSearch/issues/16934)**: Looking ahead, OpenSearch 3.x releases will continue to build on this foundation. Upcoming efforts include using Lucene's concurrent segment execution for force-merged indexes and integrating asynchronous disk I/O using the new `IndexInput.prefetch()` API. We are also planning to evaluate support for sparse doc values and block-level metadata in order to enable more efficient range queries and aggregations. These enhancements, combined with continued performance improvements (for example, in term query, `search_after`, and sort performance), will help OpenSearch deliver even lower latencies and better throughput across diverse workloads. + +* **[Cost-based query planning](https://github.com/opensearch-project/OpenSearch/issues/12390)**: OpenSearch is developing a query planner that uses statistics and cost modeling to select execution strategies more efficiently. This includes choosing between bitset and term filters, determining clause order, and deciding when to enable concurrent segment search. This effort targets improved latency and resource usage, especially for complex queries. + +* **[Streaming query execution](https://github.com/opensearch-project/OpenSearch/issues/16774)**: We're currently working on introducing a streaming model, in which query stages can begin before the previous ones fully complete. This approach should lower latency and memory usage by allowing results to flow incrementally. Initial support is planned for specific aggregations and query types in the 3.x series. + +* **[gRPC/protobuf-based communication](https://github.com/opensearch-project/OpenSearch/issues/15190)**: As per-shard latency decreases, coordination overhead becomes more significant. Optimizations are planned to reduce serialization costs, make coordinator node communication with multiple data nodes more efficient, and support more parallelism in response handling across nodes. We're also considering adding support for a gRPC-based API using protocol buffers (protobuf) for serialization and deserialization. + +* **[Join support and advanced queries](https://github.com/opensearch-project/OpenSearch/issues/15185)**: Native join support is planned for 2025, with an emphasis on runtime efficiency. Techniques like index-level bloom filters or pre-join caching will be used to reduce query costs and support production-grade usage. + +* **[Native SIMD and vectorization](https://github.com/opensearch-project/OpenSearch/issues/9423)**: OpenSearch is exploring the use of native code and SIMD instructions beyond Lucene for operations like aggregations and result sorting. These efforts aim to reduce JVM overhead and improve throughput in CPU-bound workloads. + +* **[GPU acceleration for quantized vector indexes](https://github.com/opensearch-project/k-NN/issues/2295)**: OpenSearch is expanding its GPU acceleration capabilities for quantized vector indexes. While the 3.0 release introduced GPU support for full-precision (FP32) indexes, the upcoming 3.1 release will extend GPU acceleration to a broader range of quantization techniques, including FP16, byte, and binary indexes. Looking beyond version 3.1, OpenSearch plans to extend GPU capabilities for search workloads. + +* **Disk-optimized vector search---Phase 2**: OpenSearch 3.1 will introduce significant enhancements to disk-optimized vector search capabilities, marking Phase 2 of its optimization journey. Building upon the success of binary quantization, the system will incorporate the following techniques: random rotation and Asymmetric Distance Computation (ADC). These improvements, inspired by the innovative RaBitQ paper, deliver a substantial boost to recall performance while maintaining the benefits of disk optimization. + +* **[Partial loading of graphs using the Faiss vector engine](https://github.com/opensearch-project/k-NN/issues/2401)**: Starting with version 3.1, the introduction of partial graph loading will mark a major breakthrough in how vector search operates. Unlike traditional approaches that load entire graphs into memory, this new approach will selectively load only the required portions of the graph needed for search traversal. This smart loading mechanism will deliver two crucial benefits: it will dramatically reduce memory consumption and enable billion-scale workloads to run efficiently even in single-node environments. + +* **[Support for BFloat16 (efficient FP16) for vectors](https://github.com/opensearch-project/k-NN/issues/2510)**: FP16 support using the Faiss scalar quantizer (SQfp16) reduces memory usage by 50% while maintaining performance and recall levels similar to FP32 vectors. However, it has a limitation: input vectors must fall within the range of [-65504, 65504]. BFloat16 offers an alternative that provides the full range of FP32 by trading off precision (it supports up to 2 or 3 decimal values, or 7 mantissa bits) and still uses 16 bits per dimension (providing a 50% memory reduction). + +* **[Multi-tenancy/high-cardinality filtering in vector search](https://github.com/opensearch-project/k-NN/issues/1140)**: OpenSearch is taking multi-tenant vector search to the next level with its enhanced filtering capabilities. At the core of this improvement is an innovative approach to partitioning HNSW graphs based on tenant boundaries. This strategic enhancement will deliver two critical advantages: superior search accuracy and robust data isolation between tenants. By organizing vector search data structures according to tenant boundaries, filter queries operate exclusively within their respective tenant partitions, eliminating cross-tenant noise and improving precision. + +* **Improving vector search throughput with smart query routing**: By implementing semantic-based data organization across OpenSearch nodes, grouping similar embeddings together, you will be able to enable targeted searching of relevant nodes for nearest neighbors. This approach will allow you to search a subset of shards per query, potentially increasing throughput by up to 3x while reducing compute requirements. + +OpenSearch 3.1 will be the first minor release to build on 3.0 based on the [OpenSearch release schedule](https://opensearch.org/releases/). It will include Lucene updates, refinements to concurrent search, and improvements to aggregation, vector, and indexing frameworks. As usual, we'll share performance updates in the release notes and blog posts. + + +## Appendix: Benchmarking methodology + +All performance comparisons were conducted using a repeatable process based on the OpenSearch Benchmark tool and the Big5 workload. Benchmarks covered match queries, terms aggregations, range filters, date histograms, and sorted queries. The dataset (~100 GB, 116 million documents) reflects time-series and e-commerce use cases. + +**Environment**: Tests were run on a single-node OpenSearch cluster using c5.2xlarge Amazon Elastic Compute Cloud (Amazon EC2) instances (8 vCPUs, 16 GB RAM, 8 GB JVM heap). Default settings were used unless noted. Indexes had one primary shard and no replicas to avoid multi-shard variability. Documents were ingested chronologically to simulate time-series workloads. + +**Index settings**: We used Lucene's `LogByteSizeMergePolicy` and did not enable explicit index sorting. In some tests, a force merge was applied to normalize segment counts (for example, 10 segments in both 2.19 and 3.0) in order to ensure a fair comparison. + +**Execution**: Each operation was repeated multiple times. We discarded warmup runs and averaged the next three runs. Latency metrics included p50, p90, and p99; throughput was also recorded. OpenSearch Benchmark was run in throughput-throttled mode to record accurate query latency for each operation type. + +**Software**: Comparisons used OpenSearch 2.19.1 (Java 17) and 3.0.0-beta (Java 21, Lucene 10.1.0). Only default plugins were enabled. Vector benchmarks used Faiss + HNSW using the k-NN plugin, with recall measured against brute-force results. + +**Metrics**: _Big5 median latency_ is the simple mean of the five core query types. _Aggregate latency_ is the geometric mean, used for overall comparison. Speedup factors are reported relative to OpenSearch 1.3 where noted. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
BucketsQueryOrderOS 1.3.18OS 2.7OS 2.11.1OS 2.12.0OS 2.13.0OS 2.14OS 2.15OS 2.16OS 2.17OS 2.18OS 2.19OS 3.0
Text queriesquery-string-on-message1332.7528027678.258077.7577.2577.75788544
query-string-on-message-filtered267.254730.2546.547.54646.7529.530271111
query-string-on-message-filtered-sorted-num3125.2510285.54141.254140.752424.5272627
term443.754444444444
Sortingasc_sort_timestamp59.7515.757.5777777777
asc_sort_timestamp_can_match_shortcut613.75776.7566.256.566.25777
asc_sort_timestamp_no_can_match_shortcut713.5776.5666.566.25777
asc_sort_with_after_timestamp83533.75238212197.5213.5204.25160.5185.25216150168
desc_sort_timestamp912.2539.25675.755.755.7566877
desc_sort_timestamp_can_match_shortcut107120.555.554.75555665
desc_sort_timestamp_no_can_match_shortcut116.75117554.754.54.7555665
desc_sort_with_after_timestamp1248733.75325.75358361.5385.25378.25320.25329.526224693
sort_keyword_can_match_shortcut13291333.253.53333444
sort_keyword_no_can_match_shortcut14290.753.2533.53.2533.7533.25444
sort_numeric_asc157.54.54.54444441743
sort_numeric_asc_with_match1621.7522221.7522222
sort_numeric_desc178665.54.7554.754.254.51654
sort_numeric_desc_with_match182222221.7522222
Terms aggregationscardinality-agg-high193075.752432.252506.2522462284.52202.252323.752337.252408.7523242235628
cardinality-agg-low202925.52295.5238321262245.252159333333
composite_terms-keyword21466.75378.5407.75394.5353.5366350346.5350.25216218202
composite-terms22290242263252233228.75229223.75226333362328
keyword-terms234695.253478.753557.5322029.52625.7526.2526.25272619
keyword-terms-low-cardinality244699.533833477.253249.75252221.7521.7521.75222213
multi_terms-keyword250*0*854.75817.25796.5748768.5746.75770736734657
Range querieskeyword-in-range26101.5100182223.252627.251817.75646814
range27857714.518.2520.2522.7524.2513.7514.2511144
range_field_conjunction_big_range_big_term_query28222222222222
range_field_conjunction_small_range_big_term_query2921.7522221.522222
range_field_conjunction_small_range_small_term_query30222222222222
range_field_disjunction_big_range_small_term_query31222222222.25222
range-agg-1324641.253810.753745.753578.753477.53328.753318.7522.25222
range-agg-23345683717.253669.753492.753403.53243.5323522.25222
range-numeric34222222222222
Date histogramscomposite-date_histogram-daily354828.754055.54051.25932.532.752.75333
date_histogram_hourly_agg364790.2543614363.2512.512.756.2566.256.5764
date_histogram_minute_agg371404.51340.251113.751001.259233632.7535.2539.75353637
range-auto-date-histo38103738686.759940.258696.758199.758214.758278.7583068293.75809578991871
range-auto-date-histo-with-metrics3922988.52043820108.2520392.7520117.2519656.519959.2520364.7520147.519686202115406
+ + +While results may vary in different environments, we controlled for noise and hardware variability. The relative performance trends are expected to hold across most real-world scenarios. The [OpenSearch Benchmark workload](https://github.com/opensearch-project/opensearch-benchmark-workloads) is open source, and we welcome replication and feedback from the community. diff --git a/_posts/2025-05-15-optimized-inference-processors.md b/_posts/2025-05-15-optimized-inference-processors.md new file mode 100644 index 0000000000..51e4c2c508 --- /dev/null +++ b/_posts/2025-05-15-optimized-inference-processors.md @@ -0,0 +1,242 @@ +--- +layout: post +title: "Optimizing inference processors for cost efficiency and performance" +authors: + - will-hwang + - heemin-kim + - kolchfa +date: 2025-05-29 +has_science_table: true +categories: + - technical-posts +meta_keywords: inference processors, vector embeddings, OpenSearch text embedding, text image embedding, sparse encoding, caching mechanism, ingest pipeline, OpenSearch optimization +meta_description: Learn about a new OpenSearch optimization for inference processors that reduces redundant calls, lowering costs and improving performance in vector embedding generation. + +--- + +Inference processors, such as `text_embedding`, `text_image_embedding`, and `sparse_encoding`, enable the generation of vector embeddings during document ingestion or updates. Today, these processors invoke model inference every time a document is ingested or updated, even if the embedding source fields remain unchanged. This can lead to unnecessary compute usage and increased costs. + +This blog post introduces a new inference processor optimization that reduces redundant inference calls, lowering costs and improving overall performance. + +## How the optimization works + +The optimization adds a caching mechanism that compares the embedding source fields in the updated document against the existing document. If the embedding fields have not changed, the processor directly copies the existing embeddings into the updated document instead of triggering new inference. If the fields differ, the processor proceeds with inference as usual. The following diagram illustrates this workflow. + +![Optimization workflow](/assets/media/blog-images/2025-05-15-optimized-inference-processors/diagram.png) + +This approach minimizes redundant inference calls, significantly improving efficiency without impacting the accuracy or freshness of embeddings. + +## How to enable the optimization + +To enable this optimization, set the `skip_existing` parameter to `true` in your ingest pipeline processor definition. This option is available for [`text_embedding`](#text-embedding-processor), [`text_image_embedding`](#textimage-embedding-processor), and [`sparse_encoding`](#sparse-encoding-processor) processors. By default, `skip_existing` is set to `false`. + +### Text embedding processor + +The [`text_embedding` processor](https://docs.opensearch.org/docs/latest/ingest-pipelines/processors/text-embedding/) generates vector embeddings for text fields, typically used in semantic search. + +* **Optimization behavior**: If `skip_existing` is `true`, the processor checks whether the text fields mapped in `field_map` have changed. If they haven't, inference is skipped and the existing vector is reused. + +**Example pipeline**: + +```json +PUT /_ingest/pipeline/optimized-ingest-pipeline +{ + "description": "Optimized ingest pipeline", + "processors": [ + { + "text_embedding": { + "model_id": "", + "field_map": { + "text": "" + }, + "skip_existing": true + } + } + ] +} +``` + +### Text/image embedding processor + +The [`text_image_embedding` processor](https://docs.opensearch.org/docs/latest/ingest-pipelines/processors/text-image-embedding/) generates combined embeddings from text and image fields for multimodal search use cases. + +* **Optimization behavior**: Because embeddings are generated for combined text and image fields, inference is skipped only if **both** the text and image fields mapped in `field_map` are unchanged. + +**Example pipeline**: + +```json +PUT /_ingest/pipeline/optimized-ingest-pipeline +{ + "description": "Optimized ingest pipeline", + "processors": [ + { + "text_image_embedding": { + "model_id": "", + "embedding": "", + "field_map": { + "text": "", + "image": "" + }, + "skip_existing": true + } + } + ] +} +``` + +### Sparse encoding processor + +The [`sparse_encoding` processor](https://docs.opensearch.org/docs/latest/ingest-pipelines/processors/sparse-encoding/) generates sparse vectors from text fields used in neural sparse retrieval. + +* **Optimization behavior**: If the text fields in `field_map` are unchanged, the processor skips inference and reuses the existing sparse encoding. + +**Example pipeline**: + +```json +PUT /_ingest/pipeline/optimized-ingest-pipeline +{ + "description": "Optimized ingest pipeline", + "processors": [ + { + "sparse_encoding": { + "model_id": "", + "prune_type": "max_ratio", + "prune_ratio": "0.1", + "field_map": { + "text": "" + }, + "skip_existing": true + } + } + ] +} +``` + +## Performance results + +In addition to reducing compute costs, skipping redundant inference significantly lowers latency. The following benchmarks compare processor performance with and without the `skip_existing` optimization. + +### Test environment + +We used the following cluster setup to run benchmarking tests. + +![Cluster setup](/assets/media/blog-images/2025-05-15-optimized-inference-processors/cluster_setup.png) + + +### Text embedding processor + +* **Model**: `huggingface/sentence-transformers/msmarco-distilbert-base-tas-b` +* **Dataset**: [Trec-Covid](https://public.ukp.informatik.tu-darmstadt.de/thakur/BEIR/datasets/trec-covid.zip) + +**Sample requests** + +Single document: + +```json +PUT /test_index/_doc/1 +{ + "text": "Hello World" +} +``` + +Bulk update: + +```json +POST _bulk +{ "index": { "_index": "test_index" } } +{ "text": "hello world" } +{ "index": { "_index": "test_index" } } +{ "text": "Hi World" } +``` + +The following table presents the benchmarking test results for the `text_embedding` processor. + +| Operation type | Doc size | Batch size | Baseline (`skip_existing`=false) | Updated (`skip_existing`=true) | Δ vs. baseline | Unchanged (`skip_existing`=true) | Δ vs. baseline | +| -------------- | -------- | ---------- | ------------------------------- | ----------------------------- | -------------- | ------------------------------- | -------------- | +| Single update | 3,000 | 1 | 1,400,710 ms | 1,401,216 ms | +0.04% | 292,020 ms | -79.15% | +| Batch update | 171,332 | 200 | 2,247,191 ms | 2,192,883 ms | -2.42% | 352,767 ms | -84.30% | + +### Text/image embedding processor + +* **Model**: `amazon.titan-embed-image-v1` +* **Dataset**: [Flickr Image](https://www.kaggle.com/datasets/hsankesara/flickr-image-dataset) + +**Sample requests** + +Single document: + +```json +PUT /test_index/_doc/1 +{ + "text": "Orange table", + "image": "bGlkaHQtd29rfx43..." +} +``` + +Bulk update: + +```json +POST _bulk +{ "index": { "_index": "test_index" } } +{ "text": "Orange table", "image": "bGlkaHQtd29rfx43..." } +{ "index": { "_index": "test_index" } } +{ "text": "Red chair", "image": "aFlkaHQtd29rfx43..." } +``` + +The following table presents the benchmarking test results for the `text_image_embedding` processor. + +| Operation type | Doc size | Batch size | Baseline | Updated | Δ vs. baseline | Unchanged | Δ vs. baseline | +| -------------- | -------- | ---------- | ------------ | ------------ | -------------- | ------------ | -------------- | +| Single update | 3,000 | 1 | 1,060,339 ms | 1,060,785 ms | +0.04% | 465,771 ms | -56.07% | +| Batch update | 31,783 | 200 | 1,809,299 ms | 1,662,389 ms | -8.12% | 1,571,012 ms | -13.17% | + + +### Sparse encoding processor + +* **Model**: `huggingface/sentence-transformers/msmarco-distilbert-base-tas-b` +* **Dataset**: [Trec-Covid](https://public.ukp.informatik.tu-darmstadt.de/thakur/BEIR/datasets/trec-covid.zip) +* **Prune method**: `max_ratio`, **ratio**: `0.1` + +**Sample requests** + +Single document: + +```json +PUT /test_index/_doc/1 +{ + "text": "Hello World" +} +``` + +Bulk update: + +```json +POST _bulk +{ "index": { "_index": "test_index" } } +{ "text": "hello world" } +{ "index": { "_index": "test_index" } } +{ "text": "Hi World" } +``` + +The following table presents the benchmarking test results for the `sparse_encoding` processor. + +| Operation type | Doc size | Batch size | Baseline | Updated | Δ vs. baseline | Unchanged | Δ vs. baseline | +| -------------- | -------- | ---------- | ------------ | ------------ | -------------- | ---------- | -------------- | +| Single update | 3,000 | 1 | 1,942,907 ms | 1,965,918 ms | +1.18% | 306,766 ms | -84.21% | +| Batch update | 171,332 | 200 | 3,077,040 ms | 3,101,697 ms | +0.80% | 475,197 ms | -84.56% | + +## Conclusion + +As demonstrated by the cost and performance results, the `skip_existing` optimization significantly reduces redundant inference operations, which translates to lower costs and improved system performance. By reusing existing embeddings when input fields remain unchanged, ingest pipelines can process updates faster and more efficiently. This strategy improves system performance, enhances scalability, and delivers more cost-effective embedding retrieval at scale. + +## What's next + +If you use the Bulk API with ingest pipelines, it's important to understand how different operations behave. + +The Bulk API supports two operations---`index` and `update`: + +* The `index` operation replaces the entire document and **does** trigger ingest pipelines. +* The `update` operation modifies only the specified fields but **does not** currently trigger ingest pipelines. + +If you'd like to see ingest pipeline support added to the `update` operation in Bulk API requests, consider supporting [this GitHub issue](https://github.com/opensearch-project/OpenSearch/issues/17494) by adding a +1. + diff --git a/_posts/2025-05-19-journey-to-find-replacements-java-security-manager.md b/_posts/2025-05-19-journey-to-find-replacements-java-security-manager.md new file mode 100644 index 0000000000..00e1faf8c1 --- /dev/null +++ b/_posts/2025-05-19-journey-to-find-replacements-java-security-manager.md @@ -0,0 +1,134 @@ +--- +layout: post +title: "Finding a replacement for JSM in OpenSearch 3.0" +authors: + - cwperks + - kumargu + - kolchfa +date: 2025-05-19 +categories: + - technical-posts +meta_keywords: Opensearch security, Java security manager, OpenSearch 3.0, security, sandboxing. +meta_description: The Java Security Manager (JSM) has long been a foundational security mechanism in OpenSearch. With its deprecation underway, this blog post explores the alternative technologies adopted to replace JSM. +--- + +OpenSearch 3.0.0 introduced many innovative features that provide significant advancements in performance, data management, vector database functionality, and more. In [the release announcement](https://opensearch.org/blog/unveiling-opensearch-3-0/), we shared that OpenSearch has replaced the Java Security Manager (JSM) because of its upcoming deprecation. In this blog post, we share more information about the efforts that enabled this transition. + +The decision to remove JSM in 3.0 was carefully considered and primarily driven by two factors: + +1. **The upcoming removal of JSM from the Java platform**: JSM has been deprecated since JDK 17 ([JEP411](https://openjdk.org/jeps/411)) and is scheduled for full removal in JDK 24 ([JEP 486](https://openjdk.org/jeps/486)). According to the Java Enhancement Proposal (JEP), this decision was made because very few projects were using JSM. While OpenSearch 3.0 is bundled with Java 21 and not yet forced to drop JSM, continuing to rely on a deprecated and soon-to-be-removed component was deemed unsustainable for long-term support and innovation. + +2. **Incompatibility with emerging JVM features, particularly virtual threads**: Introduced in ([JEP 444](https://openjdk.org/jeps/444)), virtual threads are one of the most anticipated features in modern Java. While OpenSearch 3.0 does not use virtual threads internally, we expect plugin developers and future versions of OpenSearch to potentially use virtual threads for improved scalability. However, virtual threads do not carry permissions when a Security Manager is enabled, effectively rendering them incompatible with any JSM-based security model. Thus, continuing to support JSM would have prevented adoption of a key Java feature that unlocks better concurrency and resource efficiency. + +Given these needs, we decided to deprecate JSM in OpenSearch 3.0. Doing this in a major version allowed us to communicate the change clearly and avoid introducing breaking security changes in later 3.x minor releases. + + +In December 2021, an [issue](https://github.com/opensearch-project/OpenSearch/issues/1687) was created in the OpenSearch core repo to discuss options for a replacement. It soon became clear that there was no direct replacement for the functionality that JSM provided for Java programs. OpenSearch embarked on a lengthy search for a replacement that would retain critical JSM functionality. + +We considered many different options, including the following: + +1. Moving to [OpenSearch extensibility](https://opensearch.org/blog/technical-roadmap-opensearch-extensibility/) through out-of-process extensions (a radical change). +2. Replacing JVM with GraalVM. +3. Hardening security by using `systemd`. +4. Introducing a separate Java agent. +5. Completely removing JSM and related functionalities. + +## Understanding JSM's role in OpenSearch + +At its core, OpenSearch is a powerful search engine built on top of Apache Lucene. It provides a REST API layer for accessing documents stored in Lucene shards, along with built-in cluster management for running Lucene on nodes distributed across a cluster. OpenSearch has a pluggable architecture and a diverse set of plugins that extend the core functionality by offering additional features like security, observability, and index management. OpenSearch plugins run in the same JVM as the OpenSearch process but remain partially separated through separate class loading. OpenSearch does not treat plugins as secure by default; instead, it relies on JSM to sandbox plugins in order to prevent them from performing privileged actions without explicit cluster administrator approval. + +Two main user groups use JSM: plugin developers and cluster administrators. These groups use JSM in different ways. + +### How plugin developers use JSM + +To perform a privileged action, plugin developers must wrap the code that performs the action in an `AccessController.doPrivileged(() -> { ... })` block and grant the necessary permissions in the `plugin-security.policy` file. A common complaint about JSM is that plugin developers don't know what constitutes a `PrivilegedAction` until runtime. At runtime, they get an error saying that the plugin is forbidden from performing a given operation, for example, connecting to a socket or reading from the file system. JSM enforced a broad range of restrictions, from preventing calls to system operations like `System.exit` to other Java language features like reflection (for more information about the areas that JSM covered, see [Permissions and Security Policy](https://docs.oracle.com/javase/8/docs/technotes/guides/security/spec/security-spec.doc3.html)). + +Plugin developers use JSM by defining permissions in a policy file and implementing privileged actions in code: + +- The following example `plugin-security.policy` file defines the basic permissions needed for a plugin to operate: + + ```json + grant { + permission java.lang.RuntimePermission "shutdownHooks"; + permission java.lang.RuntimePermission "getClassLoader"; + permission java.lang.RuntimePermission "setContextClassLoader"; + permission java.util.PropertyPermission "*","read,write"; + } + ``` + +- The following is an example `AccessController.doPrivileged` block. In this example, `SpecialPermission.check()` is invoked before the call to `AccessController.doPrivileged(() -> { ... })`. In OpenSearch, the `org.opensearch.SpecialPermission` is granted to all JAR files, both the core and any installed plugins, at runtime. This permission serves as a safeguard against external code execution. If the call stack includes a source external to OpenSearch (for example, code originating from an API payload), the call to `SpecialPermission.check()` fails. This mechanism helps prevent untrusted code from performing privileged actions within the OpenSearch process: + + ```java + SpecialPermission.check(); + AccessController.doPrivileged((PrivilegedAction) () -> { + if (Security.getProvider("BC") == null) { + try { + Class providerClass = Class.forName("org.bouncycastle.jce.provider.BouncyCastleProvider"); + Provider provider = (Provider) providerClass.getDeclaredConstructor().newInstance(); + Security.addProvider(provider); + log.debug("Bouncy Castle Provider added"); + } catch (Exception e) { + log.debug("Bouncy Castle Provider could not be added", e); + } + } + return null; + }); + ``` + +### How cluster administrators use JSM + +Cluster administrators are prompted about permissions that a plugin requests at installation time. The following snippet from the Security plugin contains permissions that allow the plugin to perform actions like adding the `BouncyCastle` provider: + + ```console + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + @ WARNING: plugin requires additional permissions @ + @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ + * java.io.FilePermission /proc/sys/net/core/somaxconn#plus read + * java.lang.RuntimePermission accessDeclaredMembers + ``` + +## Our solution for replacing JSM + +Understanding the key JSM user interactions was crucial as we developed our replacement strategy. We needed solutions that would continue to support both plugin developers' need for privileged operations and administrators' ability to control permissions. + +After evaluating potential JSM replacement alternatives, it was clear that no single approach could replace all of the functionality that JSM provided. The OpenSearch community decided to replace JSM by adopting a two-pronged strategy: + +1. [`systemd` hardening](#systemd-hardening): Using operating system controls for protection. +2. [Java agent](#java-agent): Implementing low-level instrumentation to intercept and authorize privileged operations. + +### systemd hardening + +The first component of the replacement strategy was `systemd` hardening, which is available in Linux distributions that use `systemd` as the init system. This approach sandboxes the OpenSearch process using the following native operating system features: + +- **System call restriction**: Uses `seccomp` and the `SystemCallFilter` directive to restrict the kernel interfaces that the OpenSearch process can access. + +- **File system path isolation**: Configures `ReadOnlyPaths`, `ReadWritePaths`, and `InaccessiblePaths` to control access to critical system files and restrict write access to only necessary directories. + +- **Capability restrictions**: Applies `CapabilityBoundingSet` to block dangerous Linux capabilities, such as `CAP_SYS_ADMIN` or `CAP_NET_ADMIN`, that could be exploited by malicious code. + +- **Process containment**: Enables options such as `PrivateTmp`, `NoNewPrivileges`, and `ProtectSystem` to further reduce the risk of privilege escalation or file system tampering. + +This approach effectively protects the system from malicious plugins by constraining the actions that the OpenSearch process can perform. However, the drawback is that `systemd` rules are applied at the process level, not at the plugin level. This means that any privilege granted affects the entire OpenSearch process, resulting in an unsuitable replacement for the fine-grained, per-plugin control that JSM provided. + +### Java agent + +The second component of the replacement strategy was a custom Java agent. A Java agent is a special JAR that the JVM can load before application execution or attach during execution in order to view, transform, or monitor the bytecode of every class that the JVM loads. Internally, it relies on the Instrumentation API introduced in Java 5. A Java agent is attached to the OpenSearch process through the `-javaagent` Java argument. The OpenSearch Java agent is composed of interceptors that monitor privileged operations and ensure that the executing codebase has been explicitly granted the required permissions. The configuration for the Java agent remains consistent with JSM: the `plugin-security.policy` file defines the set of granted permissions and prompts the cluster administrator during plugin installation. + +OpenSearch's Java agent uses the ByteBuddy Instrumentation API to intercept and instrument Java bytecode at runtime. Specifically, the agent installs interceptors for privileged operations such as: + +- Opening or connecting sockets. + +- Creating, reading, or writing files. + +These interceptors inspect the current call stack to identify the originating code and then evaluate whether it has been granted the required permissions based on the existing `plugin-security.policy` file. This mirrors the existing JSM model, with minimal disruption for plugin developers and administrators. + +While the agent does not cover all permission types previously supported by JSM (for example, reflection and thread context access), it focuses on the most sensitive operations, such as file and network access, which pose the highest security risks. Other security controls are delegated to the operating system using `systemd`. The agent is also designed to be extensible, allowing for the addition of more interceptors as needed. + +We specifically chose to avoid over-instrumentation because of performance and maintainability concerns. Instrumenting every possible permission check would significantly decrease performance and require an excessive amount of repetitive code. + +## Final thoughts + +JSM deprecation is a significant turning point for the Java ecosystem and OpenSearch alike. While no single solution can fully replicate the functionality that JSM provided, OpenSearch's two-pronged approach---using operating-system-level protections through `systemd` and introducing a lightweight Java agent for plugin-level access control---provides a robust and extensible foundation for securing the platform. + +This approach ensures that OpenSearch remains secure, performant, and compatible with the evolving Java ecosystem while retaining the extensibility and plugin ecosystem that users rely on. + diff --git a/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/OpenSearch_latency_performance.png b/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/OpenSearch_latency_performance.png new file mode 100644 index 0000000000..695a242079 Binary files /dev/null and b/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/OpenSearch_latency_performance.png differ diff --git a/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/cold-start-query.png b/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/cold-start-query.png new file mode 100644 index 0000000000..d5ef62aa7b Binary files /dev/null and b/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/cold-start-query.png differ diff --git a/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/force-merge.png b/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/force-merge.png new file mode 100644 index 0000000000..9594544cd0 Binary files /dev/null and b/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/force-merge.png differ diff --git a/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/vector-search-store.png b/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/vector-search-store.png new file mode 100644 index 0000000000..28c279f48d Binary files /dev/null and b/assets/media/blog-images/2025-05-08-opensearch-performance-3.0/vector-search-store.png differ diff --git a/assets/media/blog-images/2025-05-15-optimized-inference-processors/cluster_setup.png b/assets/media/blog-images/2025-05-15-optimized-inference-processors/cluster_setup.png new file mode 100644 index 0000000000..25ec6c0e1e Binary files /dev/null and b/assets/media/blog-images/2025-05-15-optimized-inference-processors/cluster_setup.png differ diff --git a/assets/media/blog-images/2025-05-15-optimized-inference-processors/diagram.png b/assets/media/blog-images/2025-05-15-optimized-inference-processors/diagram.png new file mode 100644 index 0000000000..275dfb357e Binary files /dev/null and b/assets/media/blog-images/2025-05-15-optimized-inference-processors/diagram.png differ diff --git a/assets/media/community/members/san81.jpg b/assets/media/community/members/san81.jpg new file mode 100644 index 0000000000..0b6756a1f0 Binary files /dev/null and b/assets/media/community/members/san81.jpg differ diff --git a/assets/media/community/members/will-hwang.jpg b/assets/media/community/members/will-hwang.jpg new file mode 100644 index 0000000000..5e03162e79 Binary files /dev/null and b/assets/media/community/members/will-hwang.jpg differ