Repository: netty/netty
Issue: the cpu usage is too high(80%) when run netty server thread named NioEventLoopGroup-3-1

### Expected behavior

### Actual behavior

### Steps to reproduce

### Minimal yet complete reproducer code (or URL to code)
int processors = Runtime.getRuntime().availableProcessors();
EventLoopGroup bossGroup = new NioEventLoopGroup(processors*2);
EventLoopGroup workerGroup = new NioEventLoopGroup(processors*2);

### Netty version
<dependency>
  <groupId>io.netty</groupId>
  <artifactId>netty-all</artifactId>
  [<version>4.1.90.Final</version>]
</dependency>

### JVM version (e.g. `java -version`)
jdk1.8.0_361

### OS version (e.g. `uname -a`)
Windows Server 2022 Datacenter

### some picture is worth a thousand words.
[picture1](https://raw.githubusercontent.com/zzy444626905/images/main/netty-bug/1.jpg)
[picture2](https://raw.githubusercontent.com/zzy444626905/images/main/netty-bug/2.jpg)


Issue comments:
Unfortunately, those pictures are not worth even a single word. That's too less information to conclude anything. 

What kind of workload is it? How many connections? Are you running blocking operations on EventLoop?
> Unfortunately, those pictures are not worth even a single word. That's too less information to conclude anything.
> 
> What kind of workload is it? How many connections? Are you running blocking operations on EventLoop?

5 connections only，no blocking operations on EventLoop
the cause i already found

"nioEventLoopGroup-3-1" Id=14 cpuUsage=79.15% deltaTime=171ms time=9015ms RUNNABLE
    at io.netty.handler.codec.DelimiterBasedFrameDecoder.indexOf(DelimiterBasedFrameDecoder.java:314)
    at io.netty.handler.codec.DelimiterBasedFrameDecoder.decode(DelimiterBasedFrameDecoder.java:236)
    at io.netty.handler.codec.DelimiterBasedFrameDecoder.decode(DelimiterBasedFrameDecoder.java:214)
    at io.netty.handler.codec.ByteToMessageDecoder.decodeRemovalReentryProtection(ByteToMessageDecoder.java:501)
    at io.netty.handler.codec.ByteToMessageDecoder.callDecode(ByteToMessageDecoder.java:440)
    at io.netty.handler.codec.ByteToMessageDecoder.channelRead(ByteToMessageDecoder.java:276)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
    at io.netty.handler.timeout.IdleStateHandler.channelRead(IdleStateHandler.java:286)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.AbstractChannelHandlerContext.fireChannelRead(AbstractChannelHandlerContext.java:357)
    at io.netty.channel.DefaultChannelPipeline$HeadContext.channelRead(DefaultChannelPipeline.java:1410)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:379)
    at io.netty.channel.AbstractChannelHandlerContext.invokeChannelRead(AbstractChannelHandlerContext.java:365)
    at io.netty.channel.DefaultChannelPipeline.fireChannelRead(DefaultChannelPipeline.java:919)
    at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:163)
    at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:714)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:650)
    at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:576)
    at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:493)
    at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
    at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.lang.Thread.run(Thread.java:748)

I put up a PR to use a faster search algorithm, but `DelimiterBasedFrameDecoder` is _always_ going to be CPU intensive because it has to search for the delimiters no matter what.

Pull request review comments:

Patch that resolved the issue:
diff --git a/codec/src/main/java/io/netty/handler/codec/DelimiterBasedFrameDecoder.java b/codec/src/main/java/io/netty/handler/codec/DelimiterBasedFrameDecoder.java
index 0dea8857765..68197365602 100644
--- a/codec/src/main/java/io/netty/handler/codec/DelimiterBasedFrameDecoder.java
+++ b/codec/src/main/java/io/netty/handler/codec/DelimiterBasedFrameDecoder.java
@@ -18,6 +18,7 @@
 import static io.netty.util.internal.ObjectUtil.checkPositive;
 
 import io.netty.buffer.ByteBuf;
+import io.netty.buffer.ByteBufUtil;
 import io.netty.channel.ChannelHandlerContext;
 import io.netty.util.internal.ObjectUtil;
 
@@ -311,27 +312,11 @@ private void fail(long frameLength) {
      * found in the haystack.
      */
     private static int indexOf(ByteBuf haystack, ByteBuf needle) {
-        for (int i = haystack.readerIndex(); i < haystack.writerIndex(); i ++) {
-            int haystackIndex = i;
-            int needleIndex;
-            for (needleIndex = 0; needleIndex < needle.capacity(); needleIndex ++) {
-                if (haystack.getByte(haystackIndex) != needle.getByte(needleIndex)) {
-                    break;
-                } else {
-                    haystackIndex ++;
-                    if (haystackIndex == haystack.writerIndex() &&
-                        needleIndex != needle.capacity() - 1) {
-                        return -1;
-                    }
-                }
-            }
-
-            if (needleIndex == needle.capacity()) {
-                // Found the needle from the haystack!
-                return i - haystack.readerIndex();
-            }
+        int index = ByteBufUtil.indexOf(needle, haystack);
+        if (index == -1) {
+            return -1;
         }
-        return -1;
+        return index - haystack.readerIndex();
     }
 
     private static void validateDelimiter(ByteBuf delimiter) {


Test patch: