Skip to content

Commit b4a4bd0

Browse files
committed
Add PollsetSelector implementation to resolve the performance degradation
This change brings the PollsetSelector implementation to address the performance degradation reported by a customer. The new implementation reduces thread stalls and CPU spikes by improving event handling. Validated with customer workloads showing full performance recovery. Signed-off-by: Shruthi <[email protected]>
1 parent 9c75a57 commit b4a4bd0

File tree

18 files changed

+1730
-156
lines changed

18 files changed

+1730
-156
lines changed

src/java.base/aix/classes/sun/nio/ch/PollsetArrayWrapper.java

Lines changed: 420 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
/*
2+
* ===========================================================================
3+
* (c) Copyright IBM Corp. 2025, 2025 All Rights Reserved
4+
* ===========================================================================
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* IBM designates this particular file as subject to the "Classpath" exception
11+
* as provided by IBM in the LICENSE file that accompanied this code.
12+
*
13+
* This code is distributed in the hope that it will be useful, but WITHOUT
14+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16+
* version 2 for more details (a copy is included in the LICENSE file that
17+
* accompanied this code).
18+
*
19+
* You should have received a copy of the GNU General Public License version
20+
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
21+
*
22+
* ===========================================================================
23+
*/
24+
package sun.nio.ch;
25+
26+
import java.io.IOException;
27+
import java.nio.channels.*;
28+
import java.nio.channels.spi.*;
29+
import java.util.*;
30+
import java.util.function.Consumer;
31+
import jdk.internal.misc.*;
32+
33+
/**
34+
* An implementation of Selector for AIX 5.3+ kernels that uses
35+
* the pollset event notification facility.
36+
*/
37+
class PollsetSelectorImpl
38+
extends SelectorImpl
39+
{
40+
// File descriptors used for interrupt
41+
protected int fd0;
42+
protected int fd1;
43+
44+
// The poll object
45+
PollsetArrayWrapper pollWrapper;
46+
47+
// maps file descriptor to selection key, synchronize on selector
48+
private Map<Integer, SelectionKeyImpl> fdToKey;
49+
50+
// True if this Selector has been closed
51+
private boolean closed = false;
52+
53+
// pending updates, queued by putEventOps
54+
private final Object updateLock = new Object();
55+
private final Deque<SelectionKeyImpl> updateKeys = new ArrayDeque<>();
56+
57+
// Lock for interrupt triggering and clearing
58+
private Object interruptLock = new Object();
59+
private boolean interruptTriggered = false;
60+
61+
/**
62+
* Package private constructor called by factory method in
63+
* the abstract superclass Selector.
64+
*/
65+
PollsetSelectorImpl(SelectorProvider sp) throws IOException {
66+
super(sp);
67+
try {
68+
long pipeFds = IOUtil.makePipe(false);
69+
fd0 = (int) (pipeFds >>> 32);
70+
fd1 = (int) pipeFds;
71+
} catch (IOException ioe) {
72+
throw ioe;
73+
}
74+
75+
pollWrapper = new PollsetArrayWrapper();
76+
pollWrapper.initInterrupt(fd0, fd1);
77+
fdToKey = new HashMap<>();
78+
}
79+
80+
/*
81+
* Selects a set of keys whose corresponding channels are ready for I/O
82+
* operations.
83+
*/
84+
protected int doSelect(Consumer<SelectionKey> action, long timeout)
85+
throws IOException
86+
{
87+
if (closed)
88+
throw new ClosedSelectorException();
89+
processDeregisterQueue();
90+
try {
91+
begin();
92+
pollWrapper.poll(timeout);
93+
94+
} finally {
95+
end();
96+
}
97+
processDeregisterQueue();
98+
int numKeysUpdated = updateSelectedKeys();
99+
if (pollWrapper.getReventOps(0) != 0) {
100+
synchronized (interruptLock) {
101+
IOUtil.drain(fd0);
102+
interruptTriggered = false;
103+
}
104+
}
105+
return numKeysUpdated;
106+
}
107+
108+
109+
/**
110+
* Update the keys whose fd's have been selected by the pollset.
111+
* Add the ready keys to the ready queue.
112+
*/
113+
private int updateSelectedKeys() {
114+
int entries = pollWrapper.updated;
115+
int numKeysUpdated = 0;
116+
for (int i=0; i<entries; i++) {
117+
int nextFD = pollWrapper.getDescriptor(i);
118+
SelectionKeyImpl ski = (SelectionKeyImpl) fdToKey.get(
119+
new Integer(nextFD));
120+
// ski is null in the case of an interrupt
121+
if (ski != null) {
122+
int rOps = pollWrapper.getEventOps(i);
123+
if (selectedKeys.contains(ski)) {
124+
if (ski.channel.translateAndSetReadyOps(rOps, ski)) {
125+
numKeysUpdated++;
126+
}
127+
} else {
128+
ski.channel.translateAndSetReadyOps(rOps, ski);
129+
if ((ski.nioReadyOps() & ski.nioInterestOps()) != 0) {
130+
selectedKeys.add(ski);
131+
numKeysUpdated++;
132+
}
133+
}
134+
}
135+
}
136+
return numKeysUpdated;
137+
}
138+
139+
protected void implClose() throws IOException {
140+
if (!closed) {
141+
closed = true;
142+
FileDispatcherImpl.closeIntFD(fd0);
143+
FileDispatcherImpl.closeIntFD(fd1);
144+
if (pollWrapper != null) {
145+
146+
pollWrapper.release(fd0);
147+
pollWrapper.closePollsetFD();
148+
pollWrapper = null;
149+
selectedKeys = null;
150+
151+
// Deregister channels
152+
Iterator<SelectionKey> i = keys.iterator();
153+
while (i.hasNext()) {
154+
SelectionKeyImpl ski = (SelectionKeyImpl)i.next();
155+
deregister(ski);
156+
SelectableChannel selch = ski.channel();
157+
if (!selch.isOpen() && !selch.isRegistered())
158+
((SelChImpl)selch).kill();
159+
i.remove();
160+
}
161+
}
162+
fd0 = -1;
163+
fd1 = -1;
164+
}
165+
}
166+
167+
168+
protected void implRegister(SelectionKeyImpl ski) {
169+
int fd = IOUtil.fdVal(ski.channel.getFD());
170+
fdToKey.put(new Integer(fd), ski);
171+
pollWrapper.add(fd);
172+
keys.add(ski);
173+
}
174+
175+
protected void implDereg(SelectionKeyImpl ski) throws IOException {
176+
assert (ski.getIndex() >= 0);
177+
int fd = ski.channel.getFDVal();
178+
fdToKey.remove(new Integer(fd));
179+
pollWrapper.release(fd);
180+
ski.setIndex(-1);
181+
keys.remove(ski);
182+
selectedKeys.remove(ski);
183+
deregister((AbstractSelectionKey)ski);
184+
SelectableChannel selch = ski.channel();
185+
if (!selch.isOpen() && !selch.isRegistered())
186+
((SelChImpl)selch).kill();
187+
}
188+
189+
@Override
190+
public void setEventOps(SelectionKeyImpl ski) {
191+
// Adding this method for compilation issue
192+
}
193+
194+
public void putEventOps(SelectionKeyImpl sk, int ops) {
195+
int fd = IOUtil.fdVal(sk.channel.getFD());
196+
pollWrapper.setInterest(fd, ops);
197+
}
198+
199+
/*
200+
* Causes the Earlier selection operation that has not yet returned to return
201+
* immediately
202+
*/
203+
public Selector wakeup() {
204+
synchronized (interruptLock) {
205+
if (!interruptTriggered) {
206+
pollWrapper.interrupt();
207+
interruptTriggered = true;
208+
}
209+
}
210+
return this;
211+
}
212+
213+
static {
214+
IOUtil.load();
215+
}
216+
217+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* ===========================================================================
3+
* (c) Copyright IBM Corp. 2025, 2025 All Rights Reserved
4+
* ===========================================================================
5+
*
6+
* This code is free software; you can redistribute it and/or modify it
7+
* under the terms of the GNU General Public License version 2 only, as
8+
* published by the Free Software Foundation.
9+
*
10+
* IBM designates this particular file as subject to the "Classpath" exception
11+
* as provided by IBM in the LICENSE file that accompanied this code.
12+
*
13+
* This code is distributed in the hope that it will be useful, but WITHOUT
14+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16+
* version 2 for more details (a copy is included in the LICENSE file that
17+
* accompanied this code).
18+
*
19+
* You should have received a copy of the GNU General Public License version
20+
* 2 along with this work; if not, see <http://www.gnu.org/licenses/>.
21+
*
22+
* ===========================================================================
23+
*/
24+
package sun.nio.ch;
25+
26+
import java.io.IOException;
27+
import java.nio.channels.*;
28+
import java.nio.channels.spi.*;
29+
30+
public class PollsetSelectorProvider
31+
extends SelectorProviderImpl
32+
{
33+
public AbstractSelector openSelector() throws IOException {
34+
return new PollsetSelectorImpl(this);
35+
}
36+
37+
public Channel inheritedChannel() throws IOException {
38+
return InheritedChannel.getChannel();
39+
}
40+
}

0 commit comments

Comments
 (0)