Re: HTTP/2 in massive file transfers

2016-03-08 Thread Joshua Marantz
That's a great benchmark, José.  A couple of questions:
1. When using http 1.1, is your connection over SSL?  I assume that your h2
connection is over ssl, and that might account for a speed penalty.
2. Have you tried this on other h2 implementations (h2o, nginx)?
3. Can you take some other data points?  If you just have 100 shards rather
than 1000, how does that affect the results?
4. Can you also vary the size of each shard?

Publishing your results in a more comprehensive study would be quite
valuable.

-Josh

On Tue, Mar 8, 2016 at 6:33 AM, Molina  wrote:

> Hello,
>
> I’m testing the HTTP/2 performance to add support to the software I’m
> working for. My benchmark consist on an apache 2.4.17 server with the
> following http2-related configuration:
>
> LoadModule http2_module modules/mod_http2.so
> 
>   Protocols h2c http/1.1
>   H2WindowSize 146000
>   H2StreamMaxMemSize 146000
>   H2MinWorkers 8
>   H2Direct on
>   LogLevel http2:info
>   H2MaxSessionStreams 100
>   H2SessionExtraFiles 1000
>   H2MaxWorkers 100
> 
>
> The rest is simply the default apache configuration.
> My client is a C application that downloads 1024 files of exactly 1MiB
> each, so totally 1GB. When performing the test with normal HTTP/1.1 the
> download speed is around 20MiB/s, while when using HTTP/2 is 1.5MiB/s. The
> client uses exactly one  multiplexed connection and works as expected
> Lastly, the client and server are located in center Europe and center USA
> respectively to increase the impact of opening many HTTP/1.1 connections
> with such a high physical distance due to latency.
>
> I tried to increase the Linux window size, as well as the TCP buffer to
> increase the download speed, but without success so far.
>
> Is there some configuration parameter I’m missing to make it perform
> better? Or perhaps the module itself needs an special configuration for
> such a use case?
>
> Thanks a lot in advance. Best regards,
> José Molina
>
>


Re: Sharing information across Apache child processes

2014-09-30 Thread Joshua Marantz
There's a variation on this theme you might consider.  You can use a few
counters in shared memory, and save config information in a file.  If one
of the child processes learns of a config update (say by handling an HTTP
request for one from somewhere) it can update the file (atomically, say,
via write-to-temp-and-rename) and bump a shared-memory counter (atomically
via shared-memory mutex).  Other child processes can quickly poll on
counter-changes and re-read config files when they change.

The advantage of this approach over storing the whole config in
shared-memory is that we only put a fixed number of integers in shared
memory, rather than our whole configuration structure, which might be large
or vary in size depending on the config.

mod_pagespeed uses this technique
https://code.google.com/p/modpagespeed/source/browse/trunk/src/pagespeed/kernel/cache/purge_context.h.
Note there is no apr code directly in that file as it's abstracted behind
some C++ interfaces, but 'Variable' is really an int64's worth of mutexed
shared memory in operation.

-Josh


-

On Tue, Sep 30, 2014 at 9:20 AM, Abdi Abdirahman abd.moha...@gmail.com
wrote:

 On 09/29/2014 05:14 PM, Sorin Manolache wrote:

 On 2014-09-29 13:39, Rajalakshmi Iyer wrote:

 Hello,

 I have a requirement whereby my application's configuration information
 (comprising a few complex data structures) needs to be shared across the
 various Apache child processes.

 Currently, the configuration is being individually loaded by each child
 process, which makes it hard for configuration changes to propagate.

 What is the best way / place to have a common configuration for the
 application?

 Please advise.


 I suppose you want to update the configuration without running apache2
 -k graceful (or apache2ctl graceful).

 In this case you could use a segment of memory that is shared across the
 apache children. You'll have to create the shared segment memory before the
 parent forks its children (for example in post_config). The shared memory
 is then inherited by the forked children.

 You'll need a method to update the contents of the shared memory segment
 and a multiple-readers-single-writer inter-process exclusion mechanism in
 order to safely read and write from the shared segment.

 Sorin

  Hello All,

 You can check out mod_cluster approach (https://github.com/
 modcluster/mod_cluster/tree/master/native/mod_proxy_cluster) - it uses
 shared memory as data storage and additional thread per process to check
 updates in storage. This way you'll keep per-process module config in sync
 with shared data.
 Not perfect solution though, but I doubt that there is any flawless way to
 share config structures.

 
 Best regards,
 Abdi A.



Re: sequence of request

2014-07-24 Thread Joshua Marantz
Yes, in particular, the gdb feature that can help determine who is changing
r-filename is hardware watchpoints:
http://sourceware.org/gdb/onlinedocs/gdb/Set-Watchpoints.html

1. Set a breakpoint at a line of code where you believe r-filename is
correct
2. Start up Apache with run -X
3. Issue a request to the server to hit the line of code where r-filename
is set.
4. Set up a hardware watchpoint with
  (gdb) p r-filename
  $1 = (char**) 0x
  (gdb) watch *$1
  Hardware Watchpoint 2

Depending on what you've done in the debugger beforehand, the $1 may be
something like $3 or $4.  In that case use watch *$3, etc.

-Josh


On Thu, Jul 24, 2014 at 6:54 AM, Eric Covener cove...@gmail.com wrote:

 On Thu, Jul 24, 2014 at 12:51 AM, Donatas Abraitis
 donatas.abrai...@gmail.com wrote:
  Hello guys,
 
  is it possible to know the sequence of request is handled? I mean which
  module takes precedence? Because I need to debug why r-filename becomes
  not so as I expected.

 mod_info shows you the order the loaded modules will run in for
 various phases.  A debugger can also tell you when it changes.

 --
 Eric Covener
 cove...@gmail.com



associating an object with a request

2014-04-23 Thread Joshua Marantz
Hi,

I want to create a data structure and associate it with a request_rec*,
which will be accessed by multiple filters and handlers in our module.

I know I can use the filter-ctx for general data structure storage, but I
actually want something that will be accessed by multiple filters and
handlers without having to rebuild it.  Currently our module
(mod_pagespeed) rebuilds the same context multiple times and this can be a
little more compute-intensive than desired.

Of course I can make my own std::maprequest_rec*, MyAwesomeStructure* and
put the map in my own module config, cleaning up and freeing my structure
when the request_rec's pool is deleted via a hook.

But I wanted to see if there was a more direct place to stash pointers.

I also know I can put strings in request-notes but I need to put a data
structure, not a string.

Is there an easy way to do this?  Or should I use a map?

-Josh


Re: associating an object with a request

2014-04-23 Thread Joshua Marantz
Thanks Eric.  That looks perfect!  I'll give it a try.

On Wed, Apr 23, 2014 at 4:34 PM, Eric Covener cove...@gmail.com wrote:

 On Wed, Apr 23, 2014 at 4:31 PM, Joshua Marantz jmara...@google.com
 wrote:
 
  I want to create a data structure and associate it with a request_rec*,
  which will be accessed by multiple filters and handlers in our module.

 You can allocate your structure from r-pool and associate it with the
 current request with ap_get|set_module_config(r-request_config,
 your-module)

 --
 Eric Covener
 cove...@gmail.com



Re: problem with different version of openssl in Apache and apache module

2013-12-20 Thread Joshua Marantz
We faced this exact issue (openssl clashes with other linked-in versions)
in mod_pagespeed and ngx_pagespeed, its nginx equivalent.

We solved this problem in our Apache module because we linked
mod_pagespeed.so hiding all the symbols other than the module entry-point
into Apache.  Here's the link command:

g++ -shared -pthread -Wl,-z,noexecstack -fPIC \
-Wl,--version-script=build/mod_pagespeed.map  \
-Wl,-soname=libmod_pagespeed.so \
-o out/Debug/obj.target/net/instaweb/libmod_pagespeed.so \
-Wl,--start-group \
object file list . \
-Wl,--end-group -lrt

Where mod_pagespeed.map contains:

{
  /* Make sure we don't export anything unneeded */
  global: pagespeed_module;
  local: *;
};

In nginx we didn't have such a clean solution, since nginx just uses a flat
link of .o files.  Our resolution is in this script:
https://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/automatic/rename_c_symbols.sh.
 This script is specific to our purpose but it might contain enough ideas
that you could hack it to meet yours.

This script is applied to a .a file that includes the definition and use
of a version of openssl.  It simply renames all the C symbols in the .a,
leaving the C++ ones intact, and this works for us because the .a in
question has a C++ interface.  You could hack the script to just rename the
openssl symbols and your use of them, and you can extract the list of
openssl symbols by grepping the output of nm libopenssl.a, following some
of the patterns in our rename_c_symbols.sh script.

-Josh


On Fri, Dec 20, 2013 at 5:57 AM, Rainer Jung rainer.j...@kippdata.dewrote:

 On 20.12.2013 10:51, Alex Bligh wrote:
 
  On 19 Dec 2013, at 19:29, Hong wrote:
 
  I wrote an Apache module that call functions in openssl library to sign
 the
  messages. The module is dynamic linked to openssl library 1.0.1d when I
  built it. It works fine when it is loaded into the Apache that was also
  built with the same version of openssl. But if Apache was built with
 openssl
  0.9.8x, segfault occurred. Is there anything I can do for my built so it
  also works in the Apache which was built with older version of openssl?
 
  Static link to openssl?

 That often doesn't help, because the runtime linker by default searches
 symbols in load order. So if mod_ssl was linked against OpenSSL 0.9.8
 and mod_xyz was linked against 1.0.1 and mod_ssl gets loaded before
 mod_xyz, then OpenSSL 0.9.8 gets also loaded before (either as a shared
 lib or as statically linked into mod_ssl). Now when later the runtime
 linker needs to resolve an OpenSSL symbol (e.g. function name) because
 it is used in mod_xyz it will first look in OpenSSL 0.9.8 for the symbol
 and only if not found there in 1.0.1.

 AFAIK there's no really good solution. Some platforms support symbolic
 linking (ld -Bsymbolic), which changes the search order for the runtime
 linker. With symbolic linking the runtime linker first looks into the
 dependencies of the component needing a symbol before searching through
 everything in load order. That means symbols needed by mod_xyz would
 indeed be searched in OpenSSL 1.0.1 first and in OpenSSL 0.9.8 only as a
 fallback. Note that this isn't the same as a symbolic file system link.
 There's a couple of negative side effects though.

 Another solution should be possible using a linker script but to
 implement that you would need to do quite a bit of work integrating the
 linker script into the OpenSSL build.

 All of this is somehow fragile. It should be more robust to support
 different combinations with different builds.

 As pointers have a look at:

 https://sourceware.org/binutils/docs-2.24/ld/Options.html#Options

 (short description of ld -Bsymbolic)

 http://www.akkadia.org/drepper/dsohowto.pdf

 (search for symbolic, detailed explanations)


 http://www.macieira.org/blog/2012/01/sorry-state-of-dynamic-libraries-on-linux/


 http://software.intel.com/en-us/articles/performance-tools-for-software-developers-bsymbolic-can-cause-dangerous-side-effects

 http://docs.oracle.com/cd/E19683-01/817-3677/817-3677.pdf

 Mostly about Solaris but nevertheless full of interesting stuff.

 Regards,

 Rainer



Re: Apache Buckets and Brigade

2013-05-01 Thread Joshua Marantz
I have a crazy idea for you.  Maybe this is overkill but this sounds like
it'd be natural to add to mod_pagespeed http://modpagespeed.com as a new
filter.

Here's some code you might use as a template

https://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/rewriter/collapse_whitespace_filter.cc

one thing we've thought of doing is providing a generic text-substitution
filter that would take strings in character-blocks and do arbitrary
substitutions in them, that could be specified in the .conf file:
  ModPagespeedSubstitute oldString newString

You are right that text-blocks in Apache output filters can be split
arbitrarily across buckets, but mod_pagespeed takes care of that in an
HTML-centric way, breaking up blocks on html tokens. A block of free-format
text would be treated as a single atomic token independent of the structure
of the incoming bucket brigade.

Let me know if you'd like to discuss this further.

-Josh


On Wed, May 1, 2013 at 8:54 AM, Sindhi Sindhi sindhi@gmail.com wrote:

 Hello,

 Thanks a lot for providing answers to my earlier emails with subject
 Apache C++ equivalent of javax.servlet.Filter. I really appreciate your
 help.

 I had another question. My requirement is something like this -

 I have a huge html file that I have copied into the Apache htdocs folder.
 In my C++ Apache module, I want to get this html file contents and
 remove/replace some strings.

 Say I have a HTML file that has the string oldString appearing 3 times in
 the file. My requirement is to replace oldString with the new string
 newString. I have already written a C++ function that has a signature
 like this -

 char* processHTML(char* inHTMLString) {
 //
 char* newHTMLWithNewString = code to replace all occurrences of
 oldString with newString
 return newHTMLWithNewString;
 }

 The above function does a lot more than just string replace, it has lot of
 business logic implemented and finally returns the new HTML string.

 I want to call processHTML() inside my C++ Apache module. As I know Apache
 maintains an internal data structure called Buckets and Brigades which
 actually contain the HTML file data. My question is, is the entire HTML
 file content (in my case the html file is huge) residing in a single
 bucket? Means, when I fetch one bucket at a time from a brigade, can I be
 sure that the entire HTML file data from html to /html can be found in
 a single bucket? For ex. if my html file looks like this -
 html
 ..
 ..
 oldString
 ... oldString...oldString..
 ..
 /html

 When I iterate through all buckets of a brigade, will I find my entire HTML
 file content in a single bucket OR the HTML file content can be present in
 multiple buckets, say like this -

 case1:
 bucket-1 contents =
 html
 ..
 ..
 oldString
 ... oldString...oldString..
 ..
 /html

 case2:
 bucket-1 contents =
 html
 ..
 ..
 oldStr

 bucket-2 contents =
 ing
 ... oldString...oldString..
 ..
 /html

 If its case2, then the the function processHTML() I have written will not
 work because it searches for the entire string oldString and in case2
 oldString is found only partially.

 Thanks a lot.



Re: Apache Buckets and Brigade

2013-05-01 Thread Joshua Marantz
On Wed, May 1, 2013 at 12:14 PM, Sindhi Sindhi sindhi@gmail.com wrote:

 Thanks to all for the reply.

 Josh, the concern I mentioned was, we may not want mod_pagespeed to modify
 the in-memory HTML content. The only change we may want to see in our HTML
 will be that the old strings are replaced by the new strings after applying
 our business logic which is already done by the C++ filter module I have
 written. This C++ filter implements all our business logic and takes an
 input buffer that is expected to be the entire HTML file content. So the


Yeah the filter I gave you gives you only a block of HTML characters.  E.g.
if you have
  diva b c d ie/i f/div
then you'll get this as 3 calls to Characters: a b c d , e, and  f.
 Other than that, the Characters method I pointed you to has exactly the
interface you asked for: it gets you an entire block of HTML text in one
modifiable std::string which you can mutate at will.  And it irons out all
the brigade stuff for you.

You can configure mod_pagespeed to run just one filter so no other
modifications are made.

But it looks like you probably need to read Nick's book.  You can also read
mod_deflate.c or one of the other content-modifying filters such as mod_sed
or mod_substitute.

-Josh


Re: apr_memcache operation timeouts

2013-03-22 Thread Joshua Marantz
Thanks very much for doing this, Jeff.

Unfortunately scanning your diff I think you wound up taking a snapshot of
a patch I'd uploaded to the bug, but not updated after several subsequent
bug fixes.

The golden copies are in
https://code.google.com/p/modpagespeed/source/browse/#svn%2Ftrunk%2Fsrc%2Fthird_party%2Faprutil:

https://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.c
https://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.h

After we released our module we had a few small tweaks and bug-fixes based
on external feedback for our module.  Those versions have now been stable
for 3.5 months, with multiple users reporting success with our memcached
integration, so I'm hopeful that they have settled into a stable state.

What's the best way to go from here?

-Josh


On Thu, Mar 14, 2013 at 10:45 AM, Jeff Trawick traw...@gmail.com wrote:

 On Tue, Mar 12, 2013 at 1:56 PM, Jeff Trawick traw...@gmail.com wrote:
  On Mon, Mar 11, 2013 at 3:50 PM, Joshua Marantz jmara...@google.com
 wrote:
 
  ping!
 
  Please don't hesitate to push back and tell me if I can supply the patch
  or
  update in some easier-to-digest form.  In particular, while I have
  rigorously stress-tested this change using mod_pagespeed's unit test,
  system-test, and load-test framework, I don't really understand what the
  testing flow is for APR.  I'd be happy to add unit-tests for that if
  someone points me to a change-list or patch-file that does it properly.
 
  -Josh
 
 
  I'll try hard to work on this in the next couple of days.  It would be
 great
  to have fixes in APR-Util 1.5.x, which we hope to work on later this
 week.

 Attached is a first pass at getting your patch to apr trunk.  Can you
 confirm that I didn't break your tests?  (It passes the apr tests, but
 that may not mean much.)



 
 
 
  On Thu, Nov 1, 2012 at 8:04 AM, Joshua Marantz jmara...@google.com
  wrote:
 
   I have completed a solution to this problem, which can be a drop-in
   update
   for the existing apr_memcache.c.  It is now checked in for my module
 as
  
  
 http://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.c
   .
  
   It differs from the solution in
   https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 in that:
  
  - It doesn't require an API change; it but it enforces the 50ms
  timeout that already exists for apr_multgetp for all operations.
  - It works under my load test (which I found is not true of the
 patch
  in 51065).
  
   For my own purposes, I will be shipping my module with apr_memcache2
 so
   I
   get the behavior I want regardless of what version of Apache is
   installed.
But I'd like to propose my patch for apr_memcache.c.  The patch is
   attached, and I've also submitted it as an alternative patch to bug
   51065.
  
   If you agree with the strategy I used to solve this problem, then
 please
   let me know if I can help with any changes required to get this into
 the
   main distribution,
  
  
   On Mon, Oct 22, 2012 at 5:21 PM, Joshua Marantz
   jmara...@google.comwrote:
  
   I've had some preliminary success with my own variant of
 apr_memcache.c
   (creatively called apr_memcache2.c).  Rather than setting the socket
   timeout, I've been mimicing the timeout strategy I saw in
   apr_memcache_multgetp, by adding a new helper method:
  
   static apr_status_t wait_for_server_or_timeout(apr_pool_t* temp_pool,
  apr_memcache2_conn_t*
   conn) {
   apr_pollset_t* pollset;
   apr_status_t rv = apr_pollset_create(pollset, 1, temp_pool, 0);
   if (rv == APR_SUCCESS) {
   apr_pollfd_t pollfd;
   pollfd.desc_type = APR_POLL_SOCKET;
   pollfd.reqevents = APR_POLLIN;
   pollfd.p = temp_pool;
   pollfd.desc.s = conn-sock;
   pollfd.client_data = NULL;
   apr_pollset_add(pollset, pollfd);
   apr_int32_t queries_recvd;
   const apr_pollfd_t* activefds;
   rv = apr_pollset_poll(pollset, MULT_GET_TIMEOUT,
   queries_recvd,
 activefds);
   if (rv == APR_SUCCESS) {
   assert(queries_recvd == 1);
   assert(activefds-desc.s == conn-sock);
   assert(activefds-client_data == NULL);
   }
   }
   return rv;
   }
  
   And calling that before many of the existing calls to get_server_line
   as:
  
   rv = wait_for_server_or_timeout_no_pool(conn);
   if (rv != APR_SUCCESS) {
   ms_release_conn(ms, conn);
   return rv;
   }
  
   This is just an experiment; I think I can streamline this by
   pre-populating the pollfd structure as part of the
 apr_memcache_conn_t
   (actually now apr_memcache2_conn_t).
  
   I have two questions about this:
  
   1. I noticed the version of apr_memcache.c that ships with Apache 2.4
   is
   somewhat

Re: apr_memcache operation timeouts

2013-03-11 Thread Joshua Marantz
ping!

Please don't hesitate to push back and tell me if I can supply the patch or
update in some easier-to-digest form.  In particular, while I have
rigorously stress-tested this change using mod_pagespeed's unit test,
system-test, and load-test framework, I don't really understand what the
testing flow is for APR.  I'd be happy to add unit-tests for that if
someone points me to a change-list or patch-file that does it properly.

-Josh


On Thu, Nov 1, 2012 at 8:04 AM, Joshua Marantz jmara...@google.com wrote:

 I have completed a solution to this problem, which can be a drop-in update
 for the existing apr_memcache.c.  It is now checked in for my module as
 http://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.c
 .

 It differs from the solution in
 https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 in that:

- It doesn't require an API change; it but it enforces the 50ms
timeout that already exists for apr_multgetp for all operations.
- It works under my load test (which I found is not true of the patch
in 51065).

 For my own purposes, I will be shipping my module with apr_memcache2 so I
 get the behavior I want regardless of what version of Apache is installed.
  But I'd like to propose my patch for apr_memcache.c.  The patch is
 attached, and I've also submitted it as an alternative patch to bug 51065.

 If you agree with the strategy I used to solve this problem, then please
 let me know if I can help with any changes required to get this into the
 main distribution,


 On Mon, Oct 22, 2012 at 5:21 PM, Joshua Marantz jmara...@google.comwrote:

 I've had some preliminary success with my own variant of apr_memcache.c
 (creatively called apr_memcache2.c).  Rather than setting the socket
 timeout, I've been mimicing the timeout strategy I saw in
 apr_memcache_multgetp, by adding a new helper method:

 static apr_status_t wait_for_server_or_timeout(apr_pool_t* temp_pool,
apr_memcache2_conn_t*
 conn) {
 apr_pollset_t* pollset;
 apr_status_t rv = apr_pollset_create(pollset, 1, temp_pool, 0);
 if (rv == APR_SUCCESS) {
 apr_pollfd_t pollfd;
 pollfd.desc_type = APR_POLL_SOCKET;
 pollfd.reqevents = APR_POLLIN;
 pollfd.p = temp_pool;
 pollfd.desc.s = conn-sock;
 pollfd.client_data = NULL;
 apr_pollset_add(pollset, pollfd);
 apr_int32_t queries_recvd;
 const apr_pollfd_t* activefds;
 rv = apr_pollset_poll(pollset, MULT_GET_TIMEOUT, queries_recvd,
   activefds);
 if (rv == APR_SUCCESS) {
 assert(queries_recvd == 1);
 assert(activefds-desc.s == conn-sock);
 assert(activefds-client_data == NULL);
 }
 }
 return rv;
 }

 And calling that before many of the existing calls to get_server_line as:

 rv = wait_for_server_or_timeout_no_pool(conn);
 if (rv != APR_SUCCESS) {
 ms_release_conn(ms, conn);
 return rv;
 }

 This is just an experiment; I think I can streamline this by
 pre-populating the pollfd structure as part of the apr_memcache_conn_t
 (actually now apr_memcache2_conn_t).

 I have two questions about this:

 1. I noticed the version of apr_memcache.c that ships with Apache 2.4 is
 somewhat different from the one that ships with Apache 2.2.  In particular
 the 2.4 version cannot be compiled against the headers that come with a 2.2
 distribution.  Is there any downside to taking my hacked 2.2 apr_memcache.c
 and running it in Apache 2.4?  Or should I maintain two hacks?

 2. This seems wasteful in terms of system calls.  I am making an extra
 call to poll, rather than relying on the socket timeout.  The socket
 timeout didn't work as well as this though.  Does anyone have any theories
 as to why, or what could be done to the patch in
 https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 to work?

 -Josh


 On Fri, Oct 19, 2012 at 9:25 AM, Joshua Marantz jmara...@google.comwrote:

 Following up: I tried doing what I suggested above: patching that change
 into my own copy of apr_memcache.c  It was first of all a bad idea to pull
 in only part of apr_memcache.c because that file changed slightly between
 2.2 and 2.4 and our module works in both.

 I was successful making my own version of apr_memcache (renaming
 entry-points apr_memcache2*) that I could hack.  But if I changed the
 socket timeout from -1 to 10 seconds, then the system behaved very poorly
 under load test (though it worked fine in our unit-tests and system-tests).
  In other words, I think the proposed patch that Jeff pointed to above is
 not really working (as he predicted).  This test was done without
 SIGSTOPing the memcached; it would timeout under our load anyway and
 thereafter behave poorly.

 I'm going to follow up on that bugzilla entry, but for now I'm going to
 pursue my own complicated mechanism of timing out the calls

Re: apr_memcache operation timeouts

2012-11-01 Thread Joshua Marantz
I have completed a solution to this problem, which can be a drop-in update
for the existing apr_memcache.c.  It is now checked in for my module as
http://code.google.com/p/modpagespeed/source/browse/trunk/src/third_party/aprutil/apr_memcache2.c
.

It differs from the solution in
https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 in that:

   - It doesn't require an API change; it but it enforces the 50ms timeout
   that already exists for apr_multgetp for all operations.
   - It works under my load test (which I found is not true of the patch in
   51065).

For my own purposes, I will be shipping my module with apr_memcache2 so I
get the behavior I want regardless of what version of Apache is installed.
 But I'd like to propose my patch for apr_memcache.c.  The patch is
attached, and I've also submitted it as an alternative patch to bug 51065.

If you agree with the strategy I used to solve this problem, then please
let me know if I can help with any changes required to get this into the
main distribution,


On Mon, Oct 22, 2012 at 5:21 PM, Joshua Marantz jmara...@google.com wrote:

 I've had some preliminary success with my own variant of apr_memcache.c
 (creatively called apr_memcache2.c).  Rather than setting the socket
 timeout, I've been mimicing the timeout strategy I saw in
 apr_memcache_multgetp, by adding a new helper method:

 static apr_status_t wait_for_server_or_timeout(apr_pool_t* temp_pool,
apr_memcache2_conn_t* conn)
 {
 apr_pollset_t* pollset;
 apr_status_t rv = apr_pollset_create(pollset, 1, temp_pool, 0);
 if (rv == APR_SUCCESS) {
 apr_pollfd_t pollfd;
 pollfd.desc_type = APR_POLL_SOCKET;
 pollfd.reqevents = APR_POLLIN;
 pollfd.p = temp_pool;
 pollfd.desc.s = conn-sock;
 pollfd.client_data = NULL;
 apr_pollset_add(pollset, pollfd);
 apr_int32_t queries_recvd;
 const apr_pollfd_t* activefds;
 rv = apr_pollset_poll(pollset, MULT_GET_TIMEOUT, queries_recvd,
   activefds);
 if (rv == APR_SUCCESS) {
 assert(queries_recvd == 1);
 assert(activefds-desc.s == conn-sock);
 assert(activefds-client_data == NULL);
 }
 }
 return rv;
 }

 And calling that before many of the existing calls to get_server_line as:

 rv = wait_for_server_or_timeout_no_pool(conn);
 if (rv != APR_SUCCESS) {
 ms_release_conn(ms, conn);
 return rv;
 }

 This is just an experiment; I think I can streamline this by
 pre-populating the pollfd structure as part of the apr_memcache_conn_t
 (actually now apr_memcache2_conn_t).

 I have two questions about this:

 1. I noticed the version of apr_memcache.c that ships with Apache 2.4 is
 somewhat different from the one that ships with Apache 2.2.  In particular
 the 2.4 version cannot be compiled against the headers that come with a 2.2
 distribution.  Is there any downside to taking my hacked 2.2 apr_memcache.c
 and running it in Apache 2.4?  Or should I maintain two hacks?

 2. This seems wasteful in terms of system calls.  I am making an extra
 call to poll, rather than relying on the socket timeout.  The socket
 timeout didn't work as well as this though.  Does anyone have any theories
 as to why, or what could be done to the patch in
 https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 to work?

 -Josh


 On Fri, Oct 19, 2012 at 9:25 AM, Joshua Marantz jmara...@google.comwrote:

 Following up: I tried doing what I suggested above: patching that change
 into my own copy of apr_memcache.c  It was first of all a bad idea to pull
 in only part of apr_memcache.c because that file changed slightly between
 2.2 and 2.4 and our module works in both.

 I was successful making my own version of apr_memcache (renaming
 entry-points apr_memcache2*) that I could hack.  But if I changed the
 socket timeout from -1 to 10 seconds, then the system behaved very poorly
 under load test (though it worked fine in our unit-tests and system-tests).
  In other words, I think the proposed patch that Jeff pointed to above is
 not really working (as he predicted).  This test was done without
 SIGSTOPing the memcached; it would timeout under our load anyway and
 thereafter behave poorly.

 I'm going to follow up on that bugzilla entry, but for now I'm going to
 pursue my own complicated mechanism of timing out the calls from my side.

 -Josh


 On Thu, Oct 18, 2012 at 10:46 AM, Joshua Marantz jmara...@google.comwrote:

 Thanks Jeff, that is very helpful.  We are considering a course of
 action and before doing any work toward this, I'd like to understand the
 pitfalls from people that understand Apache better than us.

 Here's our reality: we believe we need to incorporate memcached for
 mod_pagespeed http://modpagespeed.com to scale effectively for very
 large sites  hosting providers.  We are fairly close (we think) to
 releasing

Forcing Apache to exit on startup

2012-10-22 Thread Joshua Marantz
Hi,

Our module has multiple confirmation parameters.  There is a case where if
you have option A and option B, then you must also specify option C,
otherwise Bad things can happen that are a lot easier to debug on startup
than they are after the server is running.

I know how to force 'apachectl' to exit with a nice error message if I
don't like the value of option A or option B.  I can do that in the
function-pointer I provide in my option-table by returning a non-null char*
message.

But in this case I want to exit nicely from the function I have registered
with ap_hook_child_init, having noticed that option A and B are set but not
C.  Is that possible?

By nicely, I mean that the user types:

% sudo /etc/init.d/apachectl restart
Error in pagespeed.conf: if you have option A and B specified, you must
specify a value for option C.

At that point either the server would not be running, or it would still be
in whatever state it was previously in.

Is this possible?

Currently our solution is to log an error and call abort(), and it's not
very nice!

-Josh


Re: apr_memcache operation timeouts

2012-10-22 Thread Joshua Marantz
I've had some preliminary success with my own variant of apr_memcache.c
(creatively called apr_memcache2.c).  Rather than setting the socket
timeout, I've been mimicing the timeout strategy I saw in
apr_memcache_multgetp, by adding a new helper method:

static apr_status_t wait_for_server_or_timeout(apr_pool_t* temp_pool,
   apr_memcache2_conn_t* conn) {
apr_pollset_t* pollset;
apr_status_t rv = apr_pollset_create(pollset, 1, temp_pool, 0);
if (rv == APR_SUCCESS) {
apr_pollfd_t pollfd;
pollfd.desc_type = APR_POLL_SOCKET;
pollfd.reqevents = APR_POLLIN;
pollfd.p = temp_pool;
pollfd.desc.s = conn-sock;
pollfd.client_data = NULL;
apr_pollset_add(pollset, pollfd);
apr_int32_t queries_recvd;
const apr_pollfd_t* activefds;
rv = apr_pollset_poll(pollset, MULT_GET_TIMEOUT, queries_recvd,
  activefds);
if (rv == APR_SUCCESS) {
assert(queries_recvd == 1);
assert(activefds-desc.s == conn-sock);
assert(activefds-client_data == NULL);
}
}
return rv;
}

And calling that before many of the existing calls to get_server_line as:

rv = wait_for_server_or_timeout_no_pool(conn);
if (rv != APR_SUCCESS) {
ms_release_conn(ms, conn);
return rv;
}

This is just an experiment; I think I can streamline this by pre-populating
the pollfd structure as part of the apr_memcache_conn_t (actually now
apr_memcache2_conn_t).

I have two questions about this:

1. I noticed the version of apr_memcache.c that ships with Apache 2.4 is
somewhat different from the one that ships with Apache 2.2.  In particular
the 2.4 version cannot be compiled against the headers that come with a 2.2
distribution.  Is there any downside to taking my hacked 2.2 apr_memcache.c
and running it in Apache 2.4?  Or should I maintain two hacks?

2. This seems wasteful in terms of system calls.  I am making an extra call
to poll, rather than relying on the socket timeout.  The socket timeout
didn't work as well as this though.  Does anyone have any theories as to
why, or what could be done to the patch in
https://issues.apache.org/bugzilla/show_bug.cgi?id=51065 to work?

-Josh


On Fri, Oct 19, 2012 at 9:25 AM, Joshua Marantz jmara...@google.com wrote:

 Following up: I tried doing what I suggested above: patching that change
 into my own copy of apr_memcache.c  It was first of all a bad idea to pull
 in only part of apr_memcache.c because that file changed slightly between
 2.2 and 2.4 and our module works in both.

 I was successful making my own version of apr_memcache (renaming
 entry-points apr_memcache2*) that I could hack.  But if I changed the
 socket timeout from -1 to 10 seconds, then the system behaved very poorly
 under load test (though it worked fine in our unit-tests and system-tests).
  In other words, I think the proposed patch that Jeff pointed to above is
 not really working (as he predicted).  This test was done without
 SIGSTOPing the memcached; it would timeout under our load anyway and
 thereafter behave poorly.

 I'm going to follow up on that bugzilla entry, but for now I'm going to
 pursue my own complicated mechanism of timing out the calls from my side.

 -Josh


 On Thu, Oct 18, 2012 at 10:46 AM, Joshua Marantz jmara...@google.comwrote:

 Thanks Jeff, that is very helpful.  We are considering a course of action
 and before doing any work toward this, I'd like to understand the pitfalls
 from people that understand Apache better than us.

 Here's our reality: we believe we need to incorporate memcached for
 mod_pagespeed http://modpagespeed.com to scale effectively for very
 large sites  hosting providers.  We are fairly close (we think) to
 releasing this functionality as beta.  However, in such large sites, stuff
 goes wrong: machines crash, power failure, fiber cut, etc.  When it does we
 want to fall back to serving partially unoptimized sites rather than
 hanging the servers.

 I understand the realities of backward-compatible APIs.  My expectation
 is that this would take years to make it into an APR distribution we could
 depend on.  We want to deploy this functionality in weeks.  The workarounds
 we have tried backgrounding the apr_memcache calls in a thread and timing
 out in mainline are complex and even once they work 100% will be very
 unsatisfactory (resource leaks; Apache refusing to exit cleanly on
 'apachectl stop') if this happens more than (say) once a month.

 Our plan is to copy the patched implementation of
 apr_memcache_server_connect and the static methods it calls into a new .c
 file we will link into our module, naming the new entry-point something
 else (apr_memcache_server_connect_with_timeout seems good).  From a
 CS/SE perspective this is offensive and we admit it, but from a product
 quality perspective we believe this beats freezes and complicated/imperfect

Re: apr_memcache operation timeouts

2012-10-19 Thread Joshua Marantz
Following up: I tried doing what I suggested above: patching that change
into my own copy of apr_memcache.c  It was first of all a bad idea to pull
in only part of apr_memcache.c because that file changed slightly between
2.2 and 2.4 and our module works in both.

I was successful making my own version of apr_memcache (renaming
entry-points apr_memcache2*) that I could hack.  But if I changed the
socket timeout from -1 to 10 seconds, then the system behaved very poorly
under load test (though it worked fine in our unit-tests and system-tests).
 In other words, I think the proposed patch that Jeff pointed to above is
not really working (as he predicted).  This test was done without
SIGSTOPing the memcached; it would timeout under our load anyway and
thereafter behave poorly.

I'm going to follow up on that bugzilla entry, but for now I'm going to
pursue my own complicated mechanism of timing out the calls from my side.

-Josh


On Thu, Oct 18, 2012 at 10:46 AM, Joshua Marantz jmara...@google.comwrote:

 Thanks Jeff, that is very helpful.  We are considering a course of action
 and before doing any work toward this, I'd like to understand the pitfalls
 from people that understand Apache better than us.

 Here's our reality: we believe we need to incorporate memcached for
 mod_pagespeed http://modpagespeed.com to scale effectively for very
 large sites  hosting providers.  We are fairly close (we think) to
 releasing this functionality as beta.  However, in such large sites, stuff
 goes wrong: machines crash, power failure, fiber cut, etc.  When it does we
 want to fall back to serving partially unoptimized sites rather than
 hanging the servers.

 I understand the realities of backward-compatible APIs.  My expectation is
 that this would take years to make it into an APR distribution we could
 depend on.  We want to deploy this functionality in weeks.  The workarounds
 we have tried backgrounding the apr_memcache calls in a thread and timing
 out in mainline are complex and even once they work 100% will be very
 unsatisfactory (resource leaks; Apache refusing to exit cleanly on
 'apachectl stop') if this happens more than (say) once a month.

 Our plan is to copy the patched implementation of
 apr_memcache_server_connect and the static methods it calls into a new .c
 file we will link into our module, naming the new entry-point something
 else (apr_memcache_server_connect_with_timeout seems good).  From a CS/SE
 perspective this is offensive and we admit it, but from a product quality
 perspective we believe this beats freezes and complicated/imperfect
 workarounds with threads.

 So I have two questions for the Apache community:

1. What are the practical problems with this approach?  Note that in
any case a new APR rev would require editing/ifdefing our code anyway, so I
think immunity from APR updates such as this patch being applied is not a
distinguishing drawback.
2. Is there an example of the correct solution to the technical
problem Jeff highlighted: it is apparently missing a call to adjust
the socket timeout and to discard the connection if the timeout is 
 reached.
 That sounds like a pattern that might be found elsewhere in the Apache
HTTPD code base.

 Thanks in advance for your help!
 -Josh


 On Wed, Oct 17, 2012 at 8:16 PM, Jeff Trawick traw...@gmail.com wrote:

 On Wed, Oct 17, 2012 at 3:36 PM, Joshua Marantz jmara...@google.com
 wrote:
  Is there a mechanism to time out individual operations?

 No, the socket connect timeout is hard-coded at 1 second and the
 socket I/O timeout is disabled.

 Bugzilla bug https://issues.apache.org/bugzilla/show_bug.cgi?id=51065
 has a patch, though it is apparently missing a call to adjust the
 socket timeout and to discard the connection if the timeout is
 reached.  More importantly, the API can only be changed in future APR
 2.0; alternate, backwards-compatible API(s) could be added in future
 APR-Util 1.6.

 
  If memcached freezes, then it appears my calls to 'get' will block until
  memcached wakes up.  Is there any way to set a timeout for that call?
 
  I can repro this in my unit tests by sending a SIGSTOP to memcached
 before
  doing a 'get'?
 
  Here are my observations:
 
  apr_memcache_multgetp seems to time out in bounded time if I SIGSTOP the
  memcached process. Yes!
 
  apr_memcache_getp seems to hang indefinitely if I SIGSTOP the memcached
  process.
 
  apr_memcache_set seems to hang indefinitely if I SIGSTOP the memcached
  process.
 
  apr_memcache_delete seems to hang indefinitely if I SIGSTOP the
 memcached
  process.
 
  apr_memcache_stats seems to hang indefinitely if I SIGSTOP the memcached
  process.
 
  That last one really sucks as I am using that to print the status of
 all my
  cache shards to the log file if I detected a problem :(
 
 
  Why does apr_memcache_multgetp do what I want and not the others?  Can I
  induce the others to have reasonable timeout behavior?
 
  When I SIGSTOP

apr_memcache operation timeouts

2012-10-17 Thread Joshua Marantz
Is there a mechanism to time out individual operations?

If memcached freezes, then it appears my calls to 'get' will block until
memcached wakes up.  Is there any way to set a timeout for that call?

I can repro this in my unit tests by sending a SIGSTOP to memcached before
doing a 'get'?

Here are my observations:

apr_memcache_multgetp seems to time out in bounded time if I SIGSTOP the
memcached process. Yes!

apr_memcache_getp seems to hang indefinitely if I SIGSTOP the memcached
process.

apr_memcache_set seems to hang indefinitely if I SIGSTOP the memcached
process.

apr_memcache_delete seems to hang indefinitely if I SIGSTOP the memcached
process.

apr_memcache_stats seems to hang indefinitely if I SIGSTOP the memcached
process.

That last one really sucks as I am using that to print the status of all my
cache shards to the log file if I detected a problem :(


Why does apr_memcache_multgetp do what I want and not the others?  Can I
induce the others to have reasonable timeout behavior?

When I SIGSTOP memcached this makes it hard to even restart Apache, at
least with graceful-stop.


On a related note, the apr_memcache
documentationhttp://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.htmlis
very thin.  I'd be happy to augment it with my observations on its
usage
and the meaning of some of the arguments if that was desired.  How would I
go about that?

-Josh


Re: aprmemcache question

2012-10-13 Thread Joshua Marantz
Now that we've established that the TTL passed into the server-create call
is for reaping idle connections and not individual operation timeouts, I
want to ask about timing out individual operations.

If memcached freezes, then it appears my calls to 'get' will block until
memcached wakes up.  Is there any way to set a timeout for that call?

I can repro this in my unit tests by sending a SIGSTOP to memcached before
doing a 'get'.

-Josh


On Thu, Sep 27, 2012 at 4:37 PM, Joshua Marantz jmara...@google.com wrote:

 This helps a lot.  I think 600 seconds seems like a fine idle-reap timeout.

 I need to investigate why some lookups take a second or more.  Maybe
 there's a mutex contention on my end somewhere.

 Thanks!
 -Josh



 On Thu, Sep 27, 2012 at 2:08 PM, Jeff Trawick traw...@gmail.com wrote:

 On Thu, Sep 27, 2012 at 1:55 PM, Joshua Marantz jmara...@google.com
 wrote:
  That one call-site is HTTP_24/src/modules/cache/mod_socache_memcache.c,
  right?  That was where I stole my args from.

 no, subversion

  As the TCP/IP layer is a lower level abstraction than bathe apr_memcache
  interface, I'm still not clear on exactly what that means.  Does a
 value of
  600 mean that a single multiget must complete in 600 microseconds
 otherwise
  it fails with APR_TIMEUP?

 ttl only affects connections which are not currently used; it does not
 control I/O timeouts


  That might explain the behavior I saw.
 
  I've now jacked that up by x1e6  to 600 seconds and I don't see
 timeouts,
  but I'm hoping someone can bridge the gap between the socket-level
  explanation and the apr_memcache API call.
 
  I was assuming that apr_memcache created the TCP/IP connection when I
 called
  apr_memcache_server_create, and there even 600 seconds seems too short.
  Is
  the functionality more like it will create connections on-demand and
 leave
  them running for N microseconds, re-using the connection for multiple
  requests until TTL microseconds have elapsed since creation?

 create on demand
 reuse existing idle connections when possible
 when performing maintenance on the idle connections, clean up any
 which were idle for N microseconds

 If a connection is always reused before it is idle for N microseconds,
 it will live as long as memcached allows.

  If that's the case then I guess that every 10 minutes one of my cache
  lookups may have high latency to re-establish the connection, is that
 right?
  I've been histogramming this under load and seeing some long tail
 requests
  with very high latency.  My median latency is only 143us which is great.
  My 90%, 95% and 99% are all around 5ms, which is fine as well.  But
 I've got
  a fairly significant number of long-tail lookups that take hundreds of
 ms or
  even seconds to finish, and one crazy theory is that this is all
 reconnect
  cost.
 
  It would be nice if the TTL were interpreted as a maximum idle time
 before
  the connection is reaped, rather than stuttering response-time on a very
  active channel.

 It is.  The ttl is interpreted by the reslist layer, which won't touch
 objects until they're returned to the list.

 
  This testing is all using a single memcached running on localhost.
 
  -Josh
 
 
  On Thu, Sep 27, 2012 at 11:24 AM, Jeff Trawick traw...@gmail.com
 wrote:
 
  On Thu, Sep 27, 2012 at 11:15 AM, Joshua Marantz jmara...@google.com
  wrote:
   On Thu, Sep 27, 2012 at 10:58 AM, Ben Noordhuis i...@bnoordhuis.nl
   wrote:
  
 If dlsym() is called with the special handle NULL, it is
 interpreted
   as
   a
 reference to the executable or shared object from which the call
 is
   being
 made.  Thus a shared object can reference its own symbols.
  
   And that's how it works on Linux, Solaris, NetBSD and probably
 OpenBSD
   as
   well.
  
  
   Cool, thanks.
  
Do you have a feel for the exact meaning of that TTL parameter to
apr_memcache_server_create?
  
   You mean what units it uses? Microseconds (at least, in 2.4).
  
  
   Actually what I meant was what that value is used for in the library.
   The
   phrase time to live of client connection confuses me.  Does it
 really
   mean
   the maximum number of seconds apr_memcache is willing to wait for a
   single
   operation?  Or does it mean *both*, implying that a fresh TCP/IP
   connection
   is made for every new operation, but will stay alive for only a
 certain
   number of seconds.
 
  TCP/IP connections, once created, will be retained for the specified
  (ttl) number of seconds.  They'll be created when needed.
 
  The socket connect timeout is hard-coded to 1 second, and there's no
  timeout for I/O.
 
  
  
   It is a little disturbing from a module-developer perspective to have
   the
   meaning of that parameter change by a factor of 1M between versions.
   Would
   it be better to revert the recent change and instead change the doc
 to
   match
   the current behavior?
 
  The doc was already changed to match the behavior, but I missed that.
  The caller I know

Re: aprmemcache question

2012-09-27 Thread Joshua Marantz
Thanks Ben,

That might be an interesting hack to try, although I wonder whether some of
our friends running mod_pagespeed on FreeBSD might run into trouble with
it.  I did confirm that my prefork build has APR built with
APR_HAS_THREADS, which for some reason I had earlier thought was not the
case.

Do you have a feel for the exact meaning of that TTL parameter to
apr_memcache_server_create?

-Josh



On Thu, Sep 27, 2012 at 8:53 AM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 On Thu, Sep 27, 2012 at 4:05 AM, Joshua Marantz jmara...@google.com
 wrote:
  RE failing the build of my module -- the dominant usage is via
  precompiled binaries we supply.  Is there an apr query for determining
  whether apr was compiled with threads I could do on startup?

 I don't think there's an official way but you know apr was compiled
 with APR_HAS_THREADS when dlsym(NULL, apr_os_thread_current) !=
 NULL.

 Using dlsym() like that is not quite compatible with POSIX but it
 works on all the major Unices.



Re: aprmemcache question

2012-09-27 Thread Joshua Marantz
On Thu, Sep 27, 2012 at 10:58 AM, Ben Noordhuis i...@bnoordhuis.nl wrote:

   If dlsym() is called with the special handle NULL, it is interpreted as a
   reference to the executable or shared object from which the call is being
   made.  Thus a shared object can reference its own symbols.

 And that's how it works on Linux, Solaris, NetBSD and probably OpenBSD as
 well.


Cool, thanks.

   Do you have a feel for the exact meaning of that TTL parameter to
  apr_memcache_server_create?

 You mean what units it uses? Microseconds (at least, in 2.4).


Actually what I meant was what that value is used for in the library.  The
phrase time to live of client connection confuses me.  Does it really
mean the maximum number of seconds apr_memcache is willing to wait for a
single operation?  Or does it mean *both*, implying that a fresh TCP/IP
connection is made for every new operation, but will stay alive for only a
certain number of seconds.


It is a little disturbing from a module-developer perspective to have the
meaning of that parameter change by a factor of 1M between versions.  Would
it be better to revert the recent change and instead change the doc to
match the current behavior?

-Josh


Re: aprmemcache question

2012-09-27 Thread Joshua Marantz
This helps a lot.  I think 600 seconds seems like a fine idle-reap timeout.

I need to investigate why some lookups take a second or more.  Maybe
there's a mutex contention on my end somewhere.

Thanks!
-Josh



On Thu, Sep 27, 2012 at 2:08 PM, Jeff Trawick traw...@gmail.com wrote:

 On Thu, Sep 27, 2012 at 1:55 PM, Joshua Marantz jmara...@google.com
 wrote:
  That one call-site is HTTP_24/src/modules/cache/mod_socache_memcache.c,
  right?  That was where I stole my args from.

 no, subversion

  As the TCP/IP layer is a lower level abstraction than bathe apr_memcache
  interface, I'm still not clear on exactly what that means.  Does a value
 of
  600 mean that a single multiget must complete in 600 microseconds
 otherwise
  it fails with APR_TIMEUP?

 ttl only affects connections which are not currently used; it does not
 control I/O timeouts


  That might explain the behavior I saw.
 
  I've now jacked that up by x1e6  to 600 seconds and I don't see timeouts,
  but I'm hoping someone can bridge the gap between the socket-level
  explanation and the apr_memcache API call.
 
  I was assuming that apr_memcache created the TCP/IP connection when I
 called
  apr_memcache_server_create, and there even 600 seconds seems too short.
  Is
  the functionality more like it will create connections on-demand and
 leave
  them running for N microseconds, re-using the connection for multiple
  requests until TTL microseconds have elapsed since creation?

 create on demand
 reuse existing idle connections when possible
 when performing maintenance on the idle connections, clean up any
 which were idle for N microseconds

 If a connection is always reused before it is idle for N microseconds,
 it will live as long as memcached allows.

  If that's the case then I guess that every 10 minutes one of my cache
  lookups may have high latency to re-establish the connection, is that
 right?
  I've been histogramming this under load and seeing some long tail
 requests
  with very high latency.  My median latency is only 143us which is great.
  My 90%, 95% and 99% are all around 5ms, which is fine as well.  But I've
 got
  a fairly significant number of long-tail lookups that take hundreds of
 ms or
  even seconds to finish, and one crazy theory is that this is all
 reconnect
  cost.
 
  It would be nice if the TTL were interpreted as a maximum idle time
 before
  the connection is reaped, rather than stuttering response-time on a very
  active channel.

 It is.  The ttl is interpreted by the reslist layer, which won't touch
 objects until they're returned to the list.

 
  This testing is all using a single memcached running on localhost.
 
  -Josh
 
 
  On Thu, Sep 27, 2012 at 11:24 AM, Jeff Trawick traw...@gmail.com
 wrote:
 
  On Thu, Sep 27, 2012 at 11:15 AM, Joshua Marantz jmara...@google.com
  wrote:
   On Thu, Sep 27, 2012 at 10:58 AM, Ben Noordhuis i...@bnoordhuis.nl
   wrote:
  
 If dlsym() is called with the special handle NULL, it is
 interpreted
   as
   a
 reference to the executable or shared object from which the call is
   being
 made.  Thus a shared object can reference its own symbols.
  
   And that's how it works on Linux, Solaris, NetBSD and probably
 OpenBSD
   as
   well.
  
  
   Cool, thanks.
  
Do you have a feel for the exact meaning of that TTL parameter to
apr_memcache_server_create?
  
   You mean what units it uses? Microseconds (at least, in 2.4).
  
  
   Actually what I meant was what that value is used for in the library.
   The
   phrase time to live of client connection confuses me.  Does it
 really
   mean
   the maximum number of seconds apr_memcache is willing to wait for a
   single
   operation?  Or does it mean *both*, implying that a fresh TCP/IP
   connection
   is made for every new operation, but will stay alive for only a
 certain
   number of seconds.
 
  TCP/IP connections, once created, will be retained for the specified
  (ttl) number of seconds.  They'll be created when needed.
 
  The socket connect timeout is hard-coded to 1 second, and there's no
  timeout for I/O.
 
  
  
   It is a little disturbing from a module-developer perspective to have
   the
   meaning of that parameter change by a factor of 1M between versions.
   Would
   it be better to revert the recent change and instead change the doc to
   match
   the current behavior?
 
  The doc was already changed to match the behavior, but I missed that.
  The caller I know of used the wrong unit, and I'll submit a patch to
  fix that in the caller, as well as revert my screw-up from yesterday.
 
  
   -Josh
  
 
 
 
  --
  Born in Roswell... married an alien...
  http://emptyhammock.com/
 
 



 --
 Born in Roswell... married an alien...
 http://emptyhammock.com/



aprmemcache question

2012-09-26 Thread Joshua Marantz
Hi,

I've been having some success with the apr_memcache_* functions.  In
load-tests, however, I'm finding a lot of timeouts
with apr_memcache_multgetp.  Specifically, the status returned with the
individual elements is APR_TIMEUP.

This leads me to wonder what the significance of the second to last arg to
this function is:

apr_memcache_server_create(
  pool_, hosts_[i].c_str(), ports_[i],
  kDefaultServerMin, kDefaultServerSmax,
  thread_limit_, kDefaultServerTtlUs, server);

I have kDefaultServerSmax initialized to 600, as that's the value I found
in mod_socache_memcache.c   But that seems stingy (if it's really in
microseconds).  Should I be giving that a few hundred millis instead?
http://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.html#ga18ddd72bc1ab5edb0a08a8f26f193bd3
claims
that means time to live of client connection but I don't understand what
that phrase means exactly, or if it relates to the APR_TIMEUP returns I've
been suffering from.

My code is here;
http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc

-Josh


Re: aprmemcache question

2012-09-26 Thread Joshua Marantz
+dev (sorry for the duplicate; my first attempt failed due to not being a
subscriber).

Keeping modules-dev on CC if that's appropriate.

Thanks, Jeff, I was wondering if there was a units issue there.  I'm still
wondering if anyone can describe the meaning of that argument in more
detail.  Is that related to my multiget APR_TIMEUP returns?   The phrase
time to live of client connection confuses me.  Would it be inaccurate to
instead say the maximum number of seconds apr_memcache is willing to wait
for a single operation?  Or does it mean *both*, implying that a fresh
TCP/IP connection is made for every new operation, but will stay alive for
only a certain number of seconds.

I have a practical question about how I release software given this change.
 Our module (mod_pagespeed) is documented to run with Apache 2.2 and Apache
2.4.  It seems like for 2.2 I should probably multiple my desired argument
by a million.  Same with for 2.4.x and earlier, for some value of x.  How
should I work this in my code?  Should I query the version number using an
apr utility or something and multiply by a million in certain cases?

What's the best practice calling this function for module developers?

-Josh


On Wed, Sep 26, 2012 at 6:20 PM, Jeff Trawick traw...@gmail.com wrote:

 On Wed, Sep 26, 2012 at 5:38 PM, Joshua Marantz jmara...@google.com
 wrote:
  Hi,
 
  I've been having some success with the apr_memcache_* functions.  In
  load-tests, however, I'm finding a lot of timeouts
  with apr_memcache_multgetp.  Specifically, the status returned with the
  individual elements is APR_TIMEUP.
 
  This leads me to wonder what the significance of the second to last arg
 to
  this function is:
 
  apr_memcache_server_create(
pool_, hosts_[i].c_str(), ports_[i],
kDefaultServerMin, kDefaultServerSmax,
thread_limit_, kDefaultServerTtlUs, server);
 
  I have kDefaultServerSmax initialized to 600, as that's the value I found
  in mod_socache_memcache.c   But that seems stingy (if it's really in
  microseconds).  Should I be giving that a few hundred millis instead?
 
 http://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.html#ga18ddd72bc1ab5edb0a08a8f26f193bd3
  claims
  that means time to live of client connection but I don't understand
 what
  that phrase means exactly, or if it relates to the APR_TIMEUP returns
 I've
  been suffering from.
 
  My code is here;
 
 http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc
 
  -Josh

 d...@apr.apache.org is a better place to ask about details of apr
 functions.

 Coincidentally, earlier today I committed someone's fix for the
 confusion about the units of ttl:

 http://svn.apache.org/viewvc?view=revisionrevision=1390530

 It is supposed to be in seconds.  Pick up the tiny change to
 apr_memcache.c and see if that helps anything.  You should continue
 this discussion on d...@apr.apache.org.

 --
 Born in Roswell... married an alien...
 http://emptyhammock.com/



Re: aprmemcache question

2012-09-26 Thread Joshua Marantz
Looking at source, I see that Jeff's patch, and the 'ttl' parameter in
general, is only referenced under '#if APR_HAS_THREADS'.  When I
load-tested and found the timeouts, I was testing under Apache 2.2 Prefork,
and thus that patched code is not even compiled, IIUC.

However I would still like to know what that parameter is for when running
under Worker.

I think the implication of my source journey is also that if my module
instantiates multiple threads under Prefork (which it does), it must call
apr_memcache* routines from only one of them.  Is that correct?

-Josh


On Wed, Sep 26, 2012 at 7:17 PM, Joshua Marantz jmara...@google.com wrote:

 +dev (sorry for the duplicate; my first attempt failed due to not being a
 subscriber).

 Keeping modules-dev on CC if that's appropriate.

 Thanks, Jeff, I was wondering if there was a units issue there.  I'm still
 wondering if anyone can describe the meaning of that argument in more
 detail.  Is that related to my multiget APR_TIMEUP returns?   The phrase
 time to live of client connection confuses me.  Would it be inaccurate to
 instead say the maximum number of seconds apr_memcache is willing to wait
 for a single operation?  Or does it mean *both*, implying that a fresh
 TCP/IP connection is made for every new operation, but will stay alive for
 only a certain number of seconds.

 I have a practical question about how I release software given this
 change.  Our module (mod_pagespeed) is documented to run with Apache 2.2
 and Apache 2.4.  It seems like for 2.2 I should probably multiple my
 desired argument by a million.  Same with for 2.4.x and earlier, for some
 value of x.  How should I work this in my code?  Should I query the version
 number using an apr utility or something and multiply by a million in
 certain cases?

 What's the best practice calling this function for module developers?

 -Josh


 On Wed, Sep 26, 2012 at 6:20 PM, Jeff Trawick traw...@gmail.com wrote:

 On Wed, Sep 26, 2012 at 5:38 PM, Joshua Marantz jmara...@google.com
 wrote:
  Hi,
 
  I've been having some success with the apr_memcache_* functions.  In
  load-tests, however, I'm finding a lot of timeouts
  with apr_memcache_multgetp.  Specifically, the status returned with the
  individual elements is APR_TIMEUP.
 
  This leads me to wonder what the significance of the second to last arg
 to
  this function is:
 
  apr_memcache_server_create(
pool_, hosts_[i].c_str(), ports_[i],
kDefaultServerMin, kDefaultServerSmax,
thread_limit_, kDefaultServerTtlUs, server);
 
  I have kDefaultServerSmax initialized to 600, as that's the value I
 found
  in mod_socache_memcache.c   But that seems stingy (if it's really in
  microseconds).  Should I be giving that a few hundred millis instead?
 
 http://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.html#ga18ddd72bc1ab5edb0a08a8f26f193bd3
  claims
  that means time to live of client connection but I don't understand
 what
  that phrase means exactly, or if it relates to the APR_TIMEUP returns
 I've
  been suffering from.
 
  My code is here;
 
 http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc
 
  -Josh

 d...@apr.apache.org is a better place to ask about details of apr
 functions.

 Coincidentally, earlier today I committed someone's fix for the
 confusion about the units of ttl:

 http://svn.apache.org/viewvc?view=revisionrevision=1390530

 It is supposed to be in seconds.  Pick up the tiny change to
 apr_memcache.c and see if that helps anything.  You should continue
 this discussion on d...@apr.apache.org.

 --
 Born in Roswell... married an alien...
 http://emptyhammock.com/





Re: aprmemcache question

2012-09-26 Thread Joshua Marantz
RE failing the build of my module -- the dominant usage is via
precompiled binaries we supply.  Is there an apr query for determining
whether apr was compiled with threads I could do on startup?

-Josh



On Wed, Sep 26, 2012 at 7:40 PM, Jeff Trawick traw...@gmail.com wrote:

 On Wed, Sep 26, 2012 at 7:31 PM, Joshua Marantz jmara...@google.com
 wrote:
  Looking at source, I see that Jeff's patch, and the 'ttl' parameter in
  general, is only referenced under '#if APR_HAS_THREADS'.  When I
  load-tested and found the timeouts, I was testing under Apache 2.2
 Prefork,
  and thus that patched code is not even compiled, IIUC.
 
  However I would still like to know what that parameter is for when
 running
  under Worker.
 
  I think the implication of my source journey is also that if my module
  instantiates multiple threads under Prefork (which it does), it must call
  apr_memcache* routines from only one of them.  Is that correct?

 APR is usually compiled with thread support even when using the
 prefork MPM.  Check APR_HAS_THREADS in apr.h.

 If APR_HAS_THREADS is 0 (very unlikely), you probably want to fail the
 build of your module to avoid having to worry about this.

 As far as what the parameter means...  I'll try to look tomorrow if
 nobody replies first.

 See apu_version() for the APR-util version.

 
  -Josh
 
 
  On Wed, Sep 26, 2012 at 7:17 PM, Joshua Marantz jmara...@google.com
 wrote:
 
  +dev (sorry for the duplicate; my first attempt failed due to not being
 a
  subscriber).
 
  Keeping modules-dev on CC if that's appropriate.
 
  Thanks, Jeff, I was wondering if there was a units issue there.  I'm
 still
  wondering if anyone can describe the meaning of that argument in more
  detail.  Is that related to my multiget APR_TIMEUP returns?   The phrase
  time to live of client connection confuses me.  Would it be
 inaccurate to
  instead say the maximum number of seconds apr_memcache is willing to
 wait
  for a single operation?  Or does it mean *both*, implying that a fresh
  TCP/IP connection is made for every new operation, but will stay alive
 for
  only a certain number of seconds.
 
  I have a practical question about how I release software given this
  change.  Our module (mod_pagespeed) is documented to run with Apache 2.2
  and Apache 2.4.  It seems like for 2.2 I should probably multiple my
  desired argument by a million.  Same with for 2.4.x and earlier, for
 some
  value of x.  How should I work this in my code?  Should I query the
 version
  number using an apr utility or something and multiply by a million in
  certain cases?
 
  What's the best practice calling this function for module developers?
 
  -Josh
 
 
  On Wed, Sep 26, 2012 at 6:20 PM, Jeff Trawick traw...@gmail.com
 wrote:
 
  On Wed, Sep 26, 2012 at 5:38 PM, Joshua Marantz jmara...@google.com
  wrote:
   Hi,
  
   I've been having some success with the apr_memcache_* functions.  In
   load-tests, however, I'm finding a lot of timeouts
   with apr_memcache_multgetp.  Specifically, the status returned with
 the
   individual elements is APR_TIMEUP.
  
   This leads me to wonder what the significance of the second to last
 arg
  to
   this function is:
  
   apr_memcache_server_create(
 pool_, hosts_[i].c_str(), ports_[i],
 kDefaultServerMin, kDefaultServerSmax,
 thread_limit_, kDefaultServerTtlUs, server);
  
   I have kDefaultServerSmax initialized to 600, as that's the value I
  found
   in mod_socache_memcache.c   But that seems stingy (if it's really in
   microseconds).  Should I be giving that a few hundred millis instead?
  
 
 http://apr.apache.org/docs/apr-util/1.4/group___a_p_r___util___m_c.html#ga18ddd72bc1ab5edb0a08a8f26f193bd3
   claims
   that means time to live of client connection but I don't understand
  what
   that phrase means exactly, or if it relates to the APR_TIMEUP returns
  I've
   been suffering from.
  
   My code is here;
  
 
 http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc
  
   -Josh
 
  d...@apr.apache.org is a better place to ask about details of apr
  functions.
 
  Coincidentally, earlier today I committed someone's fix for the
  confusion about the units of ttl:
 
  http://svn.apache.org/viewvc?view=revisionrevision=1390530
 
  It is supposed to be in seconds.  Pick up the tiny change to
  apr_memcache.c and see if that helps anything.  You should continue
  this discussion on d...@apr.apache.org.
 
  --
  Born in Roswell... married an alien...
  http://emptyhammock.com/
 
 
 



 --
 Born in Roswell... married an alien...
 http://emptyhammock.com/



Re: apr_memcache vs libmemcached

2012-08-17 Thread Joshua Marantz
Following up: I've been pretty successful using apr_memcache so far.  The
performance is roughly on par with a file-cache running on a tmpfs
partition, but of course it adds network scalability.  I'd encourage anyone
wanting to integrate memcached into Apache modules to give it a try.  It
might even be one of the easiest ways to get a map that can be used across
processes on a single server, rather than working with shared memory.

It *looks* like libmemcached has a richer API and the potential for better
performance due to asynchronous APIs and usage of the memcached binary
protocol, but I have not been as successful with it.  And apr_memcache
seems good enough, performance wise, based on my load tests, and so far
it's very stable.

Example usage:
http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.cc,
.hhttp://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache.h,
and 
_test.cchttp://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/apache/apr_mem_cache_test.cc
.

-Josh



On Thu, Jul 19, 2012 at 5:47 PM, Joshua Marantz jmara...@google.com wrote:

 I think the point of that Wiki was that whoever wrote that entry claimed
 that apr_memcached wasn't being actively worked on, but perhaps that's
 false.  I don't think the implication was that the work was expected to
 happen in code.google.com.

 This question is in the context of 
 mod_pagespeedhttps://developers.google.com/speed/pagespeed/mod,
 which currently uses the file system for caching that's visible across
 Apache child processes.  That works pretty well but has limitations in
 performance and network scope.  memcached is being considered as a possible
 replacement for that.

 I'll take a look at socache.


 One of the advantages of libmemcached is that it supports -- or claims to
 support -- asynchronous fetches, which we believe is important for
 performance at scale.  However, I have not actually been able to get that
 to work as expected, and have fallen back to a fairly synchronous model.
  The libmemcached API *looks* asynchronous -- it just doesn't seem to quite
 work.   And if I'm going to stay synchronous then it might be a lot easier
 to integrate if I use the built in APR support.  And even synchronous
 fetches from memcached might be better than synchronous reads form disk.

 Thanks,
 -Josh


 On Thu, Jul 19, 2012 at 5:39 PM, Nick Kew n...@apache.org wrote:

 On Thu, 19 Jul 2012 16:41:51 -0400
 Joshua Marantz jmara...@google.com wrote:

  Hi,
 
  Is anyone maintaining apr_memcache?  Or should I stick with
 libmemcached?
 
  This page: http://code.google.com/p/memcached/wiki/Clients suggests
  apr_memcached is not maintained.

 Huh?  It's not maintained at google code since it was contributed
 to the core APR project.  If you have any reasonably recent APR
 installed (as you must have if you run httpd), it includes
 apr_memcache.

 Since you posted here I'd guess your purpose is writing a module?
 You might want to look at the socache modules as a higher-level
 abstraction.


 --
 Nick Kew





apr_memcache vs libmemcached

2012-07-19 Thread Joshua Marantz
Hi,

Is anyone maintaining apr_memcache?  Or should I stick with libmemcached?

This page: http://code.google.com/p/memcached/wiki/Clients suggests
apr_memcached is not maintained.

Thanks!
-Josh


Re: apr_memcache vs libmemcached

2012-07-19 Thread Joshua Marantz
I think the point of that Wiki was that whoever wrote that entry claimed
that apr_memcached wasn't being actively worked on, but perhaps that's
false.  I don't think the implication was that the work was expected to
happen in code.google.com.

This question is in the context of
mod_pagespeedhttps://developers.google.com/speed/pagespeed/mod,
which currently uses the file system for caching that's visible across
Apache child processes.  That works pretty well but has limitations in
performance and network scope.  memcached is being considered as a possible
replacement for that.

I'll take a look at socache.


One of the advantages of libmemcached is that it supports -- or claims to
support -- asynchronous fetches, which we believe is important for
performance at scale.  However, I have not actually been able to get that
to work as expected, and have fallen back to a fairly synchronous model.
 The libmemcached API *looks* asynchronous -- it just doesn't seem to quite
work.   And if I'm going to stay synchronous then it might be a lot easier
to integrate if I use the built in APR support.  And even synchronous
fetches from memcached might be better than synchronous reads form disk.

Thanks,
-Josh


On Thu, Jul 19, 2012 at 5:39 PM, Nick Kew n...@apache.org wrote:

 On Thu, 19 Jul 2012 16:41:51 -0400
 Joshua Marantz jmara...@google.com wrote:

  Hi,
 
  Is anyone maintaining apr_memcache?  Or should I stick with libmemcached?
 
  This page: http://code.google.com/p/memcached/wiki/Clients suggests
  apr_memcached is not maintained.

 Huh?  It's not maintained at google code since it was contributed
 to the core APR project.  If you have any reasonably recent APR
 installed (as you must have if you run httpd), it includes
 apr_memcache.

 Since you posted here I'd guess your purpose is writing a module?
 You might want to look at the socache modules as a higher-level
 abstraction.


 --
 Nick Kew



Re: Get the directory of the module

2012-06-11 Thread Joshua Marantz
I think he wants to write bytecodes during module installation when he will
have write access.

During installation can you also write a .conf template showing your module
where the bytecodes are?

Josh
 On Jun 11, 2012 7:29 PM, Jerry Stuckle je...@smartechhomes.com wrote:



 On 6/11/2012 5:49 PM, Ben Noordhuis wrote:

 On Mon, Jun 11, 2012 at 10:10 PM, Bart 
 Wiegmansbartwiegmans@gmail.**combartwiegm...@gmail.com
  wrote:

 Hello everybody,

 For a project I'm doing, I need to install a few bytecode files
 alongside my module. I was planning on placing them in the modules
 directory but I realised that at runtime I do not know where that is.
 What is more, that directory may (and will, as a matter of fact) vary
 during installation and testing. But most importantly, the server
 knows where the module is kept as it specified by LoadModule.

 So in short, how can I determine the directory of my module at runtime?


 You can't, the file path is internal to mod_so.c. I don't think it
 even stores it.



 In addition, there is no guarantee you have write access to that directory.



Re: Get the directory of the module

2012-06-11 Thread Joshua Marantz
I think we are saying the same thing, right?  To tell his module I'm
suggesting he write the path where the .so is installed into his .conf file
so that he can get the path at runtime.

On Mon, Jun 11, 2012 at 8:02 PM, Jerry Stuckle je...@smartechhomes.comwrote:

 In that case he should also be able to tell his module where the files are.


 On 6/11/2012 7:40 PM, Joshua Marantz wrote:

 I think he wants to write bytecodes during module installation when he
 will
 have write access.

 During installation can you also write a .conf template showing your
 module
 where the bytecodes are?

 Josh
  On Jun 11, 2012 7:29 PM, Jerry 
 Stucklejerry@smartechhomes.**comje...@smartechhomes.com
  wrote:



 On 6/11/2012 5:49 PM, Ben Noordhuis wrote:

  On Mon, Jun 11, 2012 at 10:10 PM, Bart Wiegmansbartwiegmans@gmail.
 combartwiegm...@gmail.com

  wrote:

  Hello everybody,

 For a project I'm doing, I need to install a few bytecode files
 alongside my module. I was planning on placing them in the modules
 directory but I realised that at runtime I do not know where that is.
 What is more, that directory may (and will, as a matter of fact) vary
 during installation and testing. But most importantly, the server
 knows where the module is kept as it specified by LoadModule.

 So in short, how can I determine the directory of my module at runtime?


 You can't, the file path is internal to mod_so.c. I don't think it
 even stores it.



  In addition, there is no guarantee you have write access to that
 directory.





Re: Determining mimetype of document

2012-06-08 Thread Joshua Marantz
In understand any module *can* set content-type late: I'm just wondering if
that happens with any frequency.  E.g.when I googled for how to set
content-type in Apache, I got references to AddType and some hacks using
mod_rewrite, both of which would run upstream of my filter.  My main
concern is mod_headers since it runs downstream.

RE firefox sniffing content-type:  does that imply that if there is an
explicit mimetype it will ignore it and determine XHTML vs HTML via
sniffing, I suppose, for DOCTYPE?  Do you have a link to that bit of news?
 That certainly complicates things.

-Josh

On Fri, Jun 8, 2012 at 5:16 PM, Joe Lewis j...@joe-lewis.com wrote:

 On 06/08/2012 03:07 PM, Joshua Marantz wrote:

 Hi,

 I'm trying to figure out whether my filter, which currently runs upstream
 of mod_headers, is likely to see the correct mimetype
 in request-content_type.

 In particular, we need to know whether browsers will interpret the content
 as XHTML or HTML, which is determined by the mimetype.  Do people
 typically
 set the mimetype using mod_headers, or is that typically set using AddType
 or some other mechanism?


 It's usually set by the content generator.  However, you have to keep in
 mind that any module may modify that value (any output filter may, too) up
 until the AP_FTYPE_CONTENT_SET (runs after the AP_FTYPE_RESOURCE output
 filters).

 Additionally, please keep in mind that Firefox has begun the old I.E. hack
 of sniffing the content and ignoring the Content-Type header if it can
 figure it out, so you will have to be aware that content_type is not
 indicative at any stage of what the browser is going to do.

 Joe
 --
 http://www.silverhawk.net/



Re: output filter ordering question: mod_deflate vs mod_headers vs mod_pagespeed

2012-05-17 Thread Joshua Marantz
Thanks for the quick reply, Nick.  I played around with this idea but
couldn't get it to work. My filter now runs at
AP_FTYPE_CONTENT_SET + 1, to make sure it runs after mod_headers.  I don't
know how to try to coax mod_deflate to run after me.  I can prevent it from
running before me by removing it from the filter-chain in before my main
filter-function runs, but when I try to then put it back in the filter
chain after my main filter function, it doesn't appear to work.  But you
are right; this is a hack on a hack and perhaps not worth pursuing further.

Is mod_filter a mechanism I could use in Apache 2.2 to accomplish what I
need?  I found  http://httpd.apache.org/docs/2.2/mod/mod_filter.html and it
looks promising.  I'll give it a try.

The tone of your email made it sound like mod_filter is not quite ready,
but it's there in my distribution.  Can you elaborate on the state of
mod_filter?

Thanks!
-Josh

On Thu, May 17, 2012 at 2:30 AM, Nick Kew n...@apache.org wrote:


 On 17 May 2012, at 04:24, Joshua Marantz wrote:

  Or is that insane /or dangerous?

 AP_FTYPE_ values are something of a blunt instrument, not ideal
 for cases where you care about ordering.  Running mod_headers
 as a filter is a bit of a hack.  What you're proposing is kind-of building
 a hack onto a hack.  I'm sure you can make it work (at least in
 controlled circumstances where you're not competing against
 other similar fudges) but IMHO you're right to be worried.

 Having once upon a time written mod_filter to deal with more
 complex configuration than the original design envisaged,
 I wonder if your issue might be a hint that we should
 revisit the API for programmatic configuration, and make
 your proposal less hackish?

 --
 Nick Kew



Re: output filter ordering question: mod_deflate vs mod_headers vs mod_pagespeed

2012-05-17 Thread Joshua Marantz
Hi I gave it a try but need a little help to get further.

I added this to my configuration file:

FilterDeclare headers CONTENT_SET
FilterDeclare pagespeed CONTENT_SET
FilterDeclare deflate CONTENT_SET
FilterProvider pagespeed MOD_PAGESPEED_OUTPUT_FILTER resp=Content-Type
$text/html
FilterProvider headers FIXUP_HEADERS_OUT resp=Content-Type $text/html
FilterProvider deflate DEFLATE resp=Content-Type $text/html

FilterChain headers pagespeed deflate

However when I look at the request in an early output-filter I see this:

pagespeed: AP_FTYPE_CONTENT_SET(0)
deflate: AP_FTYPE_CONTENT_SET(0)
fixup_headers_out: AP_FTYPE_CONTENT_SET(0)
byterange: AP_FTYPE_PROTOCOL(0)
content_length: AP_FTYPE_PROTOCOL(0)
http_header: AP_FTYPE_PROTOCOL(0)
http_outerror: AP_FTYPE_PROTOCOL(0)
log_input_output: AP_FTYPE_NETWORK(-1)
core: AP_FTYPE_NETWORK(0)


The code that printed this is:

void PrintFilterChain(ap_filter_t* filter) {
  // TODO(jmarantz): debug-check that these are in increasing order.
  static ap_filter_type types[] = {
AP_FTYPE_RESOURCE, AP_FTYPE_CONTENT_SET, AP_FTYPE_PROTOCOL,
AP_FTYPE_TRANSCODE, AP_FTYPE_CONNECTION, AP_FTYPE_NETWORK
  };
  static const char* type_names[] = {
AP_FTYPE_RESOURCE, AP_FTYPE_CONTENT_SET, AP_FTYPE_PROTOCOL,
AP_FTYPE_TRANSCODE, AP_FTYPE_CONNECTION, AP_FTYPE_NETWORK,
END
  };
  static ap_filter_type* types_end = types + arraysize(types);

  for (ap_filter_t* next; filter != NULL; filter = next) {
next = filter-next;

// Get the symbolic name for the filter's position, relative to the
// symbolic constants above.
ap_filter_rec_t* frec = filter-frec;
ap_filter_type type = frec-ftype;
ap_filter_type* pos = std::lower_bound(types, types_end, type);
int index = pos - types;
int delta = static_castint(type) - static_castint(*pos);
fprintf(stdout, %s: %s(%d)\n, frec-name, type_names[index], delta);
  }
  fflush(stdout);
}


Is the filter -next chain not the correct way to look at this data?  In
any case the evidence from my system-tests suggest that I haven't achieved
the ordering I want yet.  Is there something else I need to do?

On Thu, May 17, 2012 at 9:27 AM, Joshua Marantz jmara...@google.com wrote:

 Thanks for the quick reply, Nick.  I played around with this idea but
 couldn't get it to work. My filter now runs at
 AP_FTYPE_CONTENT_SET + 1, to make sure it runs after mod_headers.  I don't
 know how to try to coax mod_deflate to run after me.  I can prevent it from
 running before me by removing it from the filter-chain in before my main
 filter-function runs, but when I try to then put it back in the filter
 chain after my main filter function, it doesn't appear to work.  But you
 are right; this is a hack on a hack and perhaps not worth pursuing further.

 Is mod_filter a mechanism I could use in Apache 2.2 to accomplish what I
 need?  I found  http://httpd.apache.org/docs/2.2/mod/mod_filter.html and
 it looks promising.  I'll give it a try.

 The tone of your email made it sound like mod_filter is not quite ready,
 but it's there in my distribution.  Can you elaborate on the state of
 mod_filter?

 Thanks!
 -Josh

 On Thu, May 17, 2012 at 2:30 AM, Nick Kew n...@apache.org wrote:


 On 17 May 2012, at 04:24, Joshua Marantz wrote:

  Or is that insane /or dangerous?

 AP_FTYPE_ values are something of a blunt instrument, not ideal
 for cases where you care about ordering.  Running mod_headers
 as a filter is a bit of a hack.  What you're proposing is kind-of building
 a hack onto a hack.  I'm sure you can make it work (at least in
 controlled circumstances where you're not competing against
 other similar fudges) but IMHO you're right to be worried.

 Having once upon a time written mod_filter to deal with more
 complex configuration than the original design envisaged,
 I wonder if your issue might be a hint that we should
 revisit the API for programmatic configuration, and make
 your proposal less hackish?

 --
 Nick Kew





output filter ordering question: mod_deflate vs mod_headers vs mod_pagespeed

2012-05-16 Thread Joshua Marantz
Hi,

Currently, mod_pagespeed http://code.google.com/p/modpagespeed/ runs
before mod_headers by registering as:

  ap_register_output_filter(
  kModPagespeedFilterName, instaweb_out_filter, NULL,
  static_castap_filter_type(AP_FTYPE_RESOURCE + 1));

mod_headers registers with:
 ap_register_output_filter(FIXUP_HEADERS_OUT,
ap_headers_output_filter,
  NULL, AP_FTYPE_CONTENT_SET);
with:
./include/util_filter.h:AP_FTYPE_RESOURCE = 10,
./include/util_filter.h:AP_FTYPE_CONTENT_SET  = 20,

We've been accumulating some motivation to run *after* mod_headers, rather
than *before*.  The reason is that mod_pagespeed currently has to rewrite
content without knowing the resolved content-type based on the Headers
directives in the user's configuration files.  In particular, we don't
really know definitively whether browsers will treat content as XHTML or
HTML without seeing the accurate content-type.  We can  do parse the
DOCTYPE if there is one, but that's not really the Source Of Truth as far
as browsers are concerned: the mimetype is.

Unfortunately, mod_deflate.c is also registered at AP_FTYPE_CONTENT_SET:
ap_register_output_filter(deflateFilterName, deflate_out_filter, NULL,
  AP_FTYPE_CONTENT_SET);

mod_pagespeed really needs to run before mod_deflate.  mod_pagespeed needs
HTML in the clear, and we don't want to spend CPU-cycles re-inflating what
mod_deflate just shrunk.

But I'm at a loss to understand what dictates the order between mod_headers
and mod_deflate.  They are registered at the same position.  Is it just
that they don't really care which position they run at?  Is there anything
sane that mod_pagespeed could do to ensure this order:

1. mod_headers
2. mod_pagespeed
3. mod_deflate

Should we do something like have a tiny filter function that runs at
AP_FTYPE_RESOURCE+1 and queues mod_headers to run and then the real
mod_pagespeed filter function but *removes* mod_deflate?  Then in the real
mod_pagespeed filter function we could queue up mod_deflate to get the
ordering we want?

Or is that insane /or dangerous?

Thanks!
-Josh


Re: Inject html into response body

2011-12-04 Thread Joshua Marantz
What's your thinking on how you are going to parse the HTML to inject the
code?  Do you need to parse arbitrary HTML from any website or is this
filter targeted at a particular site whose HTML is tailored for this
purpose?

-Josh

On Sun, Dec 4, 2011 at 5:15 PM, r...@tuxteam.de wrote:

 On Sun, Dec 04, 2011 at 11:47:37PM +0200, O??uzhan TOPG?L wrote:
  Hi,
  I' ve search for all the archieve but i couln't find the answer, may be i
  missed up, don't know.
  I'm trying to write an apache module and i want to inject some html code
  into resonses.
  It might be in body, header or footer. The only thing that i want to
  implemet is inserting an url or a text into all response bodies without
  damaging the original page that is serving.
  Is there any basic way of doing that?

 Well, why don't you just write an output filter that does this? I think
 Nick's book will provide all the information you need.
 Or have a look at mod_include in apache's source code.

  Cheers, Ralf Mattes
  thanks
 
  Oguzhan



Re: Question about malloc / realloc in module

2011-09-14 Thread Joshua Marantz
If you malloc/calloc/realloc without a free you will leak memory.

Do you have some reason to believe that another module might prevent your
module's calls to free() from being run?  What do you have in mind
specifically?

You can also mimic realloc by just allocating more memory from the pool and
calling memcpy.  The old memory will leak into the pool but be resolved on
pool cleanup.


I can tell you that malloc/free works fine inside an Apache module:
mod_pagespeed is written in C++ and uses new/delete extensively with the
default underlying malloc/free implementation.  We load-test extensively and
watch for leaks carefully via top, in addition to running valgrind on small
system tests.  This methodology is sound.  I'm not sure why you think your
calls to free would not happen.

-Josh

On Wed, Sep 14, 2011 at 8:01 AM, Christoph Gröver gro...@sitepark.comwrote:


 Hello list,

 In a module I have to allocate and reallocate a chunk of memory.
 Because (AFAIK) Apache or its libraries do not support reallocation
 I use the standard functions malloc/realloc (and free), of course.

 But what if there's a problem in another module?

 Is it possible that due to some errors somewhere else the
 malloc/realloc of my modules are run (and therefor memory is allocated)
 but the corresponding free is not called, because the thread/process
 had a strange ending.

 So would this result in a memory leak? (if this happens often!)

 Hope you can enlight me on this topic.

 Bye,

 --
 Christoph Gröver, gro...@sitepark.com




Re: Apache worker

2011-09-12 Thread Joshua Marantz
+modules-dev : someone with a voice of authority should chime in if I (when)
say something controversial :)

I've not seen any doc on worker MPM vs prefork  event.  I would love to see
that.

My observations with Worker MPM is that you will get multiple concurrent
requests on the same server_rec, so all access to data you hang off the
server_rec should be properly mutex-protected.  That was enough -- we
believe -- to make our module robust and functional in worker MPM.

load-testing is essential, and helped us reproduce  prove fixed the two
issues we found where we weren't mutexing enough in our module.  Also see
http://valgrind.org/docs/manual/hg-manual.html.

As mentioned in an earlier thread, what was not helpful was the apr pool
debug infrastructure, which appears to have insufficient mutexing for its
internal debug structures to run correctly in the Worker MPM.

I would also love to hear anecdotal evidence of superior performance -- by
some metric -- obtained using the Worker MPM.  In my own load-test I got
higher QPS using prefork, but we haven't tuned our module, which has its own
multi-threading architecture independent of MPM, for Worker yet so we
probably didn't allocate the optimal number of threads.

-Josh

On Mon, Sep 12, 2011 at 4:59 AM, Massimo Manghi massimo.man...@unipr.itwrote:

 Hi Josh

 I read your messages on the modules-dev list about the problems you had
 with the worker MPM. Even though you had to deal with some problems with
 the apr pools it seems you were able to get your module working with a
 threaded server.

 I'm the maintainer/developer of Apache Rivet, an Apache module with some
 extra software for scripting pages using the Tcl language. Our
 module is working with the prefork mpm, but someone put forward that we
 should also support 'worker' so I got to work on this.

 I've been struggling with the worker mpm for a while and had to set it
 aside because of lack of adequate documentation. What I understand after
 some debugging is that, from the perspective of a server thread, threads
 don't simply take the role of prefork processes, there are more implications
 apart the usual caveats of threaded programming and perhaps there are hooks
 and specific calls to Apache to deal with threads. Did you take inspiration
 from some specific threaded module to design your threading support? Did you
 have some specific reference for this?

 sorry for the long message.

 thanks in advance for any suggestion

  -- Massimo Manghi

 P.S. I wrote on the list a similar help request weeks ago, but it went
 totally unanswered



po

2011-09-01 Thread Joshua Marantz
Hi,

I've been load-testing our module
(mod_pagespeedhttp://code.google.com/speed/page-speed/docs/module.html)
with httpd 2.2.16 built with these options:
 --enable-pool-debug --with-mpm=worker
I've been getting periodic aborts from apr_table_addn that don't look like
they are from my module.  These do not occur when using 'prefork'.

Here's a stack-trace recovered from a core file:

Program terminated with signal 6, Aborted.
#0  0x7fdd3bbd9a75 in raise (sig=value optimized out) at
../nptl/sysdeps/unix/sysv/linux/raise.c:64
64 ../nptl/sysdeps/unix/sysv/linux/raise.c: No such file or directory.
 in ../nptl/sysdeps/unix/sysv/linux/raise.c
(gdb) where
#0  0x7fdd3bbd9a75 in raise (sig=value optimized out) at
../nptl/sysdeps/unix/sysv/linux/raise.c:64
#1  0x7fdd3bbdd5c0 in abort () at abort.c:92
#2  0x7fdd3c9a2e57 in apr_table_addn (t=0xe84980, key=0xd51d60
Accept-Encoding, val=0xd51d71 identity) at tables/apr_tables.c:813
#3  0x00433e36 in ap_get_mime_headers_core (r=0xf27de0, bb=0xdda3a0)
at protocol.c:799
#4  0x0043456b in ap_read_request (conn=0xe51620) at protocol.c:918
#5  0x0047f772 in ap_process_http_connection (c=0xe51620) at
http_core.c:183
#6  0x00446e28 in ap_run_process_connection (c=0xe51620) at
connection.c:43
#7  0x004b3297 in process_socket (thd=value optimized out,
dummy=value optimized out) at worker.c:544
#8  worker_thread (thd=value optimized out, dummy=value optimized out)
at worker.c:894
#9  0x7fdd3c1339ca in start_thread (arg=value optimized out) at
pthread_create.c:300
#10 0x7fdd3bc8c70d in clone () at
../sysdeps/unix/sysv/linux/x86_64/clone.S:112


Questions

1. Is this a bug in httpd?
2. Or could I somehow have caused this with a programming error in my
module?
3. Or is enable-pool-debug simply incompatible with the Worker MPM?

Thanks,
-Josh


Detecting which MPM a module is running in

2011-09-01 Thread Joshua Marantz
Hello from mod_pagespeed again.

We are adding support for running in the Worker MPM, having spent most of
our time since we launched the product sheltered in the prefork MPM where
our multi-threading challenges are all of our own making.

Having tuned our threading model for prefork, where all request-parallelism
will come at the process level, we now offer a functional but, almost
certainly, suboptimal experience for Worker MPM users.

In particular, for a given server_rec, in prefork we are only going to be
processing one request at a time, hence we should employ only a small number
of worker threads to help us.  But in Worker MPM, from what I've seen, a
single server_rec can service multiple concurrent requests.  Thus I think we
should be aware of this and bump up the number of worker threads we create
to help us.

Is it possible to detect the MPM under which mod_pagespeed is running, or,
more generally, the number of concurrent requests that the current process
is likely to need to handle?

Thanks!
-Josh


Re: po

2011-09-01 Thread Joshua Marantz
Hi Ben,

Hmmm...don't know what happened to that subject line po.  Not what I meant
to type, obviously!

On Thu, Sep 1, 2011 at 8:14 AM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 That assertion is triggered when you add a string from pool A to a
 table in pool B where A is a child of B (adding headers from the
 request_rec to a conn_rec table, for example). It's a lifecycle issue.


OK given the stack-trace above it's hard for me to figure out a path back
from my module.  Of course a random memory stomp could make any weird thing
happen, but only this one specific thing always happens.  And we try to
avoid memory-stomps via valgrind etc though it's impossible to prove that
none exist under load.


But I think I've found 2 potential problems in httpd:
  1. protocol.c calls apr_table_addn using a char* value that is offset from
a pool-allocated string.  It's not obvious that it's doing
  this safely but it makes sense this code has to run crazy fast and has
lots of mileage on it.  And it's probably OK for the pool-find
  algorithm appears to do a pointer-range check in apr_pools.c:1908,
function pool_find().  For the moment I'll assume this is not
  the actual problem.
  2. there are a bunch of ifdefs in apr_pools.c for POOL_DEBUG and there's a
some mutexing for APR_HAS_THREADS, e.g. in
 apr_allocator_max_free_set.  But I suspect the debug structures for
POOL_DEBUG are not adequately mutexed.

Has anyone specifically used pool-debug and worker-mpm together under heavy
load?

Thanks!
-Josh


Re: Pool Debug Worker MPM compatibility

2011-09-01 Thread Joshua Marantz
Oh also I should not that when I do my load-test with pool-debugging off,
all is well. The error_log has zero signals/aborts.  The main reason I was
using pool-debug in the first place was to get better valgrind leak-checks.
 But if this is just not compatible with Worker MPM I can stay with pool
debug off.

-Josh

On Thu, Sep 1, 2011 at 9:05 AM, Joshua Marantz jmara...@google.com wrote:

 Hi Ben,

 Hmmm...don't know what happened to that subject line po.  Not what I
 meant to type, obviously!

 On Thu, Sep 1, 2011 at 8:14 AM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 That assertion is triggered when you add a string from pool A to a
 table in pool B where A is a child of B (adding headers from the
 request_rec to a conn_rec table, for example). It's a lifecycle issue.


 OK given the stack-trace above it's hard for me to figure out a path back
 from my module.  Of course a random memory stomp could make any weird thing
 happen, but only this one specific thing always happens.  And we try to
 avoid memory-stomps via valgrind etc though it's impossible to prove that
 none exist under load.


 But I think I've found 2 potential problems in httpd:
   1. protocol.c calls apr_table_addn using a char* value that is offset
 from a pool-allocated string.  It's not obvious that it's doing
   this safely but it makes sense this code has to run crazy fast and
 has lots of mileage on it.  And it's probably OK for the pool-find
   algorithm appears to do a pointer-range check in apr_pools.c:1908,
 function pool_find().  For the moment I'll assume this is not
   the actual problem.
   2. there are a bunch of ifdefs in apr_pools.c for POOL_DEBUG and there's
 a some mutexing for APR_HAS_THREADS, e.g. in
  apr_allocator_max_free_set.  But I suspect the debug structures for
 POOL_DEBUG are not adequately mutexed.

 Has anyone specifically used pool-debug and worker-mpm together under heavy
 load?

 Thanks!
 -Josh




Re: po

2011-09-01 Thread Joshua Marantz
On Thu, Sep 1, 2011 at 11:16 AM, Ray Morris supp...@bettercgi.com wrote:

  this code has to run crazy fast and has lots of mileage on it.
 ...
  OK given the stack-trace above it's hard for me to figure out
  a path back from my module.

 Why not run the test without your new module loaded?


This is such an excellent idea.  The module is, unfortunately in this case,
generating the load for the load-test, as well as handling it.  I think I
can have the module do *less* but if the module is not loaded at all, then
there will be no load.


 That seems like a far simpler and more reliable indication
 of whether the issue is in the code with mileage on it or
 in the new code.


The code with mileage in protocol.c is not really under suspicion at this
point -- I probably shouldn't have mentioned it, except that it appears in
the stack at the time of the abort(), and mod_pagespeed doesn't.

The code that I suspect has a lot less mileage on it is the application
of pool debugging to the Worker MPM.  That's why I want to know if anyone
else has put those two together under heavy load.

-Josh


Re: Vary:User-Agent, best practices, and making the web faster.

2011-06-05 Thread Joshua Marantz
Thanks for the feedback, Ben!  You are omniscient in the ways of Apache.
 I'll try to lobby for an update to the mod_deflate page.

Your concerns about Magento are interesting -- my impression from our forums
and Twitter is that mod_pagespeed is successfully accelerating many Magento
sites now, since releasing the mod_rewrite workarounds, which we were able
to do thanks to your help a few months ago.  The reason that we don't have
problems with vary:user-agent on HTML is that we don't ever cache HTML under
any circumstance.  We assume HTML generally varies on user-agent, cookies,
locale-of-client, and is generally updated frequently.

Does Magento actually vary the content of CSS  JS based on user-agent?  Or
does it only vary the content of HTML?

You've dissuaded me from trying to infer the intent of the site
administrator, and we will find another way to phase in vary:user-agent
compliance without falling off a performance cliff.

-Josh

On Sun, Jun 5, 2011 at 2:54 PM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 On Sun, Jun 5, 2011 at 13:42, Joshua Marantz jmara...@google.com wrote:
  This is a case where the content varies based on user-agent.  The
  recommendation on the mod_deflate doc page is add vary:user-agent for any
  non-image.  Can you think of a case where the absence of a
 vary:user-agent
  header causes broken behavior when the content doesn't vary?
 
  I'm not objecting to setting vary:user-agent when content varies: that's
  what it's for.  I'm objecting to setting vary:user-agent when content
 does
  *not* vary.  The mod_deflate documentation unambiguously recommends
 setting
  vary:user-agent, and my feeling is that this is to work around a bug that
  exists only in IE5 or pre-2007 patch of IE6.

 Sorry, Joshua, we're conflating things. You raised two issues in your
 original post:

 1. Updating the mod_deflate documentation. Seems reasonable. The Vary:
 UA recommendation was added in 2002 during a general clean-up of the
 mod_deflate documentation and the commit log doesn't tell why. You
 could open a bugzilla issue or raise it on the httpd-dev mailing list
 (the former is the proper channel but the bugzilla is something of a
 graveyard).

 2. mod_pagespeed second-guessing the user's intent. That still seems
 like an unambiguously bad idea. To touch on Magento again, its
 documentation links (or linked) directly to that section of the
 mod_deflate docs and people are using that. If your module scans for
 and neutralizes that Header directive, you will break someone's site.



Vary:User-Agent, best practices, and making the web faster.

2011-06-04 Thread Joshua Marantz
Hi,

We've been working on a lingering HTTP-compliance issue in mod_pagespeed:
respecting Vary:User-Agent.  mod_pagespeed needs to cache resources in order
to optimize them.  The economics of this make sense when the server
optimizes a resource, and saves the optimization for serving to multiple
clients.

The problem is that this is, in general, expensive to do correctly when the
site owner has put Vary:User-Agent in the response header for, say, a css or
javascript file.  There are legitimate reasons to do this, such as serving a
different version of a CSS file to IE6.  But I think most sites don't do
that.  However, there is a disturbing passage in the document for
mod_deflate: http://httpd.apache.org/docs/2.2/mod/mod_deflate.html:

SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary

# Make sure proxies don't deliver the wrong content
Header append Vary User-Agent env=!dont-vary

This encourages all site owners to add Vary:User-Agent to all css and js
files, whether they actually vary in content or not.

Does anyone know the history of this recommendation?  Surely that is an
inappropriate recommendation for mod_deflate.  Vary:Accept-Encoding make
sense in the context of that filter, but not Vary:User-Agent.

The problem with defensively setting Vary:User-Agent is that any proxy cache
-- and in this respect mod_pagespeed acts like a proxy cache -- must fetch
origin content for each distinct user-agent.  While it's feasible for us to
employ a level of indirection in our cache so that we only store extra
copies of a resource when it actually differs -- this can, I fear, be
catestrophic to the cache working-set and hit-rate.  We couldn't get around
storing each distinct user-agent.


So, there are two questions:

1. Who can I lobby to get the recommendation changed for the mod_deflate
doc?  That recommendation seems incorrect /or obsolete.
2. Given that there are likely a huge number of sites that blindly followed
that recommendation, is there a straightforward way for mod_pagespeed to
correct the situation?  Specifically, can mod_pagespeed get access to apache
configuration parameters that were added by other filters, looking
specifically for the pattern quoted above with SetEnvIfNoCace  Header?  Is
it OK for mod_pagespeed to register for config-parameters owned by another
module?

I think what we'd do is basically let mod_pagespeed ignore Vary:User-Agent
if we saw that it was inserted per this exact pattern.  This would, to be
pendantic, violate  HTTP, but I think it would help make the web faster, and
in practice would help many more sites than it would hurt.  Sites that
specifically added vary:user-agent using a more specific construct, such as
identifying a particular CSS file that they want to Vary, would be treated
differently.

-Josh


Re: Vary:User-Agent, best practices, and making the web faster.

2011-06-04 Thread Joshua Marantz
It was with some reluctance that I brought this up.  It occurs to me that
this idea propagates the sort of spec violations that led to this issue
(inappropriate user of Vary:User-Agent) in the first place.   However, I'm
trying to figure out how to improve compliance to support legitimate uses of
Vary:User-Agent without causing mod_pagespeed to become significantly less
ineffective across a broad range of sites.

We have found that putting complaints in Apache logs mostly causes disks to
fill and servers to crash -- although that does get it noticed :).  The
problem, put another way, is that mod_pagespeed cannot distinguish
legitimate uses of Vary:User-Agent, so it really has no business complaining
in logs.  Complaining in docs is fine; but some existing mod_pagespeed users
that simply type sudo yum update will later notice a performance-drop and
may not consult the docs to figure out why.

I'm also trying to grok the first response from Eric:

It's because of the other (dated) canned exceptions that set/unset
no-gzip/gzip-only-text/html based on the User-Agent, to second-guess
browsers that send AE:gzip but can't properly deal with it.


Going backwards:  which browsers send AE:gzip but can't properly deal with
it?   Does IE6 have that issue or is it only true of IE5?   I know that IE6
has had issues with compression in the past but they appear to be addressed
by patches issued by Microsoft four and a half years ago:
http://support.microsoft.com/default.aspx?scid=kb;en-us;Q312496.  Moreover
IE6 is shrinking in market
sharehttp://arstechnica.com/web/news/2011/05/web-browser-market-share-upgrade-analysis.ars(~
10%) and IE5 does not appear in the pie-chart at all.

And I still don't understand how that relates to Vary:User-Agent.  What's
really at issue here seems more related to proxies; is that right?  That
proxies were not respecting Accept-Encoding, but sending gzipped content to
browsers that did not want it?  Is that still a problem?  Which proxies were
broken?  Are they still broken?

And, while I understand the reluctance to help me figure out from our module
what values were passed to SetEnvIfNoCase and Header, I would like to see
whether there's agreement that the Apache 2.2 docs for mod_deflate are no
longer appropriate -- and in fact harmful.

-Josh

On Sat, Jun 4, 2011 at 5:03 PM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 On Sat, Jun 4, 2011 at 21:26, Joshua Marantz jmara...@google.com wrote:
  I think what we'd do is basically let mod_pagespeed ignore
 Vary:User-Agent
  if we saw that it was inserted per this exact pattern.  This would, to be

 This seems like a stupendously bad idea. Warn about it in your docs,
 complain about it in the logs but don't willy-nilly override people's
 settings.



KeepAlive -- why is it off by default?

2011-04-11 Thread Joshua Marantz
webpagetest.org gives a big red *F *to web sites that do* *not have
KeepAlive enabled.  Yet, at least in the CentOS installation of Apache, it
is off by default.  Why is that?  What are the reasons that KeepAlive should
be off?

Although it's trivial to turn it on in httpd.conf, many web sites do not do
it.  We are debating turning it on by default in mod_pagespeed.  This seems
counterintuitive (and maybe beyond the moral boundaries of our module) but
lots of sites on the internet appear to install mod_pagespeed but not bother
to turn KeepAlive on.  So we could either (a) engage in a campaign to get
site owners to understand what KeepAlive is or (b) turn it on by default in
mod_pagespeed and perhaps give users an option to stop mod_pagespeed from
doing so.

What are the reasons someone might wish to turn KeepAlive off?  The only one
I can think of is in single-process mode (httpd -X) it can be a drag to
refresh a page with lots of resources; but this seems like a secondary issue
that could be worked around if needed.

-Josh


Re: how to parse html content in handler

2011-03-25 Thread Joshua Marantz
mod_pagespeed's event-driven HTML parser is open source, and is written in
C++:
http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/htmlparse/public/html_parse.h

http://code.google.com/p/modpagespeed/source/browse/trunk/src/net/instaweb/htmlparse/public/html_parse.hThis
parser is tested using HTML from large numbers of web sites.  The build
process for this module (
http://code.google.com/p/modpagespeed/wiki/HowToBuild) generates a separate
.a for the HTML parser, although it's got a few dependencies that would need
to be linked in.  These are all included in mod_pagespeed.so which is
self-contained but larger.

If there was much interest we could try to try to package up a
self-contained library that would make it easier to call from other modules.

See also libxml2, which has an HTML mode.

-Josh

On Fri, Mar 25, 2011 at 9:28 AM, MK m...@cognitivedissonance.ca wrote:

 On Thu, 24 Mar 2011 20:10:46 +0800 (CST)
 Whut  Jia whut_...@163.com wrote:
  Hi,all
  I want to parse a html content and withdraw some element in myself
  apache handler.Please ask how to do it. Thanks,
  Jia

 I think right now the only public C library for parsing html is in the
 venerable and long unmaintained libwww.

 However, I wrote a quick and simple, event driven parser library a few
 months ago -- I have been meaning to open source this on CCAN or
 somewhere but have not gotten around to it, so if you are interested
 you can send me a message directly, I have some basic scraper demos
 etc.   It is not on the scale of libwww -- it is just a low level HTML
 parser -- but I am sure it could do what you want, and you can either
 compile it in or link to with an apache module (it has no further
 dependencies).


 --
 Enthusiasm is not the enemy of the intellect. (said of Irving Howe)
 The angel of history[...]is turned toward the past. (Walter Benjamin)




Re: ordering output filters

2011-03-14 Thread Joshua Marantz
Thanks, Nick  Ben!

On Mon, Mar 14, 2011 at 1:31 PM, Nick Kew n...@apache.org wrote:

 AP_FTYPE_RESOURCE+1.  That also leaves an admin the possibility of
 overriding it.


I didn't realize these +1/-1 hacks were available for this API.  This looks
really simple  is the direction I'm leaning.


 Why not an insert_filter hook?


This is a really good question: I didn't know about this hook.  Is there a
good place I should go to learn about these hooks myself?  Of course, asking
this mailing-list has worked really well so far thanks to Ben  yourself 
others.

And in particular, adding an insert_filter hook sounds a little more complex
than the AP_FTYPE_RESOURCE+1 idea.  Is there some advantage to using
insert_filter hook?

-Josh


Saving the original request URI ahead of a mod_rewrite

2011-03-12 Thread Joshua Marantz
Hi,

A new bug has surfaced in mod_pagespeed that we understand, but would
welcome advice on the best way to fix.  The problem is tracked in
http://code.google.com/p/modpagespeed/issues/detail?id=234.

Briefly, 
mod_pagespeedhttp://code.google.com/speed/page-speed/docs/using_mod.htmlseeks
to improve the performance of web sites by rewriting them while being
served from Apache.   mod_pagespeed transforms the HTML text in an output
filter.  To do this correctly, mod_pagespeed needs to know what URL that
browser thinks it has when it is displaying a site.

The failure scenario is when a site has a RewriteRule in an .htaaccess file.
 The request-unparsed_uri gets rewritten by mod_rewrite, so by the time
mod_pagespeed runs it has the wrong idea of where the page is.  This makes
mod_pagespeed resolve relative URLs embedded in the HTML in a manner
inconsistent from the browser.  We thought we had a solution to this problem
by putting in an early-running hook that saves the original
request-unparsed_uri in request-notes.

That seems to work in some cases, but, we've found, not when the RewriteRule
is in an .htaccess file.  In that case, mod_rewrite triggers an internal
redirect, which causes an entirely new 'request' to be allocated, which
does *not* have a copy of the original request-notes.  It does make a
hacked version of request-subprocess_env however, prepending REDIRECT_ to
each key.  It also seems that the new request has a pointer to the original
request (which has the note) in request-prev.  But this new request,
without the notes, is the one that's passed to mod_pagespeed's output
filter, with request-unparsed_uri pointing to the rewritten URL, which is
not consistent with the browser's URL bar.

So I'm writing to this group to get suggestions on the most robust way to
fix this.  Here are some ideas:

1. Add an early 'create_request' hook and use that to copy the 'notes' that
we care about from request-prev.
2. Change from storing notes in request-notes to request-subprocess_env.
 When we go to do the lookup with our key, we can look up REDIRECT_key if a
note with our original key is not found.  This strikes me as a brittle hack.
3. Follow the request-prev chain when looking up notes.  This strikes me as
risky because I have no idea what happens to the -prev chain through all
the modules in the Apache eco-system, or how far down the chain I might have
to go.

So I like #1 best.  Any other opinions or ideas?

-Josh


Re: Help with apr mutex

2011-03-01 Thread Joshua Marantz
For convenience, you can look at these intriguing new facilities in the SVN
repo directly without downloading the tarball:

http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_socache.h?view=log
http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_socache.h?view=markup
http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_socache.h?view=markup
http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_slotmem.h?view=markup
http://svn.apache.org/viewvc/httpd/httpd/trunk/include/ap_slotmem.h?view=markup
http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_socache_shmcb.c?view=markup

http://svn.apache.org/viewvc/httpd/httpd/trunk/modules/cache/mod_socache_shmcb.c?view=markupIs
there any design doc or examples on how these can be used to, say, construct
a server-wide cache that can be accessed from any of the child processes in
(say) prefork mode?

Thanks!
-Josh

On Tue, Mar 1, 2011 at 10:36 AM, Simone Caruso i...@simonecaruso.comwrote:

 On 28/02/2011 22:48, Ben Noordhuis wrote:

 On Mon, Feb 28, 2011 at 18:26, Simone Carusoi...@simonecaruso.com
  wrote:

 I wrote a simple cache inside my module with apr_shm and apr_rmm


 Simone, have a look at ap_socache.h and ap_slotmem.h, they're two
 simple cache facilities that were added in 2.3.0. Might save you some
 work. :)


 I read trunk/modules/cache/mod_socache_shmcb.c too, looks very interesting!
 Surely I will rewrite my module for 2.3 using socache,
 thank you Ben.

 --
 Simone Caruso
 p.iva: 03045250838



Help trying to figure out why an output_filter is not called.

2011-01-05 Thread Joshua Marantz
One of the improvements mod_pagespeed is supposed to do to sites is extend
the cache lifetime of their resources indefinitely by including a content
hash in the URL.  This is working well for a large number of sites, but I
encountered one today where it does not work.

To accomplish the cache extension, overriding any wildcarded or
directory-based expire settings a site admin has set for their resources,
mod_pagespeed inserts two output filters.

The first one does the HTML rewriting:

  ap_register_output_filter(
  kModPagespeedFilterName, instaweb_out_filter, NULL,
AP_FTYPE_RESOURCE);

When instaweb_out_filter runs, it makes this transformation:

  before:  script src=foo.js/script
  after:   script src=foo.js.pagespeed.ce.HASH.js/script

The rewritten resource, foo.js.pagespeed.ce.HASH.js, is served by a hook:

  ap_hook_handler(instaweb_handler, NULL, NULL, APR_HOOK_FIRST - 1);

Knowing that mod_headers will later override Cache-Control, which we don't
want, our hook serves the .js file with our own header:

   X-Mod-Pagespeed-Repair: max-age=31536000

We a second output filter, to repair it:

  // We need our repair headers filter to run after mod_headers. The
  // mod_headers, which is the filter that is used to add the cache
settings, is
  // AP_FTYPE_CONTENT_SET. Using (AP_FTYPE_CONTENT_SET + 2) to make sure
that we
  // run after mod_headers.
  ap_register_output_filter(
  InstawebContext::kRepairHeadersFilterName, repair_caching_header,
NULL,
  static_castap_filter_type(AP_FTYPE_CONTENT_SET + 2));

This is added into the filter chain whenever we want to extend cache:

  apr_table_add(request-headers_out, X-Mod-Pagespeed-Repair,
cache_control);
  ap_add_output_filter(X-Mod-Pagespeed-Repair,
   NULL, request, request-connection);

When working properly, this header is removed from request-headers_out by
repair_caching_header():

  const char* cache_control = apr_table_get(request-headers_out,
X-Mod-Pagespeed-Repair);
  if (cache_control != NULL) {
SetCacheControl(cache_control, request);
apr_table_unset(request-headers_out, kRepairCachingHeader);
  }

Where SetCacheControl also makes the Expires header consistent, etc.

While this approach is complex, I've never seen it fail until today, on the
site http://law.thu.edu.tw/main.php . On that site, the
X-Mod-Pagespeed-Repair
header is visible (it should have been removed) and the Cache-Control header
has the value set from the conf files (public, max-age=600).   So on this
server, the repair_caching_header filter is not being run, despite having
been programatically inserted by our code in the same place where we add 
X-Mod-Pagespeed-Repair header.

What might be going wrong in his server to cause this to fail?  Could some
other filter be somehow finding our filter and killing it?  Or sending the
bytes directly to the network before our filter has a chance to run?

Thanks!
-Josh


Re: Help trying to figure out why an output_filter is not called.

2011-01-05 Thread Joshua Marantz
Thanks again for the fast response, Ben!

On Wed, Jan 5, 2011 at 8:57 AM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 On Wed, Jan 5, 2011 at 14:45, Joshua Marantz jmara...@google.com wrote:
  other filter be somehow finding our filter and killing it?  Or sending
 the
  bytes directly to the network before our filter has a chance to run?

 Possibly, yes.


Can you elaborate?   Is this a common practice, to write bytes directly to
the network from an output filter?  What should I look for?  The owner of
the site where this is breaking sent me a few conf files and it enumerates
some of the modules inserted:

LoadModule perl_module modules/mod_perl.so
LoadModule mono_module modules/mod_mono.so
LoadModule bwlimited_module modules/mod_bwlimited.so
LoadModule bw_module modules/mod_bw.so
LoadModule jk_module modules/mod_jk.so

Does anyone know anything about these?  Could one of these have inserted an
output filter that spews bytes directly to the network?  I'll try to find
sources for those but if someone knows off-hand that would be helpful.


 By the way, why the complex setup? If you don't want the mod_headers
 filter to run, insert your filter before it, then remove it for each
 request that you handle.


This is an interesting idea.

I guess we should eliminate FIXUP_HEADERS_OUT, FIXUP_HEADERS_ERR, and
MOD_EXPIRES.  Are there any other similar header-mucking-filters I need to
kill?  I don't mind squirreling through the source code to find these names
(all are string literals in .c files) but I'm nervous they could change
without warning in a future version.

Moreover, expires_insert_filter runs as APR_HOOK_MIDDLE which means it runs
after my content-generator, which means that it won't have been inserted by
the time when I want to set my caching headers.

I guess that means I have to insert a new late-running hook that kills
undesirable output filters.  Does that wind up being simpler?

-Josh


Re: Help trying to figure out why an output_filter is not called.

2011-01-05 Thread Joshua Marantz
On Wed, Jan 5, 2011 at 10:43 AM, Ben Noordhuis i...@bnoordhuis.nl wrote:

   I guess we should eliminate FIXUP_HEADERS_OUT, FIXUP_HEADERS_ERR, and
  MOD_EXPIRES.


 Are there any other similar header-mucking-filters I need to kill?

  Moreover, expires_insert_filter runs as APR_HOOK_MIDDLE which means it
 runs
  after my content-generator, which means that it won't have been inserted
 by
  the time when I want to set my caching headers.

 You can remove it from your handler, scan
 r-output_filters-frec-name to find the filter.


I'm not following you.  mod_expires.c has this:

static void expires_insert_filter(request_rec *r) {
  ...ap_add_output_filter(MOD_EXPIRES, NULL, r, r-connection);...
}

static void register_hooks(apr_pool_t *p) {
/* mod_expires needs to run *before* the cache save filter which is
 * AP_FTYPE_CONTENT_SET-1.  Otherwise, our expires won't be honored.
 */
ap_register_output_filter(MOD_EXPIRES, expires_filter, NULL,
  AP_FTYPE_CONTENT_SET-2);
ap_hook_insert_error_filter(expires_insert_filter, NULL, NULL,
APR_HOOK_MIDDLE);
ap_hook_insert_filter(expires_insert_filter, NULL, NULL,
APR_HOOK_MIDDLE);
}

So if I try to remove the 'expires' filter from my handler (which runs
early) then mod_expires will have a handler that runs later that inserts it
after my module has completed.  Hence:

 I guess that means I have to insert a new late-running hook that kills
  undesirable output filters.  Does that wind up being simpler?

 The above is probably easier but whatever ends up being the most
 readable / maintainable, right?


And also functional :) which, evidently, my current solution is not, at
least in the presence of mod_perl and mod_php.

Your solution has the advantage of being more robust when upstream filters
write directly to the network.  I just wish I didn't have to depend on my
copies of string literals from .c files I don't control.  But as you said
core-filters will hopefully not change internal string constants often.   I
just coded it up and it seems to work :)

-Josh


Re: Help trying to figure out why an output_filter is not called.

2011-01-05 Thread Joshua Marantz
This has certainly gotten off topic :)

http://www.google.com/search?sourceid=chromeie=UTF-8q=nginx+vs+apache has
lots of interesting opinions on the subject.

Having said that, mod_pagespeed's initial target is Apache because that's
the dominant server stack driving the web.  I'm optimistic that nginx will
also be a compelling opportunity at some point and I'm anxious to learn
more.



Now -- back on topic -- this issue is tracked as
http://code.google.com/p/modpagespeed/issues/detail?id=179 for those
following along at home, and hopefully will be resolved shortly based on the
advise of the contributors to this thread.

Thanks again, everyone,
-Josh

On Wed, Jan 5, 2011 at 8:40 PM, Ray Morris supp...@bettercgi.com wrote:

  Just a quick note since you mentioned nginx.  Nginx is of
 course normally used by people wanting higher performance than
 they are getting from Apache, because certain tests seemed to
 suggest that nginx can significantly outperform Apache in some
 cases. If that's the case for you, we learned something very
 interesting.

  We wondered how nginx could possibly be much faster since the
 speed of the disk itself is normally the limiting factor.  Was
 there something to be learned from nginx which could be applied
 to Apache?  At the end of all of the testing, we learned what
 caused the large apparent difference.  noatime.  Nginx effectively
 skips atime updates, which can make a huge difference.  By simply
 mounting the directory with the noatime option, any reasonable
 Apache configuration will have about the same performance as nginx,
 which is basically the performance of the underlying storage.

   People build complex systems with nginx as a proxy to Apache,
 but the same or better performance, with better standards compliance
 and better reliability, can be obtained by just setting noatime
 directly rather than using getting noatime accidentally as a
 side effect of nginx.

   With noatime set, one server or another might be 1% faster,
 but using TWO servers, with one as a proxy, will be slower than
 just simply using Apache, and in no case will nginx be SIGNIFICANTLY
 faster, when using noatime.
 --
 Ray Morris
 supp...@bettercgi.com

 Strongbox - The next generation in site security:
 http://www.bettercgi.com/strongbox/

 Throttlebox - Intelligent Bandwidth Control
 http://www.bettercgi.com/throttlebox/

 Strongbox / Throttlebox affiliate program:
 http://www.bettercgi.com/affiliates/user/register.php



 On 01/05/2011 03:16:21 PM, Ben Noordhuis wrote:

 On Wed, Jan 5, 2011 at 22:03, Joshua Marantz jmara...@google.com wrote:
  Right you are.  That's much simpler then.  Thanks!

 My pleasure, Joshua.

 Two quick questions, hope you don't mind: Is mod_pagespeed an official
 Google project? Or is it something you guys do on your day off? And
 are there plans for a nginx port?






Re: Help trying to figure out why an output_filter is not called.

2011-01-05 Thread Joshua Marantz
This is my day job at google.  We would love to do an nginx port but have
not scheduled it yet.

sent from my android
On Jan 5, 2011 4:16 PM, Ben Noordhuis i...@bnoordhuis.nl wrote:
 On Wed, Jan 5, 2011 at 22:03, Joshua Marantz jmara...@google.com wrote:
 Right you are.  That's much simpler then.  Thanks!

 My pleasure, Joshua.

 Two quick questions, hope you don't mind: Is mod_pagespeed an official
 Google project? Or is it something you guys do on your day off? And
 are there plans for a nginx port?


Re: Overriding mod_rewrite from another module

2011-01-03 Thread Joshua Marantz
OK I tried to find a more robust alternative but could not.  I was thinking
I could duplicate whatever mod_rewrite was doing to set the request filename
that appears to be complex and probably no less brittle.

I have another query on this.  In reality we do *not* want our rewritten
resources to be associated with a filename at all.  Apache should never look
for such things in the file system under ../htdocs -- they will not be
there.  We also do not need it to validate or authenticate on these static
resources.

In particular, we have found that there is some path through Apache that
imposes what looks like a file-system-based limitation on URL segments (e.g.
around 256 bytes).  This limitation is inconvenient and, as far as I can
tell, superfluous.  URL limits imposed by proxies and browsers are more like
2k bytes, which would allow us to encode more metadata in URLs (e.g.
sprites).  Is there some magic setting we could put into the request
structure to tell Apache not to interpret the request as being mapped from a
file, but just to pass it through to our handler?

Thanks!
-Josh

On Sat, Jan 1, 2011 at 6:24 AM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 On Sat, Jan 1, 2011 at 00:16, Joshua Marantz jmara...@google.com wrote:
  Thanks for the quick response and the promising idea for a hack.  Looking
 at
  mod_rewrite.c this does indeed look a lot more surgical, if, perhaps,
  fragile, as mod_rewrite.c doesn't expose that string-constant in any
 formal
  interface (even as a #define in a .h).  Nevertheless the solution is
  easy-to-implement and easy-to-test, so...thanks!

 You're welcome, Joshua. :)

 You could try persuading a core committer to add this as a
 (semi-)official extension. Nick Kew reads this list, Paul Querna often
 idles in #node.js at freenode.net.

  I'm also still wondering if there's a good source of official
 documentation
  for the detailed semantics of interfaces like ap_hook_translate_name.
   Neither a Google Search, a  stackoverflow.com search, nor the Apache
  Modules
 http://www.amazon.com/Apache-Modules-Book-Application-Development/dp/0132409674/ref=sr_1_1?ie=UTF8qid=1293837117sr=8-1
 book
  offer much detail.
  code.google.com fares a little better but just points to 4 existing
 usages.

 This question comes up often. In my experience the online
 documentation is almost always outdated, incomplete or outright wrong.
 I don't bother looking things up, I go straight to the source.

 It's a kind of job security, I suppose. There are only a handful of
 people that truly and deeply understand Apache. We can ask any hourly
 rate we want!



Re: Overriding mod_rewrite from another module

2011-01-03 Thread Joshua Marantz
I have implemented Ben's hack in mod_pagespeed in
http://code.google.com/p/modpagespeed/source/detail?r=345 .  It works great.
 But I am concerned that a subtle change to mod_rewrite.c will break this
hack silently.  We would catch it in our regression tests, but the large
number of Apache users that have downloaded mod_pagespeed do not generally
run our regression tests.

I have another idea for a solution that I'd like to see opinions on.
Looking at Nick Kew's book, it seems like I could set request-filename to
whatever I wanted, return OK, but then also shunt off access_checker for my
rewritten resources.  The access checking on mod_pagespeed resources is
redundant, because the resource will either be served from cache (in which
case it had to be authenticated to get into the cache in the first place) or
will be decoded and the original resource(s) fetched from the same server
with full authentication.

I'd appreciate any comments on this approach.

-Josh

On Mon, Jan 3, 2011 at 11:40 AM, Joshua Marantz jmara...@google.com wrote:

 OK I tried to find a more robust alternative but could not.  I was thinking
 I could duplicate whatever mod_rewrite was doing to set the request filename
 that appears to be complex and probably no less brittle.

 I have another query on this.  In reality we do *not* want our rewritten
 resources to be associated with a filename at all.  Apache should never look
 for such things in the file system under ../htdocs -- they will not be
 there.  We also do not need it to validate or authenticate on these static
 resources.

 In particular, we have found that there is some path through Apache that
 imposes what looks like a file-system-based limitation on URL segments (e.g.
 around 256 bytes).  This limitation is inconvenient and, as far as I can
 tell, superfluous.  URL limits imposed by proxies and browsers are more like
 2k bytes, which would allow us to encode more metadata in URLs (e.g.
 sprites).  Is there some magic setting we could put into the request
 structure to tell Apache not to interpret the request as being mapped from a
 file, but just to pass it through to our handler?

 Thanks!
 -Josh

 On Sat, Jan 1, 2011 at 6:24 AM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 On Sat, Jan 1, 2011 at 00:16, Joshua Marantz jmara...@google.com wrote:
  Thanks for the quick response and the promising idea for a hack.
  Looking at
  mod_rewrite.c this does indeed look a lot more surgical, if, perhaps,
  fragile, as mod_rewrite.c doesn't expose that string-constant in any
 formal
  interface (even as a #define in a .h).  Nevertheless the solution is
  easy-to-implement and easy-to-test, so...thanks!

 You're welcome, Joshua. :)

 You could try persuading a core committer to add this as a
 (semi-)official extension. Nick Kew reads this list, Paul Querna often
 idles in #node.js at freenode.net.

  I'm also still wondering if there's a good source of official
 documentation
  for the detailed semantics of interfaces like ap_hook_translate_name.
   Neither a Google Search, a  stackoverflow.com search, nor the Apache
  Modules
 http://www.amazon.com/Apache-Modules-Book-Application-Development/dp/0132409674/ref=sr_1_1?ie=UTF8qid=1293837117sr=8-1
 book
  offer much detail.
  code.google.com fares a little better but just points to 4 existing
 usages.

 This question comes up often. In my experience the online
 documentation is almost always outdated, incomplete or outright wrong.
 I don't bother looking things up, I go straight to the source.

 It's a kind of job security, I suppose. There are only a handful of
 people that truly and deeply understand Apache. We can ask any hourly
 rate we want!





Re: Overriding mod_rewrite from another module

2011-01-03 Thread Joshua Marantz
On Mon, Jan 3, 2011 at 4:50 PM, Ben Noordhuis i...@bnoordhuis.nl wrote:

   This means that returning OK from my handler does not prevent
  mod_authz_host's handler from being called.

 You're mistaken, Joshua. The access_checker hook by default is empty.
 mod_authz_host is a module and it can be disabled (if you're on a
 Debian/Ubuntu system, run `a2dismod authz_host` and reload Apache).


My perspective is that my team has implemented an Apache module that was
launched on Nov 3 2010.  Since its launch, we've encountered a variety of
compatibility reports with other modules, notably mod_rewrite.

My goal is not to remove authentication from the server; only from messing
with my module's rewritten resource.  The above statement is just observing
that, while it's possible to shunt off mod_rewrite by returning OK from an
upstream handler, the same is not true of mod_authz_host because it's
invoked with a different magic macro.

With respect to the URL length, I'm fairly sure it's nearly 8K (grep
 for HUGE_STRING_LEN in core_filters.c).


There may exist some buffer in Apache that's 8k.  But I have traced through
failing requests earlier that were more like 256 bytes.  This was reported
as mod_pagespeed Issue
9http://code.google.com/p/modpagespeed/issues/detail?id=9 and
resolved by limiting the number of css files that could be combined together
so that we did not exceed the pathname limitations.  I'm pretty sure it was
due to some built-in filter or core element in httpd trying to map the URL
to a filename (which is not necessary as far as mod_pagespeed is concerned)
and bumping into an OS path limitation (showing up as 403 Forbidden).

I confess I'm not entirely sure what you are trying to accomplish.
 You're serving up custom content and you're afraid mod_rewrite is
 going to munch the URL? Or is it more involved than that?


That's exactly right.  The simplest example is mod_pagespeed can infinitely
extend the cache lifetime of a js file, without compromising the site
owner's ability to propagate changes quickly, by putting an md5-hash of the
css content into the URL.

old: script src=scripts/hacks.js/script
new: script src=scripts/hacks.js*.pagespeed.ce.HASH.js*/script

If some mod_rewrite rule munges scripts/hacks.js.ce.pagespeed.HASH.js,
then mod_pagespeed will fail to serve it.

The issue is most simply stated in a Stack Overflow article:
http://stackoverflow.com/questions/4099659/mod-rewrite-mod-pagespeed-rewritecond

In this case, the user had hand-entered a mod_rewrite rule that broke
mod_pagespeed so it made sense for him to fix it there.  However, we have
heard reports of other cases where a user installs some content-generation
software that generate mod_rewrite rules that break mod_pagespeed.  Such
users may not even know what mod_rewrite is, so they can't easily work
around the broken rules.  This issue is reported as mod_pagespeed
Issue 63http://code.google.com/p/modpagespeed/issues/detail?id=63
.

Hope this clears things up.

I'm still interested in your opinion on my solution where I (inspired by
your hack) save the original URL in request-notes and then use *that* in my
resource handler in lieu of request-unparsed_uri.  This change is now
committed to svn trunk (but not released in a formal patch) as
http://code.google.com/p/modpagespeed/source/detail?r=348 .

-Josh


Re: Overriding mod_rewrite from another module

2011-01-03 Thread Joshua Marantz
On Mon, Jan 3, 2011 at 6:15 PM, Eric Covener cove...@gmail.com wrote:

  The access checking on mod_pagespeed resources is
  redundant, because the resource will either be served from cache (in
 which
  case it had to be authenticated to get into the cache in the first
 place) or
  will be decoded and the original resource(s) fetched from the same
 server
  with full authentication.

 Re: suppressing mod_authz_host: This doesn't sound like it guards
 against a user that meets the AAA conditions causing the resource to
 be cached and served to users who would not have met the AAA
 restrictions.


This is a good point, but I think I'm covered.  mod_pagespeed will only
rewrite resources that are publicly cacheable.  What does AAA stand for?
 Authorization  Authentication in Apache or something?  In any case I've
abandoned, for the moment, the attempt to bypass mod_authz_host on a
per-request basis.


 Maybe you are missing a map_to_storage callback to tell
 the core that this thing will really, really not be served from the
 filesystem.


I was not aware of the concept of a map_to_storage callback at all.  I
will have to investigate.  This may be very helpful.  Thanks.


 Re: suppressing rewrite.  Your comments in the src imply that rewrite
 is doing some of what you're also suppressing in
 server/core.c:ap_core_translate_name().  Also, it's odd that your
 scheme for suppressing mod_rewrite wasn't a no-op for rewrite in
 htaccess context, since these use the RUN_ALL fixups hook to do its
 magic, but maybe you're catching a break there?


It's quite possible that the previous hack where we use the node
mod_rewrite_rewritten would break if mod_rewrite.c:hook_uri2file's
functional component could get called by mod_rewrite.c:hook_fixup, but I
haven't analyzed the module deeply enough to understand it at that level.

But I think the present hack, where we don't turn off mod_rewrite but just
ignore its output via our own request-note will be more robust.  At least I
hope it will.

In my testing 2 weeks ago I had trouble invoking mod_rewrite from .htaccess.
 I'll have to try again.

-Josh


Re: Overriding mod_rewrite from another module

2011-01-03 Thread Joshua Marantz
I answered my own question by implementing it and failing.  You can't bypass
mod_authz_host because it gets invoked via the magic macro:

  AP_IMPLEMENT_HOOK_RUN_ALL(int,access_checker,
  (request_rec *r), (r), OK, DECLINED)

This means that returning OK from my handler does not prevent
mod_authz_host's handler from being called.

I came up with a simpler idea that does not require depending on
string-literals in mod_rewrite.c.

I still add a translate_name hook to run prior to mod_rewrite, but I don't
try to prevent mod_rewrite from corrupting my URL. Instead I just squirrel
away the uncorrupted URL in my own entry in request-notes so that I can use
that rather than request-unparsed_uri downstream when processing the
request.  This seems to work well.  The only drawback is if the site admin
adds a mod_rewrite rule that mutates mod_pagespeed's resource name into
something that does not pass authentication, then mod_authz_host will reject
the request before I can process it.  This seems like a reasonable tradeoff
as that configuration would likely be borked in other ways besides
mod_pagespeed resources.

Commentary would be welcome.

-Josh

On Mon, Jan 3, 2011 at 1:10 PM, Joshua Marantz jmara...@google.com wrote:

 I have implemented Ben's hack in mod_pagespeed in
 http://code.google.com/p/modpagespeed/source/detail?r=345 .  It works
 great.  But I am concerned that a subtle change to mod_rewrite.c will break
 this hack silently.  We would catch it in our regression tests, but the
 large number of Apache users that have downloaded mod_pagespeed do not
 generally run our regression tests.

 I have another idea for a solution that I'd like to see opinions on.
 Looking at Nick Kew's book, it seems like I could set request-filename to
 whatever I wanted, return OK, but then also shunt off access_checker for my
 rewritten resources.  The access checking on mod_pagespeed resources is
 redundant, because the resource will either be served from cache (in which
 case it had to be authenticated to get into the cache in the first place) or
 will be decoded and the original resource(s) fetched from the same server
 with full authentication.

 I'd appreciate any comments on this approach.

 -Josh


 On Mon, Jan 3, 2011 at 11:40 AM, Joshua Marantz jmara...@google.comwrote:

 OK I tried to find a more robust alternative but could not.  I was
 thinking I could duplicate whatever mod_rewrite was doing to set the request
 filename that appears to be complex and probably no less brittle.

 I have another query on this.  In reality we do *not* want our rewritten
 resources to be associated with a filename at all.  Apache should never look
 for such things in the file system under ../htdocs -- they will not be
 there.  We also do not need it to validate or authenticate on these static
 resources.

 In particular, we have found that there is some path through Apache that
 imposes what looks like a file-system-based limitation on URL segments (e.g.
 around 256 bytes).  This limitation is inconvenient and, as far as I can
 tell, superfluous.  URL limits imposed by proxies and browsers are more like
 2k bytes, which would allow us to encode more metadata in URLs (e.g.
 sprites).  Is there some magic setting we could put into the request
 structure to tell Apache not to interpret the request as being mapped from a
 file, but just to pass it through to our handler?

 Thanks!
 -Josh

 On Sat, Jan 1, 2011 at 6:24 AM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 On Sat, Jan 1, 2011 at 00:16, Joshua Marantz jmara...@google.com
 wrote:
  Thanks for the quick response and the promising idea for a hack.
  Looking at
  mod_rewrite.c this does indeed look a lot more surgical, if, perhaps,
  fragile, as mod_rewrite.c doesn't expose that string-constant in any
 formal
  interface (even as a #define in a .h).  Nevertheless the solution is
  easy-to-implement and easy-to-test, so...thanks!

 You're welcome, Joshua. :)

 You could try persuading a core committer to add this as a
 (semi-)official extension. Nick Kew reads this list, Paul Querna often
 idles in #node.js at freenode.net.

  I'm also still wondering if there's a good source of official
 documentation
  for the detailed semantics of interfaces like ap_hook_translate_name.
   Neither a Google Search, a  stackoverflow.com search, nor the Apache
  Modules
 http://www.amazon.com/Apache-Modules-Book-Application-Development/dp/0132409674/ref=sr_1_1?ie=UTF8qid=1293837117sr=8-1
 book
  offer much detail.
  code.google.com fares a little better but just points to 4 existing
 usages.

 This question comes up often. In my experience the online
 documentation is almost always outdated, incomplete or outright wrong.
 I don't bother looking things up, I go straight to the source.

 It's a kind of job security, I suppose. There are only a handful of
 people that truly and deeply understand Apache. We can ask any hourly
 rate we want!






Overriding mod_rewrite from another module

2010-12-31 Thread Joshua Marantz
I need to find the best way to prevent mod_rewrite from renaming resources
that are generated by a different module, specifically mod_pagespeed.  This
needs to be done from within mod_pagespeed, rather than asking the site
admin to tweak his rule set.

By reading mod_rewrite.c, I found a mechanism that appears to work.  But it
has its own issues and I'm having trouble finding any relevant doc about the
mechanism:

ap_hook_translate_name(bypass_translators, APR_HOOK_FIRST -1);

bypass_translators returns OK for resources generated by the module,
preventing mod_rewrite from disturbing them.  It returns DECLINED for other
resources.

The trouble is that httpd seems to report error messages in the log for the
lack of a filename.  We can set the request-filename to something but that
causes the requests to fail completely on some servers.  We haven't isolated
the difference between servers that can handle the fake filename and ones
that can't yet.

Is there a better way to solve the original problem: preventing mod_rewrite
from corrupting mod_pagespeed's resources?

Or is there better doc on the semantics of the request.filename field in the
context of a resource that is not stored as a file?  Or on
ap_hook_translate_name?

sent from my android


Re: Overriding mod_rewrite from another module

2010-12-31 Thread Joshua Marantz
Thanks for the quick response and the promising idea for a hack.  Looking at
mod_rewrite.c this does indeed look a lot more surgical, if, perhaps,
fragile, as mod_rewrite.c doesn't expose that string-constant in any formal
interface (even as a #define in a .h).  Nevertheless the solution is
easy-to-implement and easy-to-test, so...thanks!

I'm also still wondering if there's a good source of official documentation
for the detailed semantics of interfaces like ap_hook_translate_name.
 Neither a Google Search, a  stackoverflow.com search, nor the Apache
Moduleshttp://www.amazon.com/Apache-Modules-Book-Application-Development/dp/0132409674/ref=sr_1_1?ie=UTF8qid=1293837117sr=8-1book
offer much detail.
code.google.com fares a little better but just points to 4 existing usages.

-Josh

On Fri, Dec 31, 2010 at 1:50 PM, Ben Noordhuis i...@bnoordhuis.nl wrote:

 On Fri, Dec 31, 2010 at 18:17, Joshua Marantz jmara...@google.com wrote:
  Is there a better way to solve the original problem: preventing
 mod_rewrite
  from corrupting mod_pagespeed's resources?

 From memory and from a quick peek at mod_rewrite.c: in your
 translate_name hook, set a mod_rewrite_rewritten note in r-notes
 with value 0 and return DECLINED. That'll trick mod_rewrite into
 thinking that it has already processed the request.



Re: Howto unittest httpd modules?

2010-11-22 Thread Joshua Marantz
For mod_pagespeed
http://code.google.com/speed/page-speed/docs/module.htmlwe do 2 of
the 3 testing modes discussed.

We have the majority of our code running independent of Apache so it can be
aggressively unit-tested with googletesthttp://code.google.com/p/googletest/
.

We also have automated system-tests with our module running inside of
Apache.  They are pretty painless once it is set up.  We use 'wget' for
control and observation.  This doesn't have nearly the functional coverage
of the unit tests but does check that stuff is hooked up and working in the
system:

http://code.google.com/p/modpagespeed/source/browse/trunk/src/install/system_test.sh

http://code.google.com/p/modpagespeed/source/browse/trunk/src/install/system_test.shWe
also have stress tests that work in a similar way.

http://code.google.com/p/modpagespeed/source/browse/trunk/src/install/stress_test.sh

Our development flow integrates the system-test into the pre-submit checks;
it really doesn't take very much time at all.  It does require that every
developer has a debug instance of Apache into which they can automatically
copy modules and restart servers.

We have talked about writing a 'fakehttp://en.wikipedia.org/wiki/Mock_object'
Apache so that we could properly unit-test all of our code.  But given the
speed of automated system testing, it seems unlikely we'd focus on this
anytime soon.

Hope this helps,
-Josh

On Mon, Nov 22, 2010 at 5:05 AM, Edgar Frank ef-li...@email.de wrote:

 2010/11/11 Sorin Manolache:
 On Thu, Nov 11, 2010 at 08:11, Edgar Frank ef-li...@email.de wrote:
  I've written a handful of modules for httpd. I'm now looking for a way
 to setup some unit tests. We have continuous integration running, so I want
 to supply some tests, starting from compiling against httpd to basic
 functionality to more elaborate feature tests.
 
  I wonder how to unit-test this, as the prerequsites are rather
 complicated. The tests would have to setup a httpd, provide a config,
 compile and install the modules. As you don't want to modify the modules
 themselves, you have to run a bunch of requests and monitor expected output
 - maybe measuring coverage or running valgrind on the way.
 
  I see no way to run real unit tests as you would have to emulate httpd
 and run your modules against it, as most of the code is httpd or at least
 highly APR dependent. I see no point in emulating httpd as you would have to
 implement every little detail - httpd specific behaviour (e.g. in version
 bumps) is one important thing to test IMHO.
 
  So, has anyone some experience with this, some suggestions, howtos or
 tutorials? Any help would be greatly appreciated.
 
 In our group we unit test only parts of our modules. We unit test the
 callbacks and their sequence (a sort of poor-man's emulation of
 httpd). We populate a request_rec structure and then we pass it to the
 various callbacks.
 
 Our callbacks are mainly wrappers around bigger functions that are
 httpd-independent. The apache filters are tested in this way.
 
 The part that needed more code in order to emulate httpd was the
 subrequest infrastructure.

 Thanks for your reply. Unfortunately this is the way we're trying to avoid
 if possible.

 Has anyone else some hints or best pratices, besides emulating httpd? Is
 there even another way?

 Regards,
 Edgar