<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Kiran U Kamath</title>
    <description>The latest articles on DEV Community by Kiran U Kamath (@kiranukamath).</description>
    <link>https://dev.to/kiranukamath</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F283777%2F8759e3d5-62d8-462d-aaeb-316e049010e5.jpg</url>
      <title>DEV Community: Kiran U Kamath</title>
      <link>https://dev.to/kiranukamath</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/kiranukamath"/>
    <language>en</language>
    <item>
      <title>DNS Resolver: The Unsung Hero of the Internet</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Tue, 08 Oct 2024 04:37:00 +0000</pubDate>
      <link>https://dev.to/kiranukamath/dns-resolver-the-unsung-hero-of-the-internet-48ap</link>
      <guid>https://dev.to/kiranukamath/dns-resolver-the-unsung-hero-of-the-internet-48ap</guid>
      <description>&lt;p&gt;We use the internet every day without even thinking about the gears turning behind the scenes. One of those crucial gears is the DNS resolver—the behind-the-curtain magician that converts those easy-to-remember domain names (like example.com) into IP addresses that computers need to communicate.&lt;/p&gt;

&lt;p&gt;But what is a DNS resolver, how does it work, and why should you care? Let's break this down, layer by layer, into a comprehensive yet digestible explanation. Buckle up, because we're about to get into the workings of the internet!&lt;/p&gt;

&lt;h2&gt;
  
  
  What Exactly is a DNS Resolver?
&lt;/h2&gt;

&lt;p&gt;At its core, a DNS resolver is a specialized server that processes DNS queries from clients (like your web browser or an application).&lt;/p&gt;

&lt;p&gt;When you type in a domain name like example.com, your computer doesn’t magically know how to find it on the web. It relies on the DNS resolver to figure out what IP address corresponds to that domain, much like how a phone book helps you find someone’s number based on their name.&lt;/p&gt;

&lt;p&gt;The resolver is often provided by your ISP (Internet Service Provider), but there are many third-party services, such as Google DNS (8.8.8.8), Cloudflare DNS (1.1.1.1), and OpenDNS (208.67.222.222), which offer enhanced speed, privacy, and security features.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two Types of DNS Resolvers
&lt;/h2&gt;

&lt;p&gt;Before diving into the nuts and bolts, let’s clarify the two primary types of DNS resolvers:&lt;/p&gt;

&lt;p&gt;Stub Resolver: This lives on your local machine (or within an application). It sends DNS queries to the recursive resolver and waits for a response. Its job is simple—start the process and display the result.&lt;/p&gt;

&lt;p&gt;Recursive Resolver: This is where the magic happens. It takes the query from the stub resolver and performs the heavy lifting, often making multiple requests to various DNS servers to resolve the domain name to an IP address.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Full DNS Resolution Journey
&lt;/h2&gt;

&lt;p&gt;Let's walk through what happens behind the scenes when you type &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt; into your browser and hit enter.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 1: Local Cache Check
&lt;/h3&gt;

&lt;p&gt;The first stop for the DNS resolution journey is your own machine's cache. Modern operating systems cache DNS records for a while to avoid unnecessary network trips. If you’ve recently visited example.com, there’s a chance the IP address is already sitting in your local DNS cache, and the process ends right here. No need to bother the DNS resolver.&lt;/p&gt;

&lt;p&gt;But let’s assume the IP address isn’t cached. Your machine now sends the query to a recursive resolver.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 2: Recursive Resolver: The Mastermind
&lt;/h3&gt;

&lt;p&gt;Now, the recursive resolver steps in. This resolver acts as a middleman, tasked with finding the right IP address for the domain name. To do that, it might have to talk to several other servers, which we’ll go over next. It could have cached the response from previous queries, but if it doesn't, the resolver begins its journey through the DNS hierarchy.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 3: Query to the Root Servers
&lt;/h3&gt;

&lt;p&gt;If the resolver has never encountered example.com, it first asks one of the root DNS servers. These root servers are a vital part of the internet’s infrastructure, operating globally at 13 key locations. There are 13 root servers (named from A to M). While there are 13 named root servers, each of these actually exists as hundreds of physical instances distributed globally using Anycast technology.&lt;/p&gt;

&lt;p&gt;Their job isn’t to know the IP address for example.com directly, but they can point the resolver in the right direction, typically by directing it to the appropriate Top-Level Domain (TLD) DNS servers.&lt;/p&gt;

&lt;p&gt;In the case of example.com, the root server will go to the .com TLD servers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 4: Query to the TLD DNS Servers
&lt;/h3&gt;

&lt;p&gt;Next, the recursive resolver queries the TLD DNS servers. For example.com, the resolver heads over to the .com DNS servers. This server doesn’t return the final IP address, but it provides a referral to the authoritative domain name servers for example.com.”&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 5: Query to Authoritative DNS Servers
&lt;/h3&gt;

&lt;p&gt;Finally, the recursive resolver reaches out to the authoritative DNS servers for the example.com domain. These servers hold the DNS records (such as A, AAAA, CNAME, etc.) for the domain and can give the exact IP address. The authoritative server looks up its records and responds with the requested IP address for the domain.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 6: Caching and Returning the Answer
&lt;/h3&gt;

&lt;p&gt;The recursive resolver now knows the answer, but it’s smart about things. Instead of repeating this process for every query, it caches the IP address and stores it for a set period (determined by the Time-To-Live (TTL) of the DNS record). This caching helps reduce the load on DNS infrastructure and speeds up subsequent lookups.&lt;/p&gt;

&lt;p&gt;Finally, the resolver sends the answer back to the stub resolver on the client machine, and browser can now load the website by connecting to 93.184.215.14.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
Try running below command on Terminal
dig @1.1.1.1 www.example.com A

you will get ip address of example.com

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  DNS Query Types
&lt;/h2&gt;

&lt;p&gt;Throughout the resolution process, different &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A (Address) Record: Returns the IPv4 address of the domain.&lt;/li&gt;
&lt;li&gt;AAAA Record: Returns the IPv6 address of the domain.&lt;/li&gt;
&lt;li&gt;CNAME (Canonical Name) Record: Returns an alias for another domain.&lt;/li&gt;
&lt;li&gt;MX (Mail Exchange) Record: Returns the mail server responsible for receiving emails for the domain.&lt;/li&gt;
&lt;li&gt;TXT Record: Provides additional text information, often used for verification or security purposes (e.g., SPF records).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Example: CNAME Resolution&lt;/p&gt;

&lt;p&gt;Let’s take an example of a CNAME resolution. If blog.example.com is an alias for &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt;, a query for blog.example.com will first return the CNAME record, which points to &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt;. The resolver will then make another query for &lt;a href="http://www.example.com" rel="noopener noreferrer"&gt;www.example.com&lt;/a&gt; to get the actual IP address.&lt;/p&gt;

&lt;h2&gt;
  
  
  DNS Resolver Caching: The Speed Booster
&lt;/h2&gt;

&lt;p&gt;Caching is crucial for DNS resolvers, especially for performance. Imagine if every single DNS query had to go through all these steps—we’d all be waiting a lot longer for our websites to load.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Local Machine Cache: Your device’s operating system caches DNS responses.&lt;/li&gt;
&lt;li&gt;Recursive Resolver Cache: The DNS resolver caches results to reduce the need for repeated queries to authoritative DNS servers.&lt;/li&gt;
&lt;li&gt;Browser Cache: Some modern browsers even perform DNS caching internally to make browsing faster.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cache Expiry: TTL (Time-To-Live)
&lt;/h3&gt;

&lt;p&gt;The duration for which a DNS record is cached is governed by the &lt;/p&gt;

&lt;h2&gt;
  
  
  Real-Life Example of TTL Impact
&lt;/h2&gt;

&lt;p&gt;Let’s say you run a website and recently migrated to a new server with a different IP address. If you’ve set a long TTL (e.g., 24 hours), some users might still be routed to the old server until the TTL expires and the new IP address propagates through the DNS system. On the other hand, a short TTL (e.g., 5 minutes) allows changes to propagate more quickly but at the cost of increased DNS query volume&lt;/p&gt;

&lt;h2&gt;
  
  
  DNS Security and Extensions
&lt;/h2&gt;

&lt;p&gt;DNSSEC (DNS Security Extensions): DNSSEC is a suite of security protocols that provide authenticity and integrity to DNS data, ensuring that the information returned during DNS resolution has not been tampered with. DNSSEC uses digital signatures to verify the authenticity of the DNS records.&lt;/p&gt;

&lt;p&gt;DoH (DNS over HTTPS) and DoT (DNS over TLS): To enhance user privacy and security, DNS queries can be encrypted using DoH or DoT. These protocols prevent eavesdropping and man-in-the-middle attacks by encrypting DNS queries between the client and the recursive resolver.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: Why You Should Care
&lt;/h2&gt;

&lt;p&gt;The DNS resolver may seem like an obscure part of the internet’s plumbing, but without it, the web as we know it wouldn’t function. From converting domain names to IP addresses, handling various DNS record types, caching responses for faster browsing, to securing the resolution process with DNSSEC, the resolver does a lot more than meets the eye.&lt;/p&gt;

&lt;p&gt;As a software engineer, understanding how DNS resolution works gives an edge in diagnosing network issues, optimizing performance, and ensuring that your systems and applications run efficiently.&lt;/p&gt;

&lt;p&gt;So, the next time you browse the web, remember: DNS resolvers are the silent heroes that make it all possible.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Maximizing Redis Efficiency: Cutting Memory Costs with Redis Hashes</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Tue, 08 Oct 2024 04:30:00 +0000</pubDate>
      <link>https://dev.to/kiranukamath/maximizing-redis-efficiency-cutting-memory-costs-with-redis-hashes-1b7g</link>
      <guid>https://dev.to/kiranukamath/maximizing-redis-efficiency-cutting-memory-costs-with-redis-hashes-1b7g</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsb5spepqu8c4z6xtaq4i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fsb5spepqu8c4z6xtaq4i.png" alt="Image description" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In-memory databases like Redis are known for their speed and efficiency, but their memory-centric design makes memory usage a critical factor when scaling an application. As applications grow, developers need to consider memory optimization strategies to keep costs low and performance high.&lt;/p&gt;

&lt;p&gt;Redis Hashes are highly useful when you have multiple related fields associated with a single entity. Instead of creating multiple individual keys for each field, you can consolidate them into a single key as a hash with multiple fields.&lt;/p&gt;

&lt;p&gt;This blog explores how Redis Hashes save memory, reduce infrastructure costs, when use case is of have multiple related fields associated with a single entity.&lt;/p&gt;

&lt;h2&gt;
  
  
  Redis: A Memory-Centric Database
&lt;/h2&gt;

&lt;p&gt;Redis stores all its data in memory, making it incredibly fast but also sensitive to memory consumption. Efficient memory usage directly impacts the performance and cost of a Redis instance, especially in high-scale systems where millions of keys may be managed.&lt;/p&gt;

&lt;p&gt;Every key stored in Redis incurs memory overhead, typically around 40 bytes per key which is primarily attributed to - Key management, Pointers , Hash table buckets. When dealing with a massive number of keys, this overhead can quickly add up, leading to higher memory costs. For systems that require significant scaling, optimizing memory becomes crucial, and Redis provides several data structures to facilitate this, including Hashes, Sets, and Lists.&lt;/p&gt;

&lt;p&gt;What is Redis Hashes ?&lt;/p&gt;

&lt;p&gt;A Redis Hash is a key-value data structure where each Redis key contains a field-value pair, similar to how a dictionary works in programming languages. Unlike storing each field as a separate Redis key, multiple fields can be stored under one key.&lt;/p&gt;

&lt;p&gt;`Example:&lt;/p&gt;

&lt;p&gt;Plain Key-Value:&lt;/p&gt;

&lt;p&gt;User:123:Name -&amp;gt; "John"&lt;br&gt;&lt;br&gt;
User:123:Age -&amp;gt; "30"&lt;/p&gt;

&lt;p&gt;Using Redis Hash:&lt;/p&gt;

&lt;p&gt;User:123 -&amp;gt; &lt;br&gt;
{ Name: "John", &lt;br&gt;
Age: "30" }`&lt;/p&gt;

&lt;p&gt;With a hash, we store related fields (such as name and age) within a single Redis key, effectively reducing the number of keys and thus, the overhead incurred.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Redis Hashes Instead of Plain Key-Value Pairs?
&lt;/h2&gt;

&lt;p&gt;Now that we understand the basics, let’s dig deeper into why Redis Hashes are so effective for memory optimization.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Reduced Memory Overhead&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The memory overhead of managing individual keys adds up quickly in Redis. By combining related fields into a single Redis Hash, you significantly reduce the number of keys in your dataset. This directly reduces the 40-byte overhead per key.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Ziplist Compression&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Redis Hashes are stored as ziplists when they contain fewer than a configurable number of fields (default 512). Ziplists are optimized for memory efficiency, as they store data in a contiguous block of memory, avoiding the overhead of pointers and metadata associated with each field.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Better Memory Management in Large Scale Systems&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;In systems where you might have hundreds of millions of key-value pairs, Redis Hashes allow you to organize and compress data more effectively. By reducing the number of keys, Redis spends less time resizing its hash tables, which improves performance and reduces memory fragmentation. Redis hash tables grow and shrink dynamically, and with fewer keys, Redis avoids frequent resizing operations.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Cost Savings&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;One of the most compelling benefits of using Redis Hashes is the cost savings.&lt;br&gt;
Let’s take a real-world example: consider an application with millions of users where each user’s activity is tracked in Redis. If you store each piece of user data as a separate Redis key, the memory overhead grows rapidly. However, by switching to Redis Hashes, you could reduce memory consumption significantly—by as much as 60%, depending on the dataset.&lt;/p&gt;

&lt;p&gt;This means you can run your Redis instance on smaller, less expensive hardware or reduce your cloud infrastructure costs. Memory optimization through Redis Hashes can lead to massive cost savings over time, especially at scale.&lt;/p&gt;

&lt;h2&gt;
  
  
  Challenges of Using Redis Hashes
&lt;/h2&gt;

&lt;p&gt;While Redis Hashes offer significant memory optimization benefits, there are a few challenges to be aware of:&lt;/p&gt;

&lt;p&gt;Memory Usage for Large Hashes&lt;/p&gt;

&lt;p&gt;If a hash grows beyond the hash-max-ziplist-entries threshold, Redis will convert the ziplist to a traditional hash table, which incurs more memory overhead. While this is generally acceptable for larger datasets, it’s important to monitor hash sizes and adjust the hash-max-ziplist-entries setting accordingly to balance memory efficiency and performance.&lt;/p&gt;

&lt;p&gt;Granular TTL&lt;/p&gt;

&lt;p&gt;In Redis version before 7, Redis Hashes did not support individual TTLs for fields inside the hash. You can only set an expiration time for the entire hash key, meaning that if one field needs to expire sooner than the others, you cannot achieve that with Redis hashes alone. New in Redis Community Edition 7.4 is the ability to specify an expiration time or a time-to-live (TTL) value for individual hash fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use Case: Real-Time Analytics in Gaming Leaderboards
&lt;/h2&gt;

&lt;p&gt;Consider an online gaming platform that tracks players' scores across multiple games. Initially, you might store each player's score for each game as a separate key:&lt;/p&gt;

&lt;p&gt;Player:123:Game:567:Score -&amp;gt; 100&lt;br&gt;
Player:123:Game:890:Score -&amp;gt; 150&lt;/p&gt;

&lt;p&gt;In this scenario, as more players engage with more games, the number of keys in Redis rapidly grows, leading to high memory overhead and management complexity. This explosion of keys makes Redis inefficient as it needs to handle a large number of keys, increasing lookup times and memory usage due to the metadata overhead associated with each key.&lt;/p&gt;

&lt;p&gt;Optimization with Redis Hashes:&lt;/p&gt;

&lt;p&gt;To optimize this, you can store scores in a Redis Hash where the player ID is the key, and the game IDs with their respective scores are stored as fields within the hash:&lt;/p&gt;

&lt;p&gt;Player:123 -&amp;gt; {Game:567 -&amp;gt; 100, Game:890 -&amp;gt; 150}&lt;/p&gt;

&lt;p&gt;This approach significantly reduces the number of keys, minimizing memory consumption. Instead of maintaining a separate key for each player-game combination, Redis handles just one key per player, with game-specific scores stored inside the hash.&lt;/p&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;p&gt;Memory Efficiency: You reduce the memory overhead by collapsing multiple keys into one, avoiding the 40-byte per key overhead associated with Redis key management.&lt;/p&gt;

&lt;p&gt;Faster Retrieval: All game scores for a player can be retrieved in one go, improving performance for leaderboard queries or score lookups.&lt;/p&gt;

&lt;p&gt;Reduced Complexity: Managing scores for millions of players and thousands of games becomes more manageable, with fewer keys to handle during data replication or backup processes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Switching from plain key-value pairs to Redis Hashes is one of the most powerful and effective strategies for optimizing memory usage in Redis. By consolidating multiple related key-value pairs into a single hash, you significantly reduce the number of individual keys in the database, which in turn minimizes overhead and improves overall memory efficiency. Redis also applies additional memory optimizations, such as ziplist compression for small hashes, allowing you to further conserve space.&lt;/p&gt;

&lt;p&gt;In large-scale applications where millions of keys are being managed or where high interaction rates are the norm, these optimizations can lead to substantial reductions in memory consumption. This not only results in better system performance but also mitigates memory fragmentation, which can degrade performance over time. More importantly, by lowering memory usage, Redis Hashes enable significant reductions in infrastructure costs, allowing you to achieve greater efficiency with the same hardware or cloud resources.&lt;/p&gt;

&lt;p&gt;When used properly, Redis Hashes provide an excellent tool for managing complex datasets efficiently. By grouping related data under a single key, you not only simplify your data model but also ensure that Redis performs optimally even under heavy load. This approach is particularly valuable in memory-constrained environments, or in scenarios where optimizing for cost is a priority.&lt;/p&gt;

&lt;p&gt;Ultimately, organizations that adopt Redis Hashes can expect to reduce infrastructure expenses while improving the responsiveness and scalability of their Redis clusters—making it a smart choice for any high-demand, data-intensive application.&lt;/p&gt;

</description>
      <category>redis</category>
    </item>
    <item>
      <title>Understanding hashCode() and equals() in Java</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Mon, 07 Oct 2024 04:33:00 +0000</pubDate>
      <link>https://dev.to/kiranukamath/understanding-hashcode-and-equals-in-java-4imi</link>
      <guid>https://dev.to/kiranukamath/understanding-hashcode-and-equals-in-java-4imi</guid>
      <description>&lt;p&gt;Java’s hashCode() and equals() methods are fundamental to the functioning of many core Java classes, particularly those in the Collections framework, such as HashMap, HashSet, and Hashtable. These methods define how Java objects behave when stored in collections that use hashing for efficient retrieval.&lt;/p&gt;

&lt;p&gt;In this blog, we’ll dive deep into how these methods work, the rationale behind them, and their impact on performance. We’ll also look at the relationship between hashCode() and equals(), explore best practices, and investigate a real-world example with Java's String class.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overview of hashCode() and equals()
&lt;/h2&gt;

&lt;p&gt;In Java, objects are often stored in collections such as HashMap or HashSet, which use hashing for efficient access and storage. For these collections to work as expected, the objects need to adhere to certain rules regarding equality (equals()) and hashing (hashCode()).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hashCode(): This method returns an integer hash code, which is used by hash-based collections to determine the "bucket" where an object should be placed.&lt;/li&gt;
&lt;li&gt;equals(): This method checks if two objects are meaningfully equal. It compares their internal state to determine if they represent the same logical entity.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The correct implementation of these methods ensures that objects can be retrieved efficiently from collections and behave correctly when compared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deep Dive into hashCode()
&lt;/h2&gt;

&lt;h3&gt;
  
  
  What is a Hash Code?
&lt;/h3&gt;

&lt;p&gt;A hash code is a numerical value generated for an object. It serves as a compact representation of the object’s contents. Hash codes are particularly useful for storing objects in hash-based collections (like HashMap, HashSet, and Hashtable) because they allow these collections to quickly find an object in a large dataset by using the hash code to determine the storage location (bucket).&lt;/p&gt;

&lt;h3&gt;
  
  
  How hashCode() Works
&lt;/h3&gt;

&lt;p&gt;The hashCode() method is defined in Java’s Object class and can be overridden to provide custom hash codes for objects. Here’s the method signature:&lt;/p&gt;

&lt;p&gt;public int hashCode();&lt;/p&gt;

&lt;p&gt;When you insert an object into a hash-based collection, the collection first calls the object’s hashCode() method to get its hash code. This hash code is then used to find the correct bucket where the object should be stored.&lt;/p&gt;

&lt;p&gt;But what happens if two objects have the same hash code? This is called a hash collision, and it’s something we’ll explore in more depth later. For now, the important takeaway is that two objects with the same hash code may be stored in the same bucket, and the collection will use equals() to differentiate between them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Overriding hashCode()
&lt;/h2&gt;

&lt;p&gt;Here’s an example of how you can override&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
public class Person {
    private String name;
    private int age;

    @Override
    public int hashCode() {
        int result = 17;  // Start with a non-zero constant
        result = 31 * result + name.hashCode();  // Combine fields
        result = 31 * result + age;
        return result;
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Example of Hash Code Calculation:
&lt;/h2&gt;

&lt;p&gt;Let's consider the string &lt;/p&gt;

&lt;p&gt;String str = "abc"; &lt;br&gt;
System.out.println(str.hashCode());&lt;/p&gt;

&lt;p&gt;The hash code is calculated as follows:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;For the first character 'a' (ASCII 97): h = 31 * 0 + 97 = 97&lt;/li&gt;
&lt;li&gt;For the second character 'b' (ASCII 98): h = 31 * 97 + 98 = 3105&lt;/li&gt;
&lt;li&gt;For the third character 'c' (ASCII 99): h = 31 * 3105 + 99 = 96354&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, the hash code for "abc" is 96354.&lt;/p&gt;
&lt;h2&gt;
  
  
  The Role of Prime Numbers in hashCode()
&lt;/h2&gt;

&lt;p&gt;You might have seen prime numbers like 31 commonly used in hash code calculations (e.g., 31 * h + val[i]). This is not arbitrary—prime numbers help reduce the likelihood of hash collisions. By multiplying intermediate hash values by a prime number, you distribute the hash values more evenly across possible buckets, ensuring better performance for hash-based collections.&lt;/p&gt;

&lt;p&gt;Prime numbers ensure that hash codes are distributed more uniformly because their factors are less predictable, reducing the likelihood that different combinations of object fields will produce the same hash code.&lt;/p&gt;
&lt;h2&gt;
  
  
  Hash Collisions and Buckets
&lt;/h2&gt;

&lt;p&gt;A hash collision occurs when two different objects return the same hash code. When this happens, both objects are stored in the same bucket, but they still need to be distinguishable. This is where the equals() method comes into play.&lt;/p&gt;

&lt;p&gt;In a HashMap, for instance, if two objects have the same hash code, they will be placed in the same bucket. However, the collection will then use equals() to check if the objects are truly equal. If they are, the collection considers them duplicates; if not, both objects are stored in the same bucket but treated as distinct elements.&lt;/p&gt;
&lt;h2&gt;
  
  
  Deep Dive into equals()
&lt;/h2&gt;
&lt;h3&gt;
  
  
  What is Equality?
&lt;/h3&gt;

&lt;p&gt;In Java, the equals() method defines logical equality between two objects. It is used to determine whether two objects represent the same logical entity, even if they are different instances.&lt;/p&gt;

&lt;p&gt;Here’s the method signature of equals():&lt;/p&gt;

&lt;p&gt;public boolean equals(Object obj);&lt;/p&gt;

&lt;p&gt;The default implementation of equals() in the Object class compares object references using ==, which checks for reference equality—i.e., whether two objects point to the same memory location. However, this default behavior is not suitable for most applications, where you want to compare the actual contents or values of objects, not just their memory addresses.&lt;/p&gt;
&lt;h3&gt;
  
  
  Overriding equals()
&lt;/h3&gt;

&lt;p&gt;Here’s an example of how you might override equals() in a custom class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
public class Person {
    private String name;
    private int age;

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Person person = (Person) obj;
        return age == person.age &amp;amp;&amp;amp; name.equals(person.name);
    }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The Contract Between equals() and hashCode()
&lt;/h2&gt;

&lt;p&gt;There is an important contract between &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;If two objects are equal according to equals(), they must have the same hash code.&lt;/li&gt;
&lt;li&gt;If two objects are not equal, they can have the same or different hash codes (hash collisions).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hash-based collections rely on this contract to function properly. If two equal objects have different hash codes, they might be stored in different buckets, causing the collection to behave incorrectly (e.g., failing to retrieve an object or incorrectly treating two objects as distinct).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reflexive: For any non-null object x, x.equals(x) must return true.&lt;/li&gt;
&lt;li&gt;Symmetric: For any non-null objects x and y, if x.equals(y) returns true, then y.equals(x) must also return true.&lt;/li&gt;
&lt;li&gt;Transitive: For any non-null objects x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) must also return true.&lt;/li&gt;
&lt;li&gt;Consistent: For any non-null objects x and y, repeated calls to x.equals(y) must consistently return true or false, provided no information used in equals() comparisons is modified.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The Importance of hashCode() and equals() in Collections
&lt;/h2&gt;

&lt;p&gt;In hash-based collections like HashMap, HashSet, and Hashtable, the hashCode() and equals() methods are used together to store and retrieve elements.&lt;/p&gt;

&lt;h3&gt;
  
  
  Insertion in a HashMap:
&lt;/h3&gt;

&lt;p&gt;Hashing: The hashCode() method is called on the key to determine the bucket (array index) where the object should be placed.&lt;/p&gt;

&lt;p&gt;Equality Check: If another object already exists in the bucket (due to a hash collision), the equals() method is used to check if the two objects are equal. If they are equal, the existing value is replaced with the new one; otherwise, the new object is stored in the same bucket using techniques like chaining or probing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Retrieval from a HashMap:
&lt;/h3&gt;

&lt;p&gt;When retrieving a value from a HashMap using a key:&lt;/p&gt;

&lt;p&gt;Hashing: The hashCode() of the key is used to find the correct bucket.&lt;/p&gt;

&lt;p&gt;Equality Check: The equals() method is used to identify the correct key-value pair within the bucket (if multiple objects are stored due to hash collisions).&lt;/p&gt;

&lt;h3&gt;
  
  
  Impact of Incorrect Implementation:
&lt;/h3&gt;

&lt;p&gt;If equals() is overridden without hashCode(), hash-based collections might not work correctly. Two objects that are equal according to equals() could end up in different buckets because their hash codes differ.&lt;/p&gt;

&lt;p&gt;If hashCode() is poorly implemented, you might experience frequent hash collisions, leading to performance degradation in collections like HashMap.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common Mistakes and Best Practices:
&lt;/h2&gt;

&lt;p&gt;Always Override hashCode() When Overriding equals():&lt;/p&gt;

&lt;p&gt;Ensure that equal objects have the same hash code.&lt;/p&gt;

&lt;p&gt;Failing to override hashCode() when overriding equals() violates the contract between the two methods and can lead to bugs in collections.&lt;/p&gt;

&lt;p&gt;Use Immutable Fields&lt;/p&gt;

&lt;p&gt;It’s a good practice to use immutable fields (e.g., final fields) in hashCode() and equals() to prevent the state of an object from changing after it’s been inserted into a collection.&lt;/p&gt;

&lt;p&gt;If the fields that equals() and hashCode() rely on can be modified, the object’s behavior in hash-based collections may become unpredictable.&lt;/p&gt;

&lt;p&gt;Use Prime Numbers for Hashing&lt;/p&gt;

&lt;p&gt;Prime numbers like 31 are commonly used in hash functions because they help distribute hash values more uniformly across the hash table, reducing collisions.&lt;/p&gt;

&lt;p&gt;Avoid Using Floating-Point Numbers&lt;/p&gt;

&lt;p&gt;Using float or double in hashCode() can be tricky due to precision issues. If you must include them, consider converting them to int using Float.floatToIntBits() or Double.doubleToLongBits().&lt;/p&gt;

&lt;p&gt;Caching Hash Codes for Immutable Objects&lt;/p&gt;

&lt;p&gt;If an object is immutable (like String), you can cache its hash code to avoid recomputation, improving performance. This is done in the String class, where the hashCode is computed once and stored for future use.&lt;/p&gt;

&lt;h2&gt;
  
  
  String Class implementation
&lt;/h2&gt;

&lt;p&gt;In Java, String is a class that represents a sequence of characters.&lt;/p&gt;

&lt;p&gt;Implementation of equals() in String&lt;/p&gt;

&lt;p&gt;Here’s the implementation of the equals() method in the String class:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
public boolean equals(Object anObject) {
    if (this == anObject) {
        return true;
    }
    if (anObject instanceof String) {
        String anotherString = (String) anObject;
        int n = value.length;
        if (n == anotherString.value.length) {
            char v1[] = value;
            char v2[] = anotherString.value;
            int i = 0;
            while (n-- != 0) {
                if (v1[i] != v2[i])
                    return false;
                i++;
            }
            return true;
        }
    }
    return false;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breakdown of equals() Logic:&lt;/p&gt;

&lt;p&gt;Reference Check: The method first checks if the two references (this and anObject) point to the same object (this == anObject). If true, they are considered equal, and the method returns true.&lt;/p&gt;

&lt;p&gt;Type Check: If the two objects are not the same reference, the method checks whether anObject is an instance of String. If not, false is returned.&lt;/p&gt;

&lt;p&gt;Length Check: If both objects are strings, their lengths are compared. If the lengths differ, the strings cannot be equal, and the method returns false.&lt;/p&gt;

&lt;p&gt;Content Comparison: If the lengths are the same, the method compares the individual characters of the two strings. If any character differs, false is returned. If all characters match, true is returned, indicating that the strings are equal.&lt;/p&gt;

&lt;p&gt;This implementation ensures that two strings are considered equal if and only if they contain the exact same sequence of characters in the same order.&lt;/p&gt;

&lt;p&gt;Implementation of hashCode() in String&lt;/p&gt;

&lt;p&gt;Here’s the actual implementation of&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
public int hashCode() {
    int h = hash;
    if (h == 0 &amp;amp;&amp;amp; value.length &amp;gt; 0) {
        char val[] = value;

        for (int i = 0; i &amp;lt; value.length; i++) {
            h = 31 * h + val[i];
        }
        hash = h;
    }
    return h;
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Breakdown of hashCode() Logic:&lt;/p&gt;

&lt;p&gt;Cached Hash Code: The String class caches the hash code once it has been calculated. The variable hash is used to store the hash code, and the method first checks if hash is already set (h == 0). If it’s non-zero, the method returns the cached hash code.&lt;/p&gt;

&lt;p&gt;Hash Calculation: If the hash code hasn’t been calculated yet, the method iterates over the characters in the string (char val[] = value). For each character, the current hash is multiplied by 31 and added to the character’s value (h = 31 * h + val[i]). This results in a final hash code that represents the string.&lt;/p&gt;

&lt;p&gt;Return Value: Once the hash code is computed, it is cached in the hash variable and returned.&lt;/p&gt;

&lt;p&gt;Thanks for reading Kiran’s Blog! Subscribe for free to receive new posts and support my work.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Understanding Git Rebase</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Sun, 06 Oct 2024 04:30:00 +0000</pubDate>
      <link>https://dev.to/kiranukamath/understanding-git-rebase-9ca</link>
      <guid>https://dev.to/kiranukamath/understanding-git-rebase-9ca</guid>
      <description>&lt;p&gt;In the world of version control, Git rebase stands as one of the most powerful yet often misunderstood tools. Especially for developers like us, working on collaborative projects, mastering git rebase can transform how we manage code history, resolve conflicts, and maintain clean, linear commit histories.&lt;/p&gt;

&lt;p&gt;However, it's equally known for being dangerous when used incorrectly, as it involves rewriting history. This guide explores all facets of git rebase, including real-world scenarios, practical command-line examples, and why it can be both powerful and hazardous.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Git Rebase?
&lt;/h2&gt;

&lt;p&gt;Git rebase allows you to move or "reapply" commits from one branch on top of another. This operation rewrites the commit history in the process. When working with multiple collaborators, rebase offers a way to synchronize the local work with the upstream repository cleanly.&lt;/p&gt;

&lt;p&gt;In a typical git pull operation, the default merge strategy creates a new "merge commit" to combine changes. In contrast, rebase moves your changes onto the tip of another branch, creating a linear history and avoiding merge commits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Points:
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Rewriting History: Rebase changes the commit history.&lt;/li&gt;
&lt;li&gt;Commit Cherry-picking: It picks commits from one branch and replays them on another.&lt;/li&gt;
&lt;li&gt;Linear History: This is the primary advantage—simplifying the history by removing unnecessary merge commits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Why is it everyone think Git Rebase is Dangerous?
&lt;/h2&gt;

&lt;p&gt;The primary danger of git rebase comes from the fact that it rewrites commit history. Once history is rewritten and pushed to a shared repository, it can lead to confusion, lost commits, or merge conflicts for others working on the same branch.&lt;/p&gt;

&lt;p&gt;A few important points:&lt;/p&gt;

&lt;p&gt;Changes Commit IDs: Each commit gets a new hash, so any reference to old commit IDs will be broken.&lt;/p&gt;

&lt;p&gt;Pushing After Rebase Can Break Shared Repos: If you push after rebasing a branch that others have already pulled, their version of the branch will conflict with the rewritten history.&lt;/p&gt;

&lt;p&gt;Losing Uncommitted Work: If conflicts are not properly resolved during rebasing, uncommitted work might be lost.&lt;/p&gt;

&lt;p&gt;To safely use git rebase, follow this golden rule:&lt;/p&gt;

&lt;p&gt;Never rebase commits that have been pushed to a shared repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  Rebase vs. Merge: Key Differences
&lt;/h2&gt;

&lt;p&gt;While both rebase and merge aim to combine changes from different branches, but they take radically different approaches:&lt;/p&gt;

&lt;p&gt;Git Merge&lt;/p&gt;

&lt;p&gt;Commit History: Creates a merge commit, keeps all history.&lt;/p&gt;

&lt;p&gt;Workflow: No changes to existing commits&lt;/p&gt;

&lt;p&gt;Merge Commits: Creates merge commits&lt;/p&gt;

&lt;p&gt;Usage: Suitable for preserving full history&lt;/p&gt;

&lt;p&gt;Git Rebase&lt;/p&gt;

&lt;p&gt;Commit History: Rewrites history by moving commits&lt;/p&gt;

&lt;p&gt;Workflow: Re-applies commits on top of the new branch&lt;/p&gt;

&lt;p&gt;Merge Commits: Does not create merge commits&lt;/p&gt;

&lt;p&gt;Usage: Ideal for linear, clean history.&lt;/p&gt;

&lt;p&gt;Example:&lt;/p&gt;

&lt;p&gt;Let's say you have the following commit history:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  A---B---C feature-branch
 /
D---E---F master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using git merge feature-branch from master will result in:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  A---B---C   feature-branch
 /         \
D---E---F---M   merge commit master

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using git rebase master from feature-branch will reapply the feature branch commits on top of master:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;D---E---F---A---B---C rebased feature-branch

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  History Rewrite: What Does It Mean?
&lt;/h2&gt;

&lt;p&gt;When we talk about rewriting history in Git, we mean changing the commit graph or altering the details of past commits (like commit IDs, messages, or ordering). Rebase changes the parent commit of each commit in the rebased branch. This makes it appear as if the commits were made directly on top of the target branch.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interactive Rebase: The Power at Your Fingertips
&lt;/h2&gt;

&lt;p&gt;Interactive rebase (git rebase -i) is one of the most powerful features in Git. It allows you to rewrite commits in a detailed, customizable way. You can:&lt;/p&gt;

&lt;p&gt;Squash commits: Combine multiple commits into one.&lt;/p&gt;

&lt;p&gt;Reword commit messages: Edit the message of specific commits.&lt;/p&gt;

&lt;p&gt;Drop commits: Remove unnecessary commits from the history.&lt;/p&gt;

&lt;h2&gt;
  
  
  Basic Rebase Workflow
&lt;/h2&gt;

&lt;p&gt;Let's consider a scenario where you're working on a feature-branch and the master branch has progressed with new commits. You want to incorporate the latest changes from master into your feature-branch while keeping a linear history.&lt;/p&gt;

&lt;p&gt;Steps:&lt;/p&gt;

&lt;p&gt;Fetch latest changes from the remote:&lt;/p&gt;

&lt;p&gt;git fetch origin&lt;/p&gt;

&lt;p&gt;Switch to feature-branch:&lt;/p&gt;

&lt;p&gt;git checkout feature-branch&lt;/p&gt;

&lt;p&gt;Rebase on top of master:&lt;/p&gt;

&lt;p&gt;git rebase origin/master&lt;/p&gt;

&lt;p&gt;This will move all your commits in feature-branch on top of the latest master branch commits.&lt;/p&gt;

&lt;h2&gt;
  
  
  Complex Rebase Workflow
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Rebase Conflicts and How to Resolve Them
&lt;/h3&gt;

&lt;p&gt;Rebase conflicts are inevitable when your branch modifies the same files as the branch you’re rebasing onto.&lt;/p&gt;

&lt;p&gt;When rebasing feature-branch onto master, Git may detect that both branches modified the same line in file foo.txt.&lt;/p&gt;

&lt;p&gt;Git will stop at the conflicting commit and mark the file as conflicted.&lt;/p&gt;

&lt;p&gt;Open the conflicted file and manually resolve the differences.&lt;/p&gt;

&lt;p&gt;After resolving, run:&lt;/p&gt;

&lt;p&gt;git add foo.txt&lt;br&gt;
git rebase --continue&lt;/p&gt;

&lt;h3&gt;
  
  
  Rebase with Multiple Branches
&lt;/h3&gt;

&lt;p&gt;In a scenario with more than two branches, rebasing becomes more complex but follows the same principles.&lt;/p&gt;

&lt;p&gt;git checkout feature-branch &lt;br&gt;
git rebase release&lt;/p&gt;

&lt;p&gt;Your commits will be replayed on top of release, ensuring your changes are up-to-date with the release branch while still staying synced with develop.&lt;/p&gt;

&lt;p&gt;git rebase --abort&lt;/p&gt;

&lt;h2&gt;
  
  
  Rebase Best Practices
&lt;/h2&gt;

&lt;p&gt;Rebase Locally, Merge Remotely: Rebase is perfect for keeping your local history clean, but when pushing changes, consider using merge to avoid overwriting shared history.&lt;/p&gt;

&lt;p&gt;Rebase Before Push: Always rebase your feature branch onto the latest master before pushing to avoid merge commits.&lt;/p&gt;

&lt;p&gt;Interactive Rebase for History Cleanup: Use git rebase -i to curate your commit history before making your changes public.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Git rebase is an incredibly powerful tool, but it should be used with caution. Its ability to rewrite history makes it ideal for keeping commit histories clean, but also risky when used on shared branches. By mastering rebase commands and understanding when to apply them, can streamline Git workflows while avoiding common pitfalls.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Power of Java Virtual Threads: A Deep Dive into Scalable Concurrency</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Sat, 05 Oct 2024 03:25:02 +0000</pubDate>
      <link>https://dev.to/kiranukamath/power-of-java-virtual-threads-a-deep-dive-into-scalable-concurrency-3529</link>
      <guid>https://dev.to/kiranukamath/power-of-java-virtual-threads-a-deep-dive-into-scalable-concurrency-3529</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2Fw_1456%2Cc_limit%2Cf_webp%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F64db0c10-9f23-4a9e-868a-fb897a160f00_1779x944.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2Fw_1456%2Cc_limit%2Cf_webp%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252F64db0c10-9f23-4a9e-868a-fb897a160f00_1779x944.png" alt="Virtual threads"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Java introduces a groundbreaking feature: Virtual Threads, designed to address the limitations of traditional threading models and make high-concurrency applications more accessible and efficient. In this blog, we'll dive deep into the why, what, and how of virtual threads, compare them with other concurrency models, and explore practical use cases with coding examples.&lt;/p&gt;

&lt;p&gt;What are Virtual Threads?&lt;/p&gt;

&lt;p&gt;Virtual threads are lightweight threads that are managed by the Java runtime rather than the OS, that reduce the effort of writing, maintaining, and debugging high-throughput concurrent applications. They provide a similar programming model to traditional threads but with much lower resource overhead, enabling the creation and management of a large number of concurrent tasks more efficiently.&lt;/p&gt;

&lt;p&gt;There are two kinds of threads, platform threads and virtual threads.Like a platform thread, a virtual thread is also an instance of java.lang.Thread. However, a virtual thread isn't tied to a specific OS thread and when code running in a virtual thread calls a blocking I/O operation, the Java runtime suspends the virtual thread until it can be resumed. The OS thread associated with the suspended virtual thread is now free to perform operations for other virtual threads.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Virtual Threads?
&lt;/h2&gt;

&lt;p&gt;Use virtual threads in high-throughput concurrent applications, especially those that consist of a great number of concurrent tasks that spend much of their time waiting. &lt;/p&gt;

&lt;p&gt;Traditional threads, or platform threads, in Java are directly mapped to operating system (OS) threads. While they are powerful, they come with several limitations:&lt;/p&gt;

&lt;p&gt;Resource Heavy: Each platform thread consumes a significant amount of memory (typically 1MB stack size by default).&lt;/p&gt;

&lt;p&gt;Scalability Issues: Managing a large number of threads can lead to high context-switching overhead, making it difficult to scale applications efficiently.&lt;/p&gt;

&lt;p&gt;Complexity: Writing scalable and maintainable multi-threaded code is complex and error-prone.&lt;/p&gt;

&lt;p&gt;These limitations hinder the development of highly concurrent applications, especially those that need to handle tens of thousands or even millions of concurrent tasks, such as web servers or real-time data processing systems.&lt;/p&gt;

&lt;p&gt;Virtual threads are not faster threads; they exist to provide scale (higher throughput), not speed (lower latency). Virtual threads are suitable for running tasks that spend most of the time blocked, often waiting for I/O operations to complete. However, they aren't intended for long-running CPU-intensive operations.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Do Virtual Threads Work?
&lt;/h2&gt;

&lt;p&gt;Virtual threads decouple the application-level concurrency from the OS-level threading model. This decoupling allows the JVM to manage thousands or millions of virtual threads efficiently by multiplexing them onto a smaller number of platform threads.&lt;/p&gt;

&lt;p&gt;When the Java runtime schedules a virtual thread, it assigns or mounts the virtual thread on a platform thread, then the operating system schedules that platform thread as usual. This platform thread is called a carrier. After running some code, the virtual thread can unmount from its carrier. This usually happens when the virtual thread performs a blocking I/O operation. After a virtual thread unmounts from its carrier, the carrier is free, which means that the Java runtime scheduler can mount a different virtual thread on it.A virtual thread cannot be unmounted during blocking operations when it is pinned to its carrier. A virtual thread is pinned when it runs code inside synchronized block. So it is recommended to use ReentrantLock.&lt;/p&gt;

&lt;h2&gt;
  
  
  Creating Virtual Threads:
&lt;/h2&gt;

&lt;p&gt;Creating virtual threads in Java 21 is straightforward. Here’s an example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Thread.startVirtualThread(() -&amp;gt; {
 // Simulate some work
 System.out.println("Running in virtual thread: " +  Thread.currentThread());
});
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Virtual threads can also be created with ExecutorService which is easy to manage&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ExecutorService myExecutor=Executors.newVirtualThreadPerTaskExecutor());
Future&amp;lt;?&amp;gt; future = myExecutor.submit(() -&amp;gt; System.out.println("Running thread"));
future.get();
System.out.println("Task completed");
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Can I create 1,000,000 Virtual Threads?
&lt;/h2&gt;

&lt;p&gt;Yes, I tried creating 1,000,000 and it took 5 seconds to create and run them.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
public static void main(String[] args) throws InterruptedException {
        Instant start = Instant.now();
        Set&amp;lt;Long&amp;gt; vThreadIds = new HashSet&amp;lt;&amp;gt;();

        var vThreads = IntStream.range(0, 1_000_000)
                .mapToObj(i -&amp;gt; Thread.ofVirtual().unstarted(() -&amp;gt; {
                    vThreadIds.add(Thread.currentThread().getId());
                    try {
                        Thread.sleep(100);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                })).toList();

        vThreads.forEach(Thread::start);
        for (var thread : vThreads) {
            thread.join();
        }

        Instant end = Instant.now();
        System.out.println("Time =" + Duration.between(start, end).toMillis() + " ms");
        System.out.println("Number of unique vThreads used " + vThreadIds.size());
    }

Output:
Time = 4482 ms
Number of unique vThreads used 1000000

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Memory Efficiency: Virtual threads use a much smaller stack size than platform threads, often just a few kilobytes compared to megabytes. This reduction in stack size allows the JVM to manage a much larger number of virtual threads without exhausting memory.&lt;/p&gt;

&lt;p&gt;JVM Management: The JVM handles the scheduling of virtual threads onto a smaller number of platform threads, reducing the overhead of context switching and improving efficiency.&lt;/p&gt;

&lt;p&gt;Scalability: By decoupling application-level concurrency from OS-level threads, virtual threads can scale to handle hundreds of thousands of concurrent tasks, making them ideal for modern applications requiring high concurrency.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Can’t I Create 100,000 Normal Threads?
&lt;/h2&gt;

&lt;p&gt;Creating 100,000 normal (platform) threads is not feasible due to their heavy memory consumption and the OS's limitations in handling such a large number of threads. Each platform thread typically uses around 1MB of memory for its stack. Creating 100,000 threads would require around 100GB of memory just for the stacks, which is impractical for most systems.Try: I tried to create Executors.newFixedThreadPool(100000) and got OutOfMemoryError. Please do try, its interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Virtual Threads vs. Other Concurrency Models
&lt;/h2&gt;

&lt;p&gt;Virtual Threads and Parallel Streams: &lt;/p&gt;

&lt;p&gt;Parallel streams abstract the complexity of parallel processing but are limited by the number of available cores. Virtual threads can handle a larger number of concurrent tasks by efficiently managing the available resources, making them suitable for tasks that involve I/O operations and need higher concurrency.Note: Parallel streams should never be used where IO operation is involved.&lt;/p&gt;

&lt;p&gt;Virtual Threads and CompletableFutures: &lt;/p&gt;

&lt;p&gt;CompletableFutures offer a way to handle asynchronous computations but can become complex when dealing with many interdependent futures. Virtual threads simplify this by allowing a straightforward threading model without the overhead of managing numerous futures.&lt;/p&gt;

&lt;p&gt;Virtual Threads and Reactive WebFlux: &lt;/p&gt;

&lt;p&gt;Reactive programming with WebFlux is powerful for I/O-bound applications but requires a different programming model. Virtual threads offer a simpler, more intuitive model while achieving similar scalability for many concurrent I/O tasks.I like reactive programming.&lt;/p&gt;

&lt;h2&gt;
  
  
  Virtual Threads in One Request Per Thread Model
&lt;/h2&gt;

&lt;p&gt;The "one request per thread" model is a common pattern where each incoming request is handled by a separate thread(tomcat). This model is simple and intuitive but scales poorly with platform threads due to their high resource usage. Virtual threads can revolutionize this model by making it feasible to handle thousands or even more of concurrent requests efficiently.Simple and Scalable: This example sets up an HTTP server where each request is handled by a new virtual thread, using the Executors.newVirtualThreadPerTaskExecutor(). This approach combines the simplicity of the one request per thread model with the scalability of virtual threads.Low Overhead: Virtual threads allow the server to handle a massive number of concurrent connections without the resource overhead associated with platform threads.&lt;/p&gt;

&lt;h2&gt;
  
  
  How Virtual threads are so efficient?
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2Fw_1456%2Cc_limit%2Cf_webp%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252Fd24886a3-b166-4348-8cc1-e449e8548f6f_800x388.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fsubstackcdn.com%2Fimage%2Ffetch%2Fw_1456%2Cc_limit%2Cf_webp%2Cq_auto%3Agood%2Cfl_progressive%3Asteep%2Fhttps%253A%252F%252Fsubstack-post-media.s3.amazonaws.com%252Fpublic%252Fimages%252Fd24886a3-b166-4348-8cc1-e449e8548f6f_800x388.png"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Assume a scenario where we have one carrier thread(platform thread) and three virtual threads. We will focus on what happens when a virtual thread performs an I/O operation and how the other virtual threads are managed.&lt;/p&gt;

&lt;p&gt;VirtualThread-1 starts executing on CarrierThread-1. At some point, VirtualThread-1 needs to perform a blocking I/O operation (e.g., reading from a file or a network socket).VirtualThread-2 and VirtualThread-3 are in a ready-to-run state but are not currently running.&lt;/p&gt;

&lt;p&gt;When VirtualThread-1 hits the blocking I/O operation, it cannot continue execution until the I/O is complete. The JVM detects that VirtualThread-1 is about to block and performs a context switch.&lt;/p&gt;

&lt;p&gt;The JVM unlinks VirtualThread-1 from CarrierThread-1. VirtualThread-1 is now parked and placed in a waiting state. CarrierThread-1 becomes available to run other virtual threads.&lt;/p&gt;

&lt;p&gt;The JVM scheduler selects VirtualThread-2 to run next. VirtualThread-2 is now linked to CarrierThread-1 and starts executing on this carrier thread. &lt;/p&gt;

&lt;p&gt;VirtualThread-2 runs on CarrierThread-1 until it either completes or hits another blocking operation. When VirtualThread-2 also performs a blocking operation, a similar unlinking process occurs. CarrierThread-1 would then be free to run VirtualThread-3. &lt;/p&gt;

&lt;p&gt;Once the I/O operation that blocked VirtualThread-1 completes, the virtual thread is ready to resume execution. The JVM scheduler finds an available carrier thread for VirtualThread-1. &lt;/p&gt;

&lt;p&gt;If CarrierThread-1 is available, VirtualThread-1 is re-linked to CarrierThread-1. If CarrierThread-1 is busy, the JVM scheduler will find another available carrier thread. VirtualThread-1 resumes execution from the point where it was blocked. The execution continues until the virtual thread completes or hits another blocking operation.&lt;/p&gt;

&lt;p&gt;Virtual threads have their stacks stored in the heap, unlike platform threads that use OS-provided stack space. This allows the JVM to efficiently manage and switch stacks without the overhead of OS-level thread context switching. &lt;/p&gt;

&lt;p&gt;Virtual threads leverage a continuation-based model. When a virtual thread is unlinked from a carrier thread, its state is captured as a continuation. This state can be stored and resumed later without needing a one-to-one mapping with carrier threads. &lt;/p&gt;

&lt;p&gt;The JVM's scheduler ensures that carrier threads are not idle when there are runnable virtual threads. This efficient scheduling minimizes the time a carrier thread is idle and maximizes CPU utilization.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is Continuation-based model
&lt;/h2&gt;

&lt;p&gt;A continuation is a mechanism that allows a computation to be paused and resumed at a later point. In the context of virtual threads, continuations enable the JVM to suspend and resume the execution of virtual threads efficiently.&lt;/p&gt;

&lt;p&gt;Pausing Execution: When a virtual thread encounters a blocking operation (e.g., waiting for I/O), the JVM can pause the execution of the thread. This is done by saving the current state of the virtual thread, including its call stack and local variables.&lt;/p&gt;

&lt;p&gt;Resuming Execution: Once the blocking operation completes, the JVM can resume the execution of the virtual thread from the exact point it was paused. The saved state is restored, and the computation continues as if it were never interrupted.&lt;/p&gt;

&lt;p&gt;Encountering a Blocking Operation: When a virtual thread performs a blocking operation (such as waiting for an I/O operation), the JVM detects this and initiates the process of unlinking the virtual thread from its current platform thread. &lt;/p&gt;

&lt;p&gt;Unlinking from Platform Threads: The JVM suspends the execution of the virtual thread by creating a continuation. The current state of the virtual thread is saved and the virtual thread is unlinked from the platform thread. The platform thread is then free to execute other tasks. &lt;/p&gt;

&lt;p&gt;Moving to the Heap: The state of the virtual thread, now encapsulated as a continuation, is stored in the heap. This means that while the virtual thread is waiting for the I/O operation to complete, it does not consume the resources of a platform thread. &lt;/p&gt;

&lt;p&gt;Completing the I/O Operation: Once the I/O operation completes, the JVM reactivates the virtual thread. The saved continuation is retrieved from the heap, and the virtual thread is linked back to an available platform thread. &lt;/p&gt;

&lt;p&gt;Resuming Execution: The virtual thread resumes execution from the point where it was paused, continuing with its task as if it was never interrupted.&lt;/p&gt;

&lt;p&gt;The JDK's virtual thread scheduler is a work-stealing ForkJoinPool that operates in FIFO mode. The parallelism of the scheduler is the number of platform threads available for the purpose of scheduling virtual threads. By default it is equal to the number of available processors. A virtual thread can be scheduled on different carriers over the course of its lifetime, i.e the scheduler does not maintain affinity between a virtual thread and any particular platform thread.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion: When to Use Virtual Threads
&lt;/h2&gt;

&lt;p&gt;When to Use Virtual Threads:&lt;/p&gt;

&lt;p&gt;High Concurrency Needs: When your application requires handling a large number of concurrent tasks, such as a web server handling many simultaneous connections.&lt;/p&gt;

&lt;p&gt;I/O-Bound Tasks: Ideal for applications with many I/O-bound tasks, where threads spend most of their time waiting for I/O operations to complete.&lt;/p&gt;

&lt;p&gt;Simplifying Thread Management: When you want to simplify concurrency management without dealing with the complexities of asynchronous programming or reactive frameworks.&lt;/p&gt;

&lt;p&gt;Request per Thread Model: Perfect for web servers and other applications following the request per thread model, allowing each request to be handled independently and efficiently.&lt;/p&gt;

&lt;p&gt;When Not to Use Virtual Threads:&lt;/p&gt;

&lt;p&gt;Heavy Computational Tasks: For CPU-bound tasks that require intensive computation, traditional threading models or ForkJoinPool or parallel streams might be more efficient.&lt;/p&gt;

&lt;p&gt;Limited Threading Needs: If your application only requires a manageable number of threads, the benefits of virtual threads might not be significant.&lt;/p&gt;

&lt;p&gt;Credits: Java,Oracle,openjdk official documentation and Java Youtube channel.&lt;/p&gt;

</description>
      <category>java</category>
      <category>multithreading</category>
    </item>
    <item>
      <title>Unlocking Efficiency: How Bloom Filters Save Space and Supercharge Data Access</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Tue, 19 Sep 2023 16:01:00 +0000</pubDate>
      <link>https://dev.to/kiranukamath/unlocking-efficiency-how-bloom-filters-save-space-and-supercharge-data-access-2kg5</link>
      <guid>https://dev.to/kiranukamath/unlocking-efficiency-how-bloom-filters-save-space-and-supercharge-data-access-2kg5</guid>
      <description>&lt;p&gt;Bloom filters stand out as a clever and efficient way to determine whether an element is a member of a set. This probabilistic data structure is particularly useful when dealing with large datasets and applications where memory efficiency and fast set membership testing are essential. In this blog post, we will delve into the fascinating world of Bloom filters, exploring their inner workings, use cases, advantages, and limitations.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is a Bloom Filter?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A Bloom filter is a space-efficient probabilistic data structure designed to quickly test whether an element belongs to a set or not. It accomplishes this by using a bit array of a fixed size and a series of hash functions. When an element is added to the Bloom filter, the hash functions generate a set of positions in the bit array where bits are set to 1. To check for membership, the same hash functions are applied to the query element, and if all corresponding bits are set to 1, it suggests that the element may be in the set. However, false positives are possible, but false negatives are not.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Does a Bloom Filter Work?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Initialisation&lt;/strong&gt;: A Bloom filter begins as an array of bits, all initially set to 0.&lt;br&gt;
&lt;strong&gt;Adding Elements&lt;/strong&gt;: To add an element to the filter, it undergoes multiple hash functions that generate a set of bit positions. These positions are then set to 1 in the filter. Each hash function takes the element as input and produces an output, typically a numeric value. This output is then mapped to positions in the bit array using modulo arithmetic. For example, if you have a Bloom filter with a bit array of size , and one of the hash functions produces an output of , you can map it to a position in the bit array using .&lt;br&gt;
&lt;strong&gt;Membership Query&lt;/strong&gt;: To check if an element is a member of the set, the same hash functions are applied to it. If all corresponding bits in the filter are set to 1, the element is considered a possible member. If any bit is 0, it is definitely not in the set.&lt;/p&gt;

&lt;p&gt;Let’s take an example to illustrate this. Suppose we have a Bloom filter with 8 bits(bit array of size 8) and two hash functions.&lt;/p&gt;

&lt;p&gt;Hash Function 1 takes the element “java” and produces an output of 3.&lt;br&gt;
Hash Function 2 takes the same element “java” and produces an output of 6.&lt;br&gt;
To add “java” to the Bloom filter:&lt;/p&gt;

&lt;p&gt;Position 3 and Position 6 in the bit array are set to 1.&lt;br&gt;
We want to check if “java” is in the bloom filter, then you’ll apply Hash Function 1 and Hash Function 2 to “java” and check if both Position 3 and Position 6 in the bit array are set to 1. If all the corresponding bits at positions 3 and 6 are set to 1, “java” is considered a possible member.&lt;/p&gt;

&lt;p&gt;It’s important to note that the positions in the bit array for different elements can overlap, which is why false positives can occur when checking for membership. False positives happen when the bits set to 1 for one element overlap with the bits set to 1 for another element, making the filter think an element is present when it’s not. The probability of false positives depends on the size of the bit array, the number of hash functions, and the number of elements added to the filter.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How Bloom Filters Save Space in Data Storage&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bloom filters are ingenious data structures known for their space-efficient characteristics. They accomplish this by making a few trade-offs and using probabilistic techniques. Here’s how Bloom filters save space in data storage:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Compact Representation&lt;/strong&gt;: Bloom filters use a compact representation of data compared to other data structures like hash tables or binary search trees. Instead of storing the actual elements, a Bloom filter employs a fixed-size bit array.&lt;br&gt;
Each element is mapped to multiple positions (bits) in this array through hash functions. As a result, the storage requirements are proportional to the size of the bit array, which can be significantly smaller than storing the elements themselves.&lt;br&gt;
&lt;strong&gt;Elimination of Redundant Data&lt;/strong&gt;: Traditional data structures often store all the elements individually. In contrast, a Bloom filter doesn’t store the elements themselves. By using multiple hash functions, it efficiently encodes the presence or absence of elements in a highly compressed form. This eliminates the need to store redundant data, which can be especially advantageous when dealing with large datasets.&lt;br&gt;
&lt;strong&gt;Constant Size&lt;/strong&gt;: The space occupied by a Bloom filter is not directly related to the number of elements it contains. Instead, it depends on parameters like the desired false positive probability and the expected number of insertions. This means that regardless of the size of the dataset, the Bloom filter maintains a relatively constant size, making it suitable for memory-constrained applications.&lt;br&gt;
&lt;strong&gt;Probabilistic Nature&lt;/strong&gt;: One of the trade-offs made by Bloom filters is their probabilistic nature. They allow for a small probability of false positives, which means that in some cases, the filter might incorrectly suggest an element is in the set when it’s not. This trade-off enables Bloom filters to achieve their space efficiency, as they don’t need to maintain complete and precise information about the elements.&lt;br&gt;
Scalability: Bloom filters can scale effectively for large datasets without a significant increase in memory usage. The size of the bit array and the number of hash functions can be adjusted to balance memory consumption and false positive rates.&lt;br&gt;
&lt;strong&gt;Parallelism&lt;/strong&gt;: Due to the independence of hash functions and bit positions in the array, Bloom filters allow for efficient parallel processing. Multiple membership tests can be performed concurrently, making them suitable for multi-threaded or distributed systems.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Advantages of Bloom Filters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Space Efficiency&lt;/strong&gt;: Bloom filters use relatively small amounts of memory compared to other data structures like hash tables, making them ideal for applications with limited memory.&lt;br&gt;
&lt;strong&gt;Fast Membership Testing&lt;/strong&gt;: Checking membership in a Bloom filter is extremely fast. The number of hash functions and size of the bit array can be adjusted to balance space and accuracy.&lt;br&gt;
&lt;strong&gt;Parallelism&lt;/strong&gt;: Multiple membership tests can be performed in parallel since each query element’s hash positions are independent.&lt;br&gt;
&lt;strong&gt;No False Negatives&lt;/strong&gt;: Bloom filters never produce false negatives. If the filter says an element is not present, it’s definitely not in the set.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Limitations of Bloom Filters&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;False Positives&lt;/strong&gt;: The probabilistic nature of Bloom filters means there can be false positives. If all bits are set to 1 for a query, it suggests membership, but the element might not be in the set.&lt;br&gt;
&lt;strong&gt;No Deletion&lt;/strong&gt;: Bloom filters do not support element deletion. Removing an element is not straightforward as it could affect other elements.&lt;br&gt;
&lt;strong&gt;Hash Functions&lt;/strong&gt;: The quality of hash functions used is crucial. Poor hash functions can increase false positives.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Use Cases&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Caching&lt;/strong&gt;: Web browsers use Bloom filters to quickly determine if a website is in a local cache, reducing network requests.&lt;br&gt;
&lt;strong&gt;Spell Checkers&lt;/strong&gt;: Bloom filters can help identify whether a word exists in a dictionary, improving the speed of spell checkers.&lt;br&gt;
&lt;strong&gt;Network Routers&lt;/strong&gt;: Routers use Bloom filters to efficiently decide whether an IP address is in a blacklist.&lt;br&gt;
Duplicate Elimination: In distributed systems, Bloom filters can be employed to eliminate duplicate data transmission.&lt;br&gt;
&lt;strong&gt;Indexing&lt;/strong&gt;: When a document is inserted or updated in the database, its key or ID is hashed using one or more hash functions. These hash values are then used to determine the positions in a Bloom filter. Bits at these positions in the Bloom filter are set to 1. For example, consider a NoSQL database that uses a Bloom filter in its index. When a new document with the key “doc123” is added to the index, the Bloom filter is updated based on the hash values of “doc123.”&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Bloom filters are an ingenious data structure for efficient set membership testing, offering space-efficient solutions in various applications.&lt;/p&gt;

&lt;p&gt;Bloom filters save space in data storage by using a compact representation, eliminating redundant data, maintaining constant size, minimising overhead, and leveraging their probabilistic nature. While they do have limitations, such as the possibility of false positives.&lt;/p&gt;

&lt;p&gt;Understanding their limitations and use cases is essential for harnessing their power effectively. When memory efficiency and fast querying are essential, Bloom filters are a valuable tool in a programmer’s toolbox.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Why should one minute be 60 seconds and not 100 seconds?</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Tue, 15 Jun 2021 04:59:11 +0000</pubDate>
      <link>https://dev.to/kiranukamath/why-should-one-minute-be-60-seconds-and-not-100-seconds-1knm</link>
      <guid>https://dev.to/kiranukamath/why-should-one-minute-be-60-seconds-and-not-100-seconds-1knm</guid>
      <description>&lt;p&gt;To understand why 60 seconds.&lt;br&gt;&lt;br&gt;
Let's see where all this began?&lt;/p&gt;

&lt;p&gt;Well, to start with, we have to know about the history of the Babylonian period. They derived their number system from the Sumerians who were using it as early as 3500 BC. They decided 24 hours are divided into two parts &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a day lasting 12 hours and a night lasting 12 hours, &lt;/li&gt;
&lt;li&gt;1hour is 60 minutes and one minute is 60seconds. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But why??&lt;/p&gt;

&lt;p&gt;Because they used the duodecimal system(base 12) and sexagesimal(base 60) which led to 12 hrs a day and 12 hrs a night. &lt;/p&gt;

&lt;p&gt;Hipparchus gave us the “Equinoctial hours” by proposing the division of a day into 24 equal hours.  &lt;/p&gt;

&lt;p&gt;** &lt;em&gt;'12' is a very special number&lt;/em&gt; **&lt;/p&gt;

&lt;p&gt;The importance of the number 12 is typically attributed either to the fact that it equals the number of lunar cycles in a year or the number of finger joints on each hand (three in each of the four fingers, excluding the thumb), making it possible to count to 12 with the thumb.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--yzimKb0d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616648113924/h9qOIyCr_.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--yzimKb0d--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1616648113924/h9qOIyCr_.png" alt="image.png" width="412" height="512"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The number of finger joints on each hand (excluding the thumb) makes it possible to count to 12 by using the thumb. So it can be said that the structure of our fingers may be the reason! &lt;/p&gt;

&lt;p&gt;Another reason behind using '12' is that ‘12’ can be written as ‘6 X 2’, ‘3 X 4’.  So that a day can be divided into half and quarters easily. whereas 10 has only three divisors - whole numbers that divide it a whole number of times. &lt;/p&gt;

&lt;p&gt;Sixty has 12 divisors and because 60 = 5 x 12 it combines the advantages of both 10 and 12. It is notably convenient for expressing fractions since 60 is the smallest number divisible by the first six counting numbers(1,2,3,4,5,6) as well as by 10, 12, 15, 20, and 30.&lt;/p&gt;

&lt;p&gt;Nobody really cared about seconds until after the Middle Ages and all the division of time was mainly to communicate time to others.&lt;br&gt;&lt;br&gt;
If someone asks you what time is it, you can say “half a day completed” or “quarter day completed”. &lt;/p&gt;

&lt;p&gt;But imagine what it would be if a day was 10 hrs, it would hard to tell since 10/3 is 3.3333333….. &lt;br&gt;
 Obviously, it would be difficult to speak.&lt;br&gt;
60 can be divided by 6,5,4, 3, 2. So it would be easy to communicate the time.&lt;/p&gt;

&lt;p&gt;Another reason might be with the calculation of degrees.&lt;br&gt;&lt;br&gt;
Longitude is measured by imaginary lines that run around the Earth vertically (up and down) and meet at the North and South Poles. These lines are known as meridians. Each meridian measures one arcdegree of longitude. The distance around the Earth measures 360 degrees. Each degree was divided into 60 parts, each of which was again subdivided into 60 smaller parts.&lt;br&gt;&lt;br&gt;
The first division, partes minutae primae, or first minute, became known simply as the "minute."&lt;br&gt;&lt;br&gt;
The second segmentation, partes minutae secundae, or "second minute," became known as the second. &lt;/p&gt;

&lt;p&gt;So now division of time can be connected to the rotation of the earth. Earth rotates 1 degree in 4 minutes. This rotation is a full 360 degree.&lt;br&gt;&lt;br&gt;
So, in one hour, the earth turns 15 degrees. Every four minutes, the earth has turned one degree.&lt;br&gt;
So in 60 mins, it would rotate 15 degrees. Now as we have 360 degrees in total to rotate, we take 24 hours to do so. (24×15 = 360).&lt;/p&gt;

&lt;p&gt;Isn't this fun to know about this.&lt;br&gt;&lt;br&gt;
Hope you learned something new here and don't forget to comment below your thoughts. Thanks for reading!&lt;br&gt;
Keep learning, Keep Growing.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Measures of Similarity and Distance</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Tue, 15 Jun 2021 04:54:11 +0000</pubDate>
      <link>https://dev.to/kiranukamath/measures-of-similarity-and-distance-542g</link>
      <guid>https://dev.to/kiranukamath/measures-of-similarity-and-distance-542g</guid>
      <description>&lt;p&gt;In statistics, a similarity measure is a real-valued function that quantifies the similarity between two objects. The purpose of a measure of similarity is to compare two vectors and compute a single number which evaluates their similarity. The main objective is to determine to what extent two vectors co-vary.&lt;/p&gt;

&lt;p&gt;We will look at metrics that helps in understanding similarities by measures of correlation.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Pearson's Correlation Coefficient&lt;/li&gt;
&lt;li&gt;Spearman's Correlation Coefficient&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Let's take a look at each of these individually.&lt;/p&gt;

&lt;h3&gt;
  
  
  Pearson's Correlation Coefficient
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Pearson's correlation coefficient&lt;/strong&gt; is a measure related to the strength and direction of a &lt;strong&gt;linear&lt;/strong&gt; relationship.   The value for this coefficient will be between -1 and 1 where -1 indicates a strong, negative linear relationship and 1 indicates a strong, positive linear relationship. &lt;/p&gt;

&lt;p&gt;If we have two vectors x and y, we can compare them in the following way to calculate Pearson's correlation coefficient:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--PolqfDCm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.upmath.me/svg/CORR%28%255Ctextbf%257Bx%257D%252C%2520%255Ctextbf%257By%257D%29%2520%253D%2520%255Cfrac%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28x_i%2520-%2520%255Cbar%257Bx%257D%29%28y_i%2520-%2520%255Cbar%257By%257D%29%257D%257B%255Csqrt%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28x_i-%255Cbar%257Bx%257D%29%255E2%257D%255Csqrt%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28y_i-%255Cbar%257By%257D%29%255E2%257D%257D%2520" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--PolqfDCm--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.upmath.me/svg/CORR%28%255Ctextbf%257Bx%257D%252C%2520%255Ctextbf%257By%257D%29%2520%253D%2520%255Cfrac%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28x_i%2520-%2520%255Cbar%257Bx%257D%29%28y_i%2520-%2520%255Cbar%257By%257D%29%257D%257B%255Csqrt%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28x_i-%255Cbar%257Bx%257D%29%255E2%257D%255Csqrt%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28y_i-%255Cbar%257By%257D%29%255E2%257D%257D%2520" alt="CORR(\textbf{x}, \textbf{y}) = \frac{\sum\limits_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})}{\sqrt{\sum\limits_{i=1}^{n}(x_i-\bar{x})^2}\sqrt{\sum\limits_{i=1}^{n}(y_i-\bar{y})^2}} " width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;where &lt;/p&gt;

&lt;p&gt;$$\bar{x} = \frac{1}{n}\sum\limits_{i=1}^{n}x_i$$&lt;/p&gt;

&lt;p&gt;or it can also be written as&lt;/p&gt;

&lt;p&gt;$$CORR(x, y) = \frac{\text{COV}(x, y)}{\text{STDEV}(x)\text{ }\text{STDEV}(y)}$$&lt;/p&gt;

&lt;p&gt;where &lt;/p&gt;

&lt;p&gt;$$\text{STDEV}(x) = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})^2}$$&lt;/p&gt;

&lt;p&gt;and &lt;/p&gt;

&lt;p&gt;$$\text{COV}(x, y) = \frac{1}{n-1}\sum_{i=1}^{n}(x_i - \bar{x})(y_i - \bar{y})$$&lt;/p&gt;

&lt;p&gt;where n is the length of the vector, which must be the same for both x and y and &lt;br&gt;
$$\bar{x}$$ is the mean of the observations.  &lt;/p&gt;

&lt;p&gt;Function to get Pearson correlation coefficient.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def pearson_corr(x, y):
    '''
    Parameters
    x - an array of matching length to array y
    y - an array of matching length to array x
    Return
    corr - the pearson correlation coefficient for comparing x and y
    '''
    mean_x, mean_y = np.sum(x)/len(x), np.sum(y)/len(y) 

    x_diffs = x - mean_x
    y_diffs = y - mean_y
    corr_numerator = np.sum(x_diffs*y_diffs)
    corr_denominator = np.sqrt(np.sum(x_diffs**2))*np.sqrt(np.sum(y_diffs**2))

    corr = corr_numerator/corr_denominator
    return corr                                                       
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Spearman's Correlation coefficient
&lt;/h3&gt;

&lt;p&gt;Spearman's correlation is  &lt;a href="https://en.wikipedia.org/wiki/Nonparametric_statistics"&gt;non-parametric&lt;/a&gt; measure of rank correlation (statistical dependence between the rankings of two variables). It assesses how well the relationship between two variables can be described using a monotonic function. &lt;/p&gt;

&lt;p&gt;The Spearman correlation between two variables is equal to the Pearson correlation between the rank values of those two variables; while Pearson's correlation assesses linear relationships, Spearman's correlation assesses monotonic relationships (whether linear or not).&lt;/p&gt;

&lt;p&gt;You can quickly change from the raw data to the ranks using the &lt;strong&gt;.rank()&lt;/strong&gt; method as shown code cell below.&lt;/p&gt;

&lt;p&gt;If should map each of our data to ranked data values:&lt;/p&gt;

&lt;p&gt;$$\textbf{x} \rightarrow \textbf{x}^{r}$$&lt;br&gt;
$$\textbf{y} \rightarrow \textbf{y}^{r}$$&lt;/p&gt;

&lt;p&gt;Here &lt;strong&gt;r&lt;/strong&gt; indicate these are ranked values (this is not raising any value to the power of r).  Then we compute Spearman's correlation coefficient as:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--427_2cNF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.upmath.me/svg/SCORR%28%255Ctextbf%257Bx%257D%252C%2520%255Ctextbf%257By%257D%29%2520%253D%2520%255Cfrac%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28x%255E%257Br%257D_i%2520-%2520%255Cbar%257Bx%257D%255E%257Br%257D%29%28y%255E%257Br%257D_i%2520-%2520%255Cbar%257By%257D%255E%257Br%257D%29%257D%257B%255Csqrt%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28x%255E%257Br%257D_i-%255Cbar%257Bx%257D%255E%257Br%257D%29%255E2%257D%255Csqrt%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28y%255E%257Br%257D_i-%255Cbar%257By%257D%255E%257Br%257D%29%255E2%257D%257D%2520" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--427_2cNF--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://i.upmath.me/svg/SCORR%28%255Ctextbf%257Bx%257D%252C%2520%255Ctextbf%257By%257D%29%2520%253D%2520%255Cfrac%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28x%255E%257Br%257D_i%2520-%2520%255Cbar%257Bx%257D%255E%257Br%257D%29%28y%255E%257Br%257D_i%2520-%2520%255Cbar%257By%257D%255E%257Br%257D%29%257D%257B%255Csqrt%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28x%255E%257Br%257D_i-%255Cbar%257Bx%257D%255E%257Br%257D%29%255E2%257D%255Csqrt%257B%255Csum%255Climits_%257Bi%253D1%257D%255E%257Bn%257D%28y%255E%257Br%257D_i-%255Cbar%257By%257D%255E%257Br%257D%29%255E2%257D%257D%2520" alt="SCORR(\textbf{x}, \textbf{y}) = \frac{\sum\limits_{i=1}^{n}(x^{r}_i - \bar{x}^{r})(y^{r}_i - \bar{y}^{r})}{\sqrt{\sum\limits_{i=1}^{n}(x^{r}_i-\bar{x}^{r})^2}\sqrt{\sum\limits_{i=1}^{n}(y^{r}_i-\bar{y}^{r})^2}} " width="" height=""&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;where &lt;/p&gt;

&lt;p&gt;$$\bar{x}^r = \frac{1}{n}\sum\limits_{i=1}^{n}x^r_i$$&lt;/p&gt;

&lt;p&gt;Function that takes in two vectors and returns the Spearman correlation coefficient.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def spearman_corr(x, y):
    '''
    Parameters
    x - an array of matching length to array y
    y - an array of matching length to array x
    Return
    corr - the spearman correlation coefficient for comparing x and y
    '''
    # Change each vector to ranked values
    x = x.rank()
    y = y.rank()

    # Compute Mean Values
    mean_x, mean_y = np.sum(x)/len(x), np.sum(y)/len(y) 

    x_diffs = x - mean_x
    y_diffs = y - mean_y
    corr_numerator = np.sum(x_diffs*y_diffs)
    corr_denominator = np.sqrt(np.sum(x_diffs**2))*np.sqrt(np.sum(y_diffs**2))

    corr = corr_numerator/corr_denominator

    return corr  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Measures of distance
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Euclidean Distance&lt;/li&gt;
&lt;li&gt;Manhattan Distance&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  Euclidean Distance
&lt;/h3&gt;

&lt;p&gt;Euclidean distance is a measure of the straight line distance from one vector to another. In other words, euclidean distance is the square root of the sum of squared differences between corresponding elements of the two vectors.  Since this is a measure of distance, larger values are an indicate two vectors are different from one another. The basis of many measures of similarity and dissimilarity is euclidean distance. &lt;/p&gt;

&lt;p&gt;Euclidean distance is only appropriate for data measured on the same scale. &lt;br&gt;
Consider two vectors &lt;strong&gt;x&lt;/strong&gt; and &lt;strong&gt;y&lt;/strong&gt;, we can compute Euclidean Distance as:&lt;/p&gt;

&lt;p&gt;$$ EUC(\textbf{x}, \textbf{y}) = \sqrt{\sum\limits_{i=1}^{n}(x_i - y_i)^2}$$&lt;/p&gt;

&lt;p&gt;Function to Euclidean Distance. (I have taken help from numpy)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def eucl_dist(x, y):
    '''
    Parameters
    x - an array of matching length to array y
    y - an array of matching length to array x
    Return
    euc - the euclidean distance between x and y
    '''  
    return np.linalg.norm(x - y)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Manhattan Distance
&lt;/h3&gt;

&lt;p&gt;Different from euclidean distance, Manhattan distance is a 'manhattan block' distance from one vector to another.  Therefore, imagine this distance as a way to compute the distance between two points when you are not able to go through buildings or blocks.&lt;/p&gt;

&lt;p&gt;Specifically, this distance is computed as:&lt;/p&gt;

&lt;p&gt;$$ MANHATTAN(\textbf{x}, \textbf{y}) = \sqrt{\sum\limits_{i=1}^{n}|x_i - y_i|}$$&lt;/p&gt;

&lt;p&gt;Function to calculate Manhattan distance&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;def manhat_dist(x, y):
    '''
    INPUT
    x - an array of matching length to array y
    y - an array of matching length to array x
    OUTPUT
    manhat - the manhattan distance between x and y
    '''  
    return sum(abs(e - s) for s, e in zip(x, y))
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--QgdGoAMP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1615212596981/zQz2mA6-G.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--QgdGoAMP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1615212596981/zQz2mA6-G.png" alt="image.png" width="200" height="200"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above image, the &lt;strong&gt;blue&lt;/strong&gt; line gives the &lt;strong&gt;Manhattan&lt;/strong&gt; distance, while the &lt;strong&gt;green&lt;/strong&gt; line gives the &lt;strong&gt;Euclidean&lt;/strong&gt; distance between two points.&lt;/p&gt;

&lt;p&gt;Here in finding similarity by measure of distance, no scaling is performed in the denominator.  Therefore, you need to make sure all of your data are on the &lt;strong&gt;same scale&lt;/strong&gt; when using this metric.&lt;/p&gt;

&lt;p&gt;Because measuring similarity is often based on looking at the distance between vectors, it is important in these cases to scale your data or to have all data be in the same scale.&lt;br&gt;&lt;br&gt;
It becomes a problem if some measures are on a 5 point scale, while others are on a 100 point scale, and we are most likely to have non-optimal results due to the difference in variability of features.&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Is Confusion Matrix really Confusing?</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Mon, 31 May 2021 05:05:59 +0000</pubDate>
      <link>https://dev.to/kiranukamath/is-confusion-matrix-really-confusing-45dc</link>
      <guid>https://dev.to/kiranukamath/is-confusion-matrix-really-confusing-45dc</guid>
      <description>&lt;p&gt;After reading this blog, I am sure you will not be confused with the confusion matrix. &lt;/p&gt;

&lt;p&gt;Let's get started. &lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;confusion matrix&lt;/strong&gt; is the table that is used to describe the performance of the model.&lt;/p&gt;

&lt;p&gt;We can use accuracy as a metric to analyze the performance of the model, then why confusion matrix???&lt;br&gt;&lt;br&gt;
What is the need for Confusion matrix???&lt;/p&gt;

&lt;p&gt;So to understand this let us consider an &lt;strong&gt;example&lt;/strong&gt; of the cancer prediction model.&lt;br&gt;&lt;br&gt;
Since this is a binary classification model its job is to detect cancerous patients based on some features. Considering that only a few, get cancer out of millions of population we consider only 1% of the data provided has cancer positive.&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Having cancer is labeled as 1 and not cancer labeled as 0,&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
An interesting thing to note here is if a system gives the prediction as all 0’s, even then the prediction accuracy will be 99%. It is similar to writing print(0) in model output. This will have an accuracy of 99%.&lt;br&gt;&lt;br&gt;
But this is not correct right??&lt;/p&gt;

&lt;p&gt;Now that you know what is the problem and the need for a new metric to help in this situation, let us see how the confusion matrix solves this problem.&lt;/p&gt;

&lt;p&gt;Let us consider an example with a classification dataset having 1000 data points. &lt;/p&gt;

&lt;p&gt;We get the below confusion matrix:&lt;br&gt;&lt;br&gt;
There will be two classes 1 and 0.&lt;br&gt;&lt;br&gt;
1 would mean the person has cancer, and 0 would mean they don't have cancer.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--u1-CMOem--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622345479330/UIbruZuI9.jpeg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--u1-CMOem--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622345479330/UIbruZuI9.jpeg" alt="IMG_20210530_085941.jpg" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By seeing this table we have 4 different combinations of predicted and actual values.&lt;br&gt;
Let us consider predicted values as Positive and Negative and actual values as True and False.&lt;/p&gt;

&lt;p&gt;Just hold on,,, this is easy and you will understand....&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;True Positive&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Interpretation: Model predicted positive and it’s true.&lt;br&gt;&lt;br&gt;
Example understanding: The model predicted that a person has cancer and a person actually has it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;True Negative&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Interpretation: Model predicted negative and it’s true.&lt;br&gt;&lt;br&gt;
Example understanding: The model predicted that a person does not have cancer and he actually doesn't have cancer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;False Positive&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Interpretation: Model predicted positive and it’s false.&lt;br&gt;&lt;br&gt;
Example understanding: The model predicted that a person has cancer but he actually doesn't have cancer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;False Negative&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Interpretation: Model predicted negative and it’s false.&lt;br&gt;&lt;br&gt;
Example understanding: The model predicted that a person does not have cancer and person actually has cancer.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Precision&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Out of all the positive classes we have predicted correctly, how many are actually positive.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--tt4jElgw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622334721927/DhF2NBE0g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--tt4jElgw--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622334721927/DhF2NBE0g.png" alt="image.png" width="249" height="84"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Recall&lt;/strong&gt;:&lt;br&gt;&lt;br&gt;
Out of all the positive classes, how much we predicted correctly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--HDHEqO5m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622334857706/WQxDBv2UZ.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--HDHEqO5m--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622334857706/WQxDBv2UZ.png" alt="image.png" width="246" height="79"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--DHapH6Mp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622334167725/PfpXzVcsM.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--DHapH6Mp--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622334167725/PfpXzVcsM.png" alt="image.png" width="350" height="636"&gt;&lt;/a&gt;&lt;br&gt;
Image credit: Wikipedia&lt;/p&gt;

&lt;p&gt;Calculating precision and recall for the above table.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--VBBaqFkG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622342128850/VQYydB3C5.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--VBBaqFkG--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622342128850/VQYydB3C5.png" alt="image.png" width="245" height="128"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's compare this with accuracy.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--YXPzHrB7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622342164674/itD37EtZi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--YXPzHrB7--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622342164674/itD37EtZi.png" alt="image.png" width="291" height="57"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--q3Bj5m9G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622342176939/GyhuZxGqu.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--q3Bj5m9G--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622342176939/GyhuZxGqu.png" alt="image.png" width="313" height="71"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The model got an accuracy of 96% but the precision of 0.5 and recall of 0.75&lt;br&gt;&lt;br&gt;
which means that 50% percent of the correctly predicted cases turned out to be cancer cases. Whereas 75% of the cancer positives were successfully predicted by our model.&lt;/p&gt;

&lt;p&gt;Consider an example where prediction is replaced by print(0). so that we get 0 every time. &lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;&lt;/th&gt;
&lt;th&gt;Actual y=0&lt;/th&gt;
&lt;th&gt;Actual y=1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Predicted y = 0&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;914&lt;/td&gt;
&lt;td&gt;86&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Predicted y = 1&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;td&gt;0&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Here accuracy will be 91.4% but what happens to Precision and recall??&lt;br&gt;&lt;br&gt;
Precision becomes 0 since TP is 0.&lt;br&gt;&lt;br&gt;
Recall becomes 0 since TP is 0.&lt;br&gt;&lt;br&gt;
This is a classic example to understand Precision and Recall.&lt;/p&gt;

&lt;p&gt;So now you understand why accuracy is not so useful for imbalanced dataset and how Precision and Recall plays a key role.&lt;/p&gt;

&lt;p&gt;One important thing is to understand is, when to use Precision and when to use Recall??&lt;/p&gt;

&lt;p&gt;Precision is a useful metric where False Positive is of greater importance than False Negatives.&lt;br&gt;&lt;br&gt;
For example, In recommendation systems like Youtube, Google this is an important metric, where the wrong recommendations may cause users to leave the platform.&lt;/p&gt;

&lt;p&gt;Recall is a useful metric where False Negative is of greater importance than False Positive. For example, In the medical field, detecting patients without a disease positive can be tolerated to an extent but patients with disease should always be predicted.&lt;/p&gt;

&lt;p&gt;So what is the case when we are not sure whether to use Precision or Recall??&lt;br&gt;&lt;br&gt;
or what to do when one of the two is high, whether the model is good???&lt;/p&gt;

&lt;p&gt;To answer this let us see what is F1 score. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;F1-score&lt;/strong&gt; is a harmonic mean of Precision and Recall, and it is a high value when Precision is equal to Recall.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why not normal arithmetic mean instead of harmonic mean??&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Because arithmetic mean gives high value when one of the two is high value but harmonic mean will be high only when both are almost equal.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--cispXzj_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622343891175/QMs195OjA.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--cispXzj_--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://cdn.hashnode.com/res/hashnode/image/upload/v1622343891175/QMs195OjA.png" alt="image.png" width="575" height="55"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;So from our example, the F1 score becomes&lt;br&gt;&lt;br&gt;
F1 = 2TP / (2TP + FP + FN) = 2*30 / (2*30 + 30 + 10) = 0.6&lt;/p&gt;

&lt;p&gt;I believe after reading this Confusion matrix is not so confusing anymore! &lt;/p&gt;

&lt;p&gt;Hope you learned something new here and don't forget to comment below your thoughts. Thanks for reading!&lt;br&gt;&lt;br&gt;
Keep learning, Keep Growing.&lt;/p&gt;

</description>
      <category>datascience</category>
      <category>machinelearning</category>
    </item>
    <item>
      <title>Between Stimulus and response - We have freedom of Choice</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Mon, 03 May 2021 15:58:54 +0000</pubDate>
      <link>https://dev.to/kiranukamath/between-stimulus-and-response-we-have-freedom-of-choice-1450</link>
      <guid>https://dev.to/kiranukamath/between-stimulus-and-response-we-have-freedom-of-choice-1450</guid>
      <description>&lt;p&gt;Stimulus is an event that happens to us, and response is our reaction or action towards that event.&lt;br&gt;&lt;br&gt;
We respond in a particular way to a particular stimulus.  &lt;/p&gt;

&lt;p&gt;But in between stimulus and response, We have the freedom to choose how we respond.&lt;br&gt;&lt;br&gt;
And based on our freedom of choice to respond, we either become reactive or proactive.  &lt;/p&gt;

&lt;p&gt;Reactive people are affected by physical, social, or psychological environment and response to the stimulus is based on their surrounding environment. Response keeps changing based on the change in the environment.&lt;br&gt;&lt;br&gt;
Proactive people are also influenced by external stimuli, but their response to stimuli is a value-based choice.&lt;/p&gt;

&lt;p&gt;How do we shift our attitude from Reactive to Proactive???&lt;/p&gt;

&lt;p&gt;For this paradigm shift to happen from Reactive to Proactive we should start by taking Initiative.&lt;br&gt;&lt;br&gt;
We should make a conscious effort to change. Many people wait for something to happen or someone to help them, but in reality, we should help ourselves and instead of being problem ourselves we should start finding solutions to problems.&lt;br&gt;&lt;br&gt;
And that comes with taking responsibility to act. Just Planning is not enough, Taking that first step is so much important.&lt;/p&gt;

&lt;p&gt;When facing any critical situation we can ask these 3 questions to find a solution to Problem.  &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;What's happening to me? What is the stimulus?
&lt;/li&gt;
&lt;li&gt;What's going to happen in the future based on the decision I make? &lt;/li&gt;
&lt;li&gt;What is my response? What can I do? What initiative can I take in this situation?
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Our initiative to respond to stimulus determines our degree of Proactivity.   &lt;/p&gt;

&lt;p&gt;As many people say &lt;code&gt;be a positive person&lt;/code&gt; and &lt;code&gt;have positive thinking in life&lt;/code&gt;. But that's just not enough.&lt;br&gt;&lt;br&gt;
Thinking positively without understanding reality may cause danger. And that's exactly the difference between Positive thinking and Proactivity.   &lt;/p&gt;

&lt;p&gt;The stimulus may be Good or bad, but response towards that stimulus is our own choice, which may make the situation better or worse and just(mostly) depends on the choice we make.   &lt;/p&gt;

&lt;p&gt;Just thinking Positive is not the solution, We should face reality. We should consider the current and future impact and still find the power to choose a positive response to that stimulus.   &lt;/p&gt;

&lt;p&gt;Using correct language also has an impact on our Proactive behavior. For example instead of "I have to" start using "I choose to"  &lt;/p&gt;

&lt;p&gt;To become Proactive we should start focusing more of our time and energy on the circle of Influence. These are things within our Circle of Concern on which we can do something about. This also determines our degree of Proactivity.   &lt;/p&gt;

&lt;p&gt;Try to work on the Circle of Influence by making small commitments and work on them. Don't be in Blaming, accusing mode, rather work on things that have you have control over. Work on You.  &lt;/p&gt;

&lt;p&gt;Concentrate on the Freedom of Choice you choose for responding to stimuli.&lt;/p&gt;

&lt;p&gt;You can read my other Blogs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://blog.learnwithdata.me/why-do-i-write-blogs"&gt;Why do I write Blogs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Series of blogs based on my &lt;a href="https://blog.learnwithdata.me/series/learnings-from-ikigai-the-japanese-secret-to-a-long-happy-life"&gt;Learnings from IKIGAI : the Japanese secret to a long happy life&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.learnwithdata.me/invention-vs-innovation"&gt;Invention vs Innovation&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://blog.learnwithdata.me/www-of-new-years-resolution"&gt;www of new years resolution&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Hope you learned something new here and don't forget to comment below your thoughts.&lt;br&gt;
Thanks for reading!&lt;br&gt;&lt;br&gt;
Keep learning, Keep Growing.  &lt;/p&gt;

</description>
      <category>productivity</category>
    </item>
    <item>
      <title>Why do I write blogs?</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Fri, 16 Apr 2021 13:26:35 +0000</pubDate>
      <link>https://dev.to/kiranukamath/why-do-i-write-blogs-bj0</link>
      <guid>https://dev.to/kiranukamath/why-do-i-write-blogs-bj0</guid>
      <description>&lt;h3&gt;
  
  
  Documenting my learning and creating beginner-friendly content.
&lt;/h3&gt;

&lt;p&gt;The main reason for me to blog, is to write about things I learned and difficulties I faced while learning something new so that if a beginner is starting on the same journey, they might quickly understand beginner stuff and quickly move to intermediate level.&lt;/p&gt;

&lt;p&gt;We usually learn complicated concepts with hard work and dedication but as we work on it for few days, those concepts become easy for us, and at that time if a beginner asks us about that concept we explain with lot jargons and might not be able to explain in a beginner-friendly way.&lt;/p&gt;

&lt;p&gt;so I feel the solution for this to try to write a blog about what I learn so that it might help beginners and even for me to refer in the future. So basically for Beginner friendly documentation. &lt;/p&gt;

&lt;h3&gt;
  
  
  Learning by teaching
&lt;/h3&gt;

&lt;p&gt;I believe I learn more when I am able to teach a concept to someone in simple words. Teaching to others also improves communication skills.&lt;br&gt;&lt;br&gt;
If I am able to explain a concept to a person without much jargon and in a simple way, means that I have learned that concept correctly. So second reason is to teach what I have learned, by which I learn in more depth. One of the best ways to test whether I understood something is to explain it to someone else.&lt;/p&gt;

&lt;h3&gt;
  
  
  Habit &amp;gt; motivation
&lt;/h3&gt;

&lt;p&gt;I want to develop the habit of learning a new concept in Machine learning every week. And when I learn something I will write a blog on it.&lt;br&gt;&lt;br&gt;
So indirectly, excitement and maintaining consistency of publishing blog every week will keep me motivated to learn a new concept in ML every week.&lt;br&gt;&lt;br&gt;
Making a habit of writing a blog with consistency is difficult. But once this becomes a habit it is much better than striving for motivation. Building a system of habit is much better than motivation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Expand my network and learn from Feedback
&lt;/h3&gt;

&lt;p&gt;I want to expand my network and connect with like-minded people and learn from them. As I expand my network, I will get more feedbacks for the blogs I write.&lt;br&gt;&lt;br&gt;
Feedbacks play a vital role for a writer and helps to improve. Feedbacks and suggestions always improve writing, and may sometimes be an eye-opener.&lt;br&gt;&lt;br&gt;
Positive feedbacks motivate me to write more, whereas, negative feedback helps me grow and get better. &lt;/p&gt;

&lt;h2&gt;
  
  
  Confidence
&lt;/h2&gt;

&lt;p&gt;Blogging increased my confidence. I don't know why, but I am now much confident to post a blog compared to posting my first blog. I still remember I did not published and post my blog on social handles for 7 days after writing it, and used to check the entire content to see if everything is correct. &lt;br&gt;
Writing blogs has increased my confidence, both in terms of depth of understanding a concept and expressing my voice in social media.&lt;/p&gt;

&lt;p&gt;Coming to Monetization,&lt;br&gt;&lt;br&gt;
&lt;strong&gt;I don't want to monetize my blog. Actually, I don't feel like reading blog which contains ads around them, so I don't want to give that trouble to the readers.&lt;/strong&gt;&lt;br&gt;
Maybe in future, if there is a way, by which I can monetize the blog without disturbing readers than surely I may try that option.&lt;/p&gt;

&lt;h2&gt;
  
  
  My Future plan in blogging
&lt;/h2&gt;

&lt;p&gt;I want to cover as much as the topic I can in Data science which is necessary for beginners to start the journey in data science. I also want to write about python and how to effectively use it for competitive programming. &lt;/p&gt;

&lt;p&gt;P.S : I have learned a lot about deep learning from fastai, and was inspired by Racheal Thomas's blog &lt;a href="https://medium.com/@racheltho/why-you-yes-you-should-blog-7d2544ac1045"&gt;Why you should blog?&lt;/a&gt;&lt;br&gt;&lt;br&gt;
If you have not read it, please do read it. &lt;/p&gt;

&lt;p&gt;Thanks for your time and reading!&lt;/p&gt;

&lt;p&gt;See you until the next article! &lt;/p&gt;

</description>
    </item>
    <item>
      <title>Exploring Couchbase Analytics Service</title>
      <dc:creator>Kiran U Kamath</dc:creator>
      <pubDate>Fri, 16 Apr 2021 13:25:24 +0000</pubDate>
      <link>https://dev.to/kiranukamath/exploring-couchbase-analytics-service-4k13</link>
      <guid>https://dev.to/kiranukamath/exploring-couchbase-analytics-service-4k13</guid>
      <description>&lt;p&gt;Recently I have been exploring Couchbase Analytics service and finding out how it could be more useful and increase efficiency compared to Couchbase query service.&lt;/p&gt;

&lt;p&gt;Couchbase Analytics service comes with enterprise addition.&lt;/p&gt;

&lt;p&gt;Couchbase Analytics is a parallel data management capability for Couchbase Server which is designed to efficiently run large ad hoc join, set, aggregation, and grouping operations over many records.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Why analytics?&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Every business does these three things in a cycle or a spiral [The Goal]. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Run the business process to deliver products or services to the customers. &lt;/li&gt;
&lt;li&gt;Analyze the business to determine what to change and what to change to. &lt;/li&gt;
&lt;li&gt;Make the change happen. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The Query Service is used by the applications needed to run the the business; it is designed for large number of concurrent queries, each doing small amount of work.  In the RDBMS world, this workload is called the OLTP workload. &lt;/p&gt;

&lt;p&gt;Applications or tools used for analysis have different workload characteristics.  These typically use the Analytics Service; it is designed for a smaller number of concurrent queries analyzing a larger number of documents. In the RDBMS world, this workload is called the OLAP workload(Online analytical processing) &lt;/p&gt;

&lt;p&gt;Advantages Couchbase Analytics approach/ WHY Couchbase Analytics? &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Common data model&lt;/strong&gt;: we don’t have to force our data into a flat, predefined, relational model to analyze it&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Workload isolation&lt;/strong&gt;: Operational query latency and throughput are protected from slow-downs due to your analytical query workload&lt;br&gt;&lt;br&gt;
&lt;strong&gt;High data freshness&lt;/strong&gt;: Analytics runs on data that’s extremely current, without ETL or delays. &lt;br&gt;
&lt;strong&gt;Continuous data sync&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Easy to manage SQL++ interface&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Reduce infrastructure complexity, application development complexity, and cost with a single system for operations and analytics. &lt;/p&gt;

&lt;p&gt;Analytics Service should be run alone, on its own cluster node, with no other Couchbase Service running on that node Due to the large scale and duration of operations it is likely to perform. &lt;/p&gt;

&lt;p&gt;The minimum memory(RAM) quota required is 1024 MB for analytics service. &lt;/p&gt;

&lt;p&gt;Analytics queries never touch Couchbase data servers, but instead running on real-time shadow copies of our data in parallel. Because of this, there is no worry about slowing down the Couchbase Server nodes with complex queries.&lt;/p&gt;
&lt;h3&gt;
  
  
  Dataverse
&lt;/h3&gt;

&lt;p&gt;The top-level organizing concept in the Analytics data world is the dataverse.  &lt;/p&gt;

&lt;p&gt;A &lt;strong&gt;dataverse&lt;/strong&gt;, is a namespace that gives you a place to create and manage datasets and other artifacts for a given Analytics application.  &lt;/p&gt;

&lt;p&gt;In that respect, a dataverse is similar to a database or a schema(schema is the skeleton structure that represents the logical view of the entire database. It defines how the data is organized and how the relations among them are associated) in a relational DBMS. &lt;/p&gt;

&lt;p&gt;Datasets are containers that hold collections of JSON objects. They are similar to tables in an RDBMS or keyspaces in N1QL. A dataset is linked to a Couchbase bucket so that the dataset can ingest data from Couchbase Server.&lt;/p&gt;

&lt;p&gt;Fresh Analytics instance starts out with two dataverses, one called Metadata (the system catalog) and one called Default (available for holding data). &lt;/p&gt;

&lt;p&gt;The first task is to tell Analytics about the Couchbase Server data that you want to shadow and the datasets where you want it to live.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CREATE DATASET datasetName ON `bucketName`; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the bucket has data that are of different types or categories, we can create a separate dataset for those using &lt;code&gt;WHERE&lt;/code&gt;  and it will be created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONNECT LINK Local; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Local = local server(Data service in the same cluster) &lt;/p&gt;

&lt;p&gt;Now perform basic query from analytics service to check if everything is working fine.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SELECT meta(k) AS meta, k AS data 
FROM datasetName k 
LIMIT 1; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As in SQL, the query’s FROM clause binds the variable &lt;code&gt;k&lt;/code&gt; incrementally to the data instances residing in the dataset named &lt;code&gt;datasetName&lt;/code&gt;.  The SELECT clause returns all of the meta-information plus the data value for each binding that satisfies the predicate.&lt;/p&gt;

&lt;p&gt;Once this is set up you can access this service from Couchbase java SDK too.&lt;/p&gt;

&lt;p&gt;Follow &lt;a href="https://kirankamath.hashnode.dev/establishing-connection-to-couchbase-server-from-aws-ec2-instance"&gt;Establishing connection to Couchbase server using Couchbase Java SDK&lt;/a&gt; to set up Java SDK.&lt;/p&gt;

&lt;p&gt;After following that blog edit App.java code with following code to use Couchbase analytics.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import com.couchbase.client.java.*;
import com.couchbase.client.java.kv.*;
import com.couchbase.client.java.json.*;
import com.couchbase.client.java.query.*;
import com.couchbase.client.core.error.CouchbaseException;
import com.couchbase.client.java.analytics.*;


public class App {
    public static void main(String[] args) {
        try {
            Cluster cluster = Cluster.connect("localhost", "username", "password");
              final AnalyticsResult result = cluster
                .analyticsQuery("SELECT * FROM datasetName LIMIT 2;");


              for (JsonObject row : result.rowsAsObject()) {
                    System.out.println("Found row: " + row);
                    System.out.println();

              }

            } catch (CouchbaseException ex) {
              ex.printStackTrace();
            }
    }
}

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Credits:  &lt;a href="https://docs.couchbase.com/home/index.html"&gt;Couchbase Documentation&lt;/a&gt; &lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
