I'd love to see Memcache API support connections via unix sockets out of the box. As I as I can tell omitting the tcp overhead and intead using socket connection one can improve memcache performance by up to 10%. (Of course, only if respective memcached daemon runs locally).

Please consider attached patch. I am running a site with said modification and have not been running into any problems so far (using memcache.db.inc).

Comments

jaydub’s picture

Status: Active » Needs review
premanup’s picture

thank you! It works for me fine.

happysnowmantech’s picture

+1 for this feature

jeremy’s picture

Status: Needs review » Closed (works as designed)

If you're using Memcache locally, why not just use APC (or another PHP-opcode cache). I believe you'll get much better performance that way, and gain some additional functionality as well.

Marking as works-as-designed.

threading_signals’s picture

Status: Closed (works as designed) » Needs review

I think this is a simple request. Drupal uses java-based apachesolr and CAS services as well, as you know, and both APC and memcached can be enabled for one machine for such a purpose (opcode & database cache).

Here's one sample of a xhprof run after restarting memcached, clearing all cache, then refreshing watchdog (admin/reports/dblog):



Regression/Improvement summary for Memcached::set

Memcached::set Run 1 Run 2 Diff Diff%
Number of Function Calls 9 10 1 11.1%
Incl. Wall Time (microsec) 153,281 30,526 -122,755 -80.1%
Incl. Wall Time (microsec) per call 17,031 3,053 -13,979 -82.1%
Excl. Wall Time (microsec) 153,281 30,526 -122,755 -80.1%
Incl. CPU (microsecs) 17,997 23,994 5,997 33.3%
Incl. CPU (microsecs) per call 2,000 2,399 400 20.0%
Excl. CPU (microsec) 17,997 23,994 5,997 33.3%
Incl. MemUse (bytes) 1,088 1,088 0 0.0%
Incl. MemUse (bytes) per call 121 109 -12 -10.0%
Excl. MemUse (bytes) 1,088 1,088 0 0.0%
Incl. PeakMemUse (bytes) 6,848 4,176 -2,672 -39.0%
Incl. PeakMemUse (bytes) per call 761 418 -343 -45.1%
Excl. PeakMemUse (bytes) 6,848 4,176 -2,672 -39.0%

There's not enough sampling, but it's a good start.

threading_signals’s picture

Note that sockets and tcp port connections can be used in conjunction.

rjbrown99’s picture

I was poking around and came across this issue. Just a note - the php-pecl-memcached package does not yet support unix sockets. So the use of this patch, if it were to be committed, would also necessitate the need to use the older php-pecl-memcache library with php.

threading_signals’s picture

I haven't been able to test the patch thoroughly, but I'm using Debian with memcached and php5-memcached, so check your packages accordingly.

ball.in.th’s picture

subscribing.

abx’s picture

Memcached PECL package version 2 beta 1 that support unix socket has been released on Mar 13.

http://pecl.php.net/package-changelog.php?package=memcached&release=2.0.0b1

- Add support for Unix domain socket connections

pillarsdotnet’s picture

I also submitted a patch for the underlying libmemcached code here:
https://bugs.launchpad.net/libmemcached/+bug/738208

Miko.’s picture

That was a pretty arrogant reply Jeremy. It doesn't work for me and I HAVE add a patch like this but I wasted half a day trying to figure out the issue (it's still not fixed) and taking sockets into consideration seems like a good way to evolve this project.

catch’s picture

Now we have wildcard support in memcache (and this isn't available in the APC project afaik), I think it makes sense to revisit this.

Although I'd rather not be parsing the strings like this - could we add a new key to the servers array or similar instead?

threading_signals’s picture

Doesn't that hardcode the file path? It could make for headaches during config time.

Peter Bowey’s picture

This Patch (top) -> http://drupal.org/files/issues/socket-connection-dmemcache.inc_.patch
works very well in conjuction with the latest SVN 'memcache' daemon V3.0.6 at http://svn.php.net/viewvc/pecl/memcache/

Release notes on the current SVN V3.0.6 memcache PECL:

Changelog for memcache: from http://pecl.php.net/package-changelog.php?package=memcache&release=3.0.6

3.0.6 - Fixed PECL Bug #16672 (memcache.php doesn't support unix socket)
- Fixed PECL Bug #19374 (memcache.php throws Notice: Undefined index: VALUE when viewing expired items)
- Fixed PECL Bug #17518 (Strange behavior in increment on non integer and after)
- Fixed potential segfault in memcache queue.

- Fixed various tests

See http://drupal.org/node/1181968 for some setup guidelines on this.

ralf.strobel’s picture

This patch works great indeed. I would really request that it is implementet, epecially since the modification required is so minor.

There are good reasons not to use APC for local caching of larger sites. Write performance and memory fragmentation management are still better using memcached. Even the developers of the APC Drupal module do not recommend using it for cache bins that can grow very large and are updated frequently.

Even if that wasn't the case, the use of unix sockets is absolutely compliant with both memcached and the php memcache(d) API. So why should it not be supported by Drupal.

Peter Bowey’s picture

Version: 6.x-1.x-dev » 6.x-1.3
Status: Needs work » Needs review

Refer #16
@ralf.strobel - concurred + agreed
@catch - This needs to be standardized

Apart from APC, I have tested that the latest XCache 1.3.2 does not suffer the fragmentation with large and frequently changing bins.

In my tests where APC was showing near high fragmentation (with resulting low performance), I then increased APC's memory limit (to 600 MB) enough to give it some slack room. Fragmentation dropped to zero, and the CPU usage on the server dropped by 50%. Note also that there seems to be a bug with apc.php's graph: http://pecl.php.net/bugs/bug.php?id=13146.

With XCache, garbage collection (gc) will clear expired items when GC counts down to 0, or when it's cache is full. A cached item is only cleared after it has expired. This is done automatically by XCache, depending on your xcache settings in php.ini. eg:

; interval of gc scanning expired items, 0=no scan, other values is in seconds
xcache.gc_interval =            900
xcache.var_gc_interval =        900
catch’s picture

Version: 6.x-1.3 » 6.x-1.x-dev
Status: Needs review » Needs work

This just about still applies to the 6.x-1.x branch, however it needs work.

        list($host, $port) = explode(':', $s);

          // enable connecting to sockets (format: 'unix:///path/to/socket:0') 
          if (strpos($s, 'unix://') === 0) {
            $host = "{$host}:{$port}"; // reassemble socket path
            $port = 0; // port must be 0 if using sockets
          }

There's no point exploding the string then putting it back together again, and the comment doesn't conform to standards.

This should be plenty:

list($host, $port) = explode(':', $s);
// Support unix sockets in the format 'unix:///path/to/socket'.
if ($host == 'unix') {
  // When using unix sockets use the full path for $host.
  $host = $s;
  // Port is always 0 for unix sockets.
  $port= 0;
}

If someone can re-roll along these lines and test it I'll commit.

Peter Bowey’s picture

Version: 6.x-1.3 » 6.x-1.x-dev
Status: Needs review » Needs work

Refer #18

Thanks @catch, as I no longer use memcache, it could be some time before I could test this.

I moved to my own custom code method with XCache bins (so much faster). I found the over-head of memcache rather high (even with Unix Sockets) for a single high performance Linux box. All my up-streams are virtual, and it boil's down to best memory use and speed with 8Gbs with a dedicated multi-core Xeon box :)

JamesK’s picture

RE: #18
This doesn't really work since when you use it, you need to remove the ":0" from the end of the memcache_servers variable in settings.php. This makes $host string different than the memcache_servers string which breaks the reports page because it can't lookup the reports.

ralf.strobel’s picture

Priority: Normal » Major
Status: Needs work » Needs review

I just patched the new 7.x-0.1 release for myself using an improved version of the old fix:

foreach ($memcache_servers as $s => $c) {
  if ($c == $cluster) {
    list($host, $port) = explode(':', $s);

    // enable connecting to sockets (format: 'unix:///path/to/socket:0') 
    if ($host == 'unix') {
      $host .= ":$port";
      $port = 0;
    }

I think this is quite the optimal solution. I'm upping the priority now, as this should really be committed. It's a shame this tiny fix didn't makt it into the stable 7.x release.

pillarsdotnet’s picture

Version: 6.x-1.x-dev » 7.x-1.x-dev
catch’s picture

Status: Needs review » Needs work

@ralf.strobel - if you want fixes to go in, it's best to supply an actual patch. See http://drupal.org/patch for instructions on how to create one.

Peter Bowey’s picture

*Smile*
Supply a 'patch' for 9 lines of code? ...... :-)
have a 'chocky bicky' for that 'extra' code push!
Release it!!
-------------------------------------------------
Oops! Sorry, my apology note + email sent to catch.
"Time to TLC the Drupal kittens"

ralf.strobel’s picture

Well, actually it's just three lines of code.
I did look into creating patches, but I have never done it and I don't have the time to install GIT now for the purpose of this. I just hope somebody finds the time to put it in.

catch’s picture

Yes it's normal practice when you want a change to be made to supply a patch, even if you're only changing one character.

If you don't do that, maintainers probably won't pay much attention to the issue, so you can either spend time complaining, submit the patch, or twiddle thumbs waiting for someone else to do it - it's up to you to decide what you think will be most effective. Since I don't personally need this feature at the moment, I don't have a particular itch to write the patch myself, and sarky comments demotivate me even more, as well as being quite busy too.

mikeytown2’s picture

Status: Needs work » Needs review
StatusFileSize
new745 bytes
new745 bytes

D6 & D7 patches.

ralf.strobel’s picture

Status: Needs review » Needs work
// Support unix sockets in the format 'unix:///path/to/socket'.
if ($host == 'unix') {
    // When using unix sockets use the full path for $host.
    $host = $s;
    // Port is always 0 for unix sockets.
    $port = 0;
}

That also makes sense. Reconstructing $host by appending the extracted $port is a bit more flexible, since it will accept hosts with or without the appended ":0". You could argue that appending the 0 port is a better generalization of the tcp syntax which has the port appended.

But in the end I don't care.

catch’s picture

Status: Needs work » Fixed

Hmm I'm fine with the patch as is, we can open a followup if necessary. So committed and pushed to both branches.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

W.M.’s picture

Issue summary: View changes

I am using Memcached and trying to connect to server via Unix socket. I am getting this error message:

Failed to connect to server at /var/run/memcached/memcached.sock:11211

I have followed the instructions and put these settings inside settings.php

$conf['memcache_servers'] = array(
   'unix:///var/run/memcached/memcached.sock' => 'cache',
   '127.0.0.1:11298' => 'session',
   '127.0.0.1:11299' => 'users'
);

I am using PHP 5.6.2. Thanks.

jeremy’s picture

@W.M. please be sure you're using the latest version of the Drupal memcache module, and file a new bug report if you still have problems; this one has already been closed.

W.M.’s picture

@Jeremy. I am using the latest Memcache Drupal module version.

sunfire-design’s picture

Sorry for reopening.

Same error with PHP 5.4.37:

Failed to connect to server at /var/run/memcached/memcached.sock:11211