Skip to content

readSemaphore not signaled immediately when data is available #19876

Description

@daniels220

Bug description
Sometimes, when receiving data over a TCP socket, there is a delay between dataAvailable starting to return true, and the readSemaphore actually being signaled. If the wait is removed, CPU usage jumps to 100% because we are constantly querying data available, but the read actually completes faster.

To Reproduce
I don't have a clean low-level reproduction, using only Socket—I haven't really tried—but there is a simple, realistic use-case that reproduces it.

  1. Install Pharo-MySQL
  2. Connect to a MySQL server
  3. Time execution of a simple query—even just [conn query: 'select "foo";'] bench "=> 6,917 iterations in 5 seconds. 1383.400 per second".
  4. Edit Socket>>waitForDataFor:ifClosed:ifTimedOut: to remove the self readSemaphore waitTimeoutMSecs: (1000 min: msecsDelta - msecsElapsed) line entirely.
  5. Benchmark again and note a significant improvement—8,620 iterations in 5 seconds. 1724.000 per second. Of course CPU usage will be 100% so this is not a viable workaround.

If you instead profile the execution of a large number of queries, you'll see a big chunk of time spent in that waitTimeoutMSecs: call as well.

Expected behavior

Similar or faster performance with the wait as without—the semaphore to be signaled immediately when dataAvailable would return true.

Version information:

  • OS: Windows for sure, I forget if I tested in Linux as well but I think so.
  • VM Version: tested in v10.0.5 and latest v12.0.3-beta. Above results are from 12.
  • Pharo Version: Tested in Pharo 11 and 14.

Expected development cost

Honestly, I'm not sure it's worth chasing down bugs like this in the plugin-based sockets implementation—this isn't the only problem, and it's much harder to maintain a plugin than code in the image. Dealing with the plugin feels likely to be a big job, and it's not something I can contribute to. I would be more in favor of replacing the plugin implementation with a pure-FFI implementation, and honestly I wouldn't be surprised if this just goes away at that point.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions