You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@tomcat.apache.org by Ran Berenfeld <ic...@ichess.co.il> on 2011/01/16 09:08:48 UTC

Setting HTTP response headers caching for 1 year doesn't work

Hello

I'm trying to set caching for 1 year for my static context (js,css and
images)
however seems like caching is only done for 2-3 weeks. below I put my
caching filter
and a response for some js file request.

I've added this code in a special "catch-all" filter and verified that all
resources
are indeed going through this filter :

    // cache for 1 year
    private static final long _cacheTime = (1000 * 60 * 60 * 24 * 365);

    public void doFilter(ServletRequest req, ServletResponse res,
FilterChain chain) throws IOException, ServletException {

        HttpServletRequest hreq = (HttpServletRequest)req;
        HttpServletResponse hres = (HttpServletResponse)res;

        hreq.setCharacterEncoding("UTF-8");

        hres.setHeader("Vary", "Accept-Encoding");
                hres.setCharacterEncoding("UTF-8");
        // put caching for 1 year for images and js, css files

        if ((path.endsWith(".png")) || (path.endsWith(".jpg")) ||
(path.endsWith(".gid"))) {
            // put caching for 1 year for images and js, css files
            hres.setHeader("Cache-Control", "public: max-age=31536000");
            hres.setDateHeader("Expires", Utils.now().getTime() +
_cacheTime);
        } else if ((path.endsWith(".js")) || (path.endsWith(".css"))) {
            // put caching for 1 year for images and js, css files
            hres.setHeader("Cache-Control", "public: max-age=31536000");
            hres.setDateHeader("Expires", Utils.now().getTime() +
_cacheTime);
        } else {
            // don't cache servlets or HTML - override headers
            hres.setHeader("Pragma", "no-cache");
            hres.setHeader("Cache-Control", "private, no-store, no-cache,
must-revalidate");
            hres.setHeader("Expires", "0");
        }
        passFilter(req, res, chain);
    }


now the problem is that the caching is set "only" for something like 2-3
weeks.
here is an example of response headers for some js file :
*
*

   1. Request URL:
   http://www.ichess.co.il/scripts/tiny_mce/tiny_mce.js
   2. Request Method:
   GET
   3. Status Code:
   200 OK
   4. Request Headers
      1. Accept:
      */*
      2. Referer:
      http://www.ichess.co.il/
      3. User-Agent:
      Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/534.10
      (KHTML, like Gecko) Chrome/8.0.552.237 Safari/534.10
      5. Response Headers
      1. Accept-Ranges:
      bytes
      2. Age:
      138
      3. Cache-Control:
      public: max-age=31536000
      4. Connection:
      Keep-Alive
      5. Content-Length:
      181324
      6. Content-Type:
      text/javascript;charset=UTF-8
      7. *Date:*
      *Sun, 16 Jan 2011 07:40:28 GMT*
      8. ETag:
      W/"181324-1294691843184"
      9. *Expires:*
      *Wed, 02 Feb 2011 08:20:57 GMT*
      10. Last-Modified:
      Mon, 10 Jan 2011 20:37:23 GMT
      11. Proxy-Connection:
      Keep-Alive
      12. Server:
      Apache-Coyote/1.1
      13. Vary:
      Accept-Encoding
      14. Via:
      1.1 TLVPROXY01




-- 
רן ברנפלד
מנהל
אתר השחמט הישראלי
*http://www.ichess.co.il*

Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Peter Crowther <pe...@melandra.com>.
On 19 January 2011 15:53, Caldarale, Charles R
<Ch...@unisys.com> wrote:
> No, most hardware (e.g., all flavors of x86) just sets a flag indicating that an overflow has occurred; it's up to the executing program to check the flag.

And on some machines (again, x86 springs to mind) it's easier to check
some flags than others.  I needed to do this for some stats software
recently.  Detecting FP overflow was easy ("there's an instruction for
that"), detecting integer overflow was significantly harder.

- Peter

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Jeffrey Janner <Je...@PolyDyne.com>.
Thanks for the clarification on the hardware Chuck.
Like I said, my detailed hardware kb hasn't been updated in quite a while.
I did mean either a flag or interrupt. It has been decades since I did "serious" coding, at least serious enough to go into that level of detail.
Jeff

> -----Original Message-----
> From: Caldarale, Charles R [mailto:Chuck.Caldarale@unisys.com]
> Sent: Wednesday, January 19, 2011 9:54 AM
> To: Tomcat Users List
> Subject: RE: [OT] Setting HTTP response headers caching for 1 year
> doesn't work
> 
> > From: Jeffrey Janner [mailto:Jeffrey.Janner@PolyDyne.com]
> > Subject: RE: [OT] Setting HTTP response headers caching for 1 year
> doesn't work
> 
> > My hardware internals knowledge is just as rusty as my coding
> > skills, but doesn't the hardware catch the overflow and raise
> > the exception anyway?
> 
> No, most hardware (e.g., all flavors of x86) just sets a flag
> indicating that an overflow has occurred; it's up to the executing
> program to check the flag.  Some CPUs have the capability of optionally
> generating an interrupt if the condition occurs, but again, that's
> under program control.  And, of course, the mechanisms for integer and
> floating point operations are usually completely independent (partly
> because the Intel floating point was originally on a co-processor).
> 
>  - Chuck
> 
> 
> THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE
> PROPRIETARY MATERIAL and is thus for use only by the intended
> recipient. If you received this in error, please contact the sender and
> delete the e-mail and its attachments from all computers.

__________________________________________________________________________

Confidentiality Notice:  This Transmission (including any attachments) may contain information that is privileged, confidential, and exempt from disclosure under applicable law.  If the reader of this message is not the intended recipient you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited.  

If you have received this transmission in error, please immediately reply to the sender or telephone (512) 343-9100 and delete this transmission from your system.

RE: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Jeffrey Janner [mailto:Jeffrey.Janner@PolyDyne.com] 
> Subject: RE: [OT] Setting HTTP response headers caching for 1 year doesn't work

> My hardware internals knowledge is just as rusty as my coding 
> skills, but doesn't the hardware catch the overflow and raise
> the exception anyway?
 
No, most hardware (e.g., all flavors of x86) just sets a flag indicating that an overflow has occurred; it's up to the executing program to check the flag.  Some CPUs have the capability of optionally generating an interrupt if the condition occurs, but again, that's under program control.  And, of course, the mechanisms for integer and floating point operations are usually completely independent (partly because the Intel floating point was originally on a co-processor).

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


RE: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Jeffrey Janner <Je...@PolyDyne.com>.

> -----Original Message-----
> From: Caldarale, Charles R [mailto:Chuck.Caldarale@unisys.com]
> Sent: Wednesday, January 19, 2011 9:13 AM
> To: Tomcat Users List
> Subject: RE: [OT] Setting HTTP response headers caching for 1 year
> doesn't work
> 
> > From: Jeffrey Janner [mailto:Jeffrey.Janner@PolyDyne.com]
> > Subject: RE: [OT] Setting HTTP response headers caching for 1 year
> doesn't work
> 
> > Does the Java compiler do this?  One would think so, but judging
> > from the results you guys are displaying, it seems not.
> 
> javac does do the constant expression evaluation (look in the constant
> pool); it just fails to detect the truncation.

Ah, room for improvement in javac then.

> 
> > by the default run-time catch is to ignore and return.
> 
> Again, the C _standard_ requires that overflow be ignored at runtime,
> so on most hardware, no exception occurs.
> 

My hardware internals knowledge is just as rusty as my coding skills, but doesn't the hardware catch the overflow and raise the exception anyway?  It's just a matter of have the exception-handling code in place, right?

(Life is so much nicer when you're only running machines instead of coding for them.  Much less detail to remember.)
Jeff
__________________________________________________________________________

Confidentiality Notice:  This Transmission (including any attachments) may contain information that is privileged, confidential, and exempt from disclosure under applicable law.  If the reader of this message is not the intended recipient you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited.  

If you have received this transmission in error, please immediately reply to the sender or telephone (512) 343-9100 and delete this transmission from your system.

RE: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Jeffrey Janner [mailto:Jeffrey.Janner@PolyDyne.com] 
> Subject: RE: [OT] Setting HTTP response headers caching for 1 year doesn't work

> Does the Java compiler do this?  One would think so, but judging 
> from the results you guys are displaying, it seems not.

javac does do the constant expression evaluation (look in the constant pool); it just fails to detect the truncation.

> by the default run-time catch is to ignore and return.

Again, the C _standard_ requires that overflow be ignored at runtime, so on most hardware, no exception occurs.

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


RE: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Jeffrey Janner <Je...@PolyDyne.com>.

> -----Original Message-----
> From: André Warnier [mailto:aw@ice-sa.com]
> Sent: Wednesday, January 19, 2011 5:52 AM
> To: Tomcat Users List
> Subject: Re: [OT] Setting HTTP response headers caching for 1 year
> doesn't work
> 
> Christopher Schultz wrote:
> > -----BEGIN PGP SIGNED MESSAGE-----
> > Hash: SHA1
> >
> > André,
> >
> > (You always make me write so much code!)
> 
> I don't /make/ you write code, I just provide the inspiration.
> I'm quite good at that, when I don't have to do the work myself.
> Thanks for writing the code in question though, it is nice getting to
> the bottom of an issue.
> 
> About this :
>  > Note that it's the Java compiler not the runtime that fails to
> deliver
>  > an error. The compiled C code happily overflows without any warning.
> Had
>  > I written the code using an array to store the operands and used an
> int
>  > to store the temporary result, you'd see the same truncation
> behavior
>  > with no compiler warnings. The fact that constants are being used
> are
>  > allowing the compiler to complain in this case.
> 
> Nitpick:
> I am not sure that it is the use of constants that allows the compiler
> to complain.
> Let's check that with a sample freely adapted from yours:
> 
> #include <stdio.h>
> 
> int main(int argc, char *argv[]) {
> 
> int thousand = 1000;
> int sixty = 60;
> int twentyfour = 24;
> int hundred = 100;
> int three = 3;
> 
>    int cacheTime1 = (1000 * 60 * 60 * 24 * 100 * 3);
>    long cacheTime2 = ((long)1000 * 60 * 60 * 24 * 100 * 3);
>    long long cacheTime3 = ((long long)1000 * 60 * 60 * 24 * 100 * 3);
>    long long cacheTime4 = (1000 * 60 * 60 * 24 * 100 * (long long)3);
>    long long cacheTime5 = (thousand * sixty * sixty * twentyfour *
> hundred * three);
> 
>    printf("%d\n%ld\n%lld\n%lld\n%lld\n", cacheTime1, cacheTime2,
> cacheTime3,
> cacheTime4,cacheTime5);
> 
>    return 0;
> }
> 
> aw@arthur:~/tests$ cc -ansi -pedantic -Wall -o longtime2 longtime2.c &&
> ./longtime2
> longtime2.c: In function 'main':
> longtime2.c:11: warning: integer overflow in expression
> longtime2.c:12: warning: integer overflow in expression
> longtime2.c:13: warning: ISO C90 does not support 'long long'
> longtime2.c:13: warning: ISO C90 does not support 'long long'
> longtime2.c:14: warning: ISO C90 does not support 'long long'
> longtime2.c:14: warning: integer overflow in expression        <===
> ****
> longtime2.c:14: warning: ISO C90 does not support 'long long'
> longtime2.c:15: warning: ISO C90 does not support 'long long'
> longtime2.c:18: warning: ISO C90 does not support the 'll' printf
> length modifier
> longtime2.c:18: warning: ISO C90 does not support the 'll' printf
> length modifier
> longtime2.c:18: warning: ISO C90 does not support the 'll' printf
> length modifier
> 150196224
> 150196224
> 25920000000
> 150196224
> 150196224
> 
> Aha.  So, it seems that the C compiler is smart enough to see that,
> potentially,
> multiplying an int variable by an int /might/ generate an overflow.
> Or else, it is smart enough to see that the defined int variables are
> in fact never
> modified in the scope of the function, and it internally optimises them
> as int constants,
> and then complains.
> Either way, it is smart.
> 
> Maybe the Java compiler cannot afford to do that, because it is used in
> "just-in-time"
> compilations ?
> 

The reason the C compiler "catches" this overflow is actually due to the built-in optimization.
Whenever it comes across a constant expression, it actually executes the expression at compile time (based on assumed or explicit typing) and then stores the result a single referenced constant.  You should be able to verify this by having the compiler generate the assembler listing it's going to use to generate the machine code.

This is a common optimization "trick" used by a number of compilers for decades.

Does the Java compiler do this?  One would think so, but judging from the results you guys are displaying, it seems not.

I've been out the coding biz too long, so I don't remember everything, but I think there are options you can turn on when compiling C that will add overflow checks for you to generate error at runtime.  I seem to remember they were defaulted on for the last compiler I used.  Then again, maybe it is generating the exception, by the default run-time catch is to ignore and return.

Jeff
__________________________________________________________________________

Confidentiality Notice:  This Transmission (including any attachments) may contain information that is privileged, confidential, and exempt from disclosure under applicable law.  If the reader of this message is not the intended recipient you are hereby notified that any dissemination, distribution, or copying of this communication is strictly prohibited.  

If you have received this transmission in error, please immediately reply to the sender or telephone (512) 343-9100 and delete this transmission from your system.

Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

André,

On 1/19/2011 6:52 AM, André Warnier wrote:
> #include <stdio.h>
> 
> int main(int argc, char *argv[]) {
> 
> int thousand = 1000;
> int sixty = 60;
> int twentyfour = 24;
> int hundred = 100;
> int three = 3;
> 
>   int cacheTime1 = (1000 * 60 * 60 * 24 * 100 * 3);
>   long cacheTime2 = ((long)1000 * 60 * 60 * 24 * 100 * 3);
>   long long cacheTime3 = ((long long)1000 * 60 * 60 * 24 * 100 * 3);
>   long long cacheTime4 = (1000 * 60 * 60 * 24 * 100 * (long long)3);
>   long long cacheTime5 = (thousand * sixty * sixty * twentyfour *
> hundred * three);
> 
>   printf("%d\n%ld\n%lld\n%lld\n%lld\n", cacheTime1, cacheTime2, cacheTime3,
> cacheTime4,cacheTime5);
> 
>   return 0;
> }
> 
> aw@arthur:~/tests$ cc -ansi -pedantic -Wall -o longtime2 longtime2.c &&
> ./longtime2
> longtime2.c: In function 'main':
> longtime2.c:11: warning: integer overflow in expression
> longtime2.c:12: warning: integer overflow in expression
> longtime2.c:13: warning: ISO C90 does not support 'long long'
> longtime2.c:13: warning: ISO C90 does not support 'long long'
> longtime2.c:14: warning: ISO C90 does not support 'long long'
> longtime2.c:14: warning: integer overflow in expression        <=== ****

Line 14 looks like "long long cacheTime4..." not the one you're looking
for. Yours is on line 15 where no warning was indicated.

> Maybe the Java compiler cannot afford to do that, because it is used in
> "just-in-time" compilations ?

No, Java has a well-defined conversion system regardless of the
underlying platform, so the compiler should be able to check. It just
doesn't apparently.

>> I couldn't make head or tail out of the timeit() function's return
>> value, so I just used 'time' from the command line to see what really
>> happened.
>>
> Neither could I, so I rewrote your test program somewhat (and decreased
> the loop by a factor 10, to be practical):

(Just get a bigger machine :)

> #!/usr/bin/perl
> 
> use Benchmark;
> 
> my $loops = 10000000;
> NORMAL:{
> my $left = 10;
> my $right = 3;
> my $res = $left / $right;
> print "\'NORMAL\' result : $res\n";
> my $t0 = Benchmark->new;
> for (my $i=0; $i<$loops; $i++) {
>   my $res = $left / $right;
> }
> my $t1 = Benchmark->new;
> my $td = timediff($t1, $t0);
> print "\'NORMAL\' times :",timestr($td),"\n";
> }
> 
> INTEGER:{
> use integer;

So, does "use integer" set the arithmetic evaluation strategy? I've
never see that before (though I'm not a seasoned Perl programmer).

> Note that for the BIGFLOAT and BIGINT sections, you need to be *really*
> patient.
> I interrupted at after maybe 10 minutes..

What, you didn't run it yourself? :( I ran mine for you :)

> Funny thing is, the INTEGER section seems actually slower than the
> standard one.

I'll have to run your test and see what happens.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk03E2YACgkQ9CaO5/Lv0PBRRQCgsueTU+jBVycQrS4b9eRapUaE
3FIAnjr5EhzCckAwhisNS99ZrxjdDqFV
=Q0gR
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by André Warnier <aw...@ice-sa.com>.
Christopher Schultz wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> André,
> 
> (You always make me write so much code!)

I don't /make/ you write code, I just provide the inspiration.
I'm quite good at that, when I don't have to do the work myself.
Thanks for writing the code in question though, it is nice getting to the bottom of an issue.

About this :
 > Note that it's the Java compiler not the runtime that fails to deliver
 > an error. The compiled C code happily overflows without any warning. Had
 > I written the code using an array to store the operands and used an int
 > to store the temporary result, you'd see the same truncation behavior
 > with no compiler warnings. The fact that constants are being used are
 > allowing the compiler to complain in this case.

Nitpick:
I am not sure that it is the use of constants that allows the compiler to complain.
Let's check that with a sample freely adapted from yours:

#include <stdio.h>

int main(int argc, char *argv[]) {

int thousand = 1000;
int sixty = 60;
int twentyfour = 24;
int hundred = 100;
int three = 3;

   int cacheTime1 = (1000 * 60 * 60 * 24 * 100 * 3);
   long cacheTime2 = ((long)1000 * 60 * 60 * 24 * 100 * 3);
   long long cacheTime3 = ((long long)1000 * 60 * 60 * 24 * 100 * 3);
   long long cacheTime4 = (1000 * 60 * 60 * 24 * 100 * (long long)3);
   long long cacheTime5 = (thousand * sixty * sixty * twentyfour * hundred * three);

   printf("%d\n%ld\n%lld\n%lld\n%lld\n", cacheTime1, cacheTime2, cacheTime3,
cacheTime4,cacheTime5);

   return 0;
}

aw@arthur:~/tests$ cc -ansi -pedantic -Wall -o longtime2 longtime2.c && ./longtime2
longtime2.c: In function 'main':
longtime2.c:11: warning: integer overflow in expression
longtime2.c:12: warning: integer overflow in expression
longtime2.c:13: warning: ISO C90 does not support 'long long'
longtime2.c:13: warning: ISO C90 does not support 'long long'
longtime2.c:14: warning: ISO C90 does not support 'long long'
longtime2.c:14: warning: integer overflow in expression        <=== ****
longtime2.c:14: warning: ISO C90 does not support 'long long'
longtime2.c:15: warning: ISO C90 does not support 'long long'
longtime2.c:18: warning: ISO C90 does not support the 'll' printf length modifier
longtime2.c:18: warning: ISO C90 does not support the 'll' printf length modifier
longtime2.c:18: warning: ISO C90 does not support the 'll' printf length modifier
150196224
150196224
25920000000
150196224
150196224

Aha.  So, it seems that the C compiler is smart enough to see that, potentially, 
multiplying an int variable by an int /might/ generate an overflow.
Or else, it is smart enough to see that the defined int variables are in fact never 
modified in the scope of the function, and it internally optimises them as int constants, 
and then complains.
Either way, it is smart.

Maybe the Java compiler cannot afford to do that, because it is used in "just-in-time" 
compilations ?

...

> 
> $ time ./divisionSpeedTest.pl
> 
>  2 wallclock secs ( 1.50 usr +  0.06 sys =  1.56 CPU) @ 64102564.10/s
> (n=100000000)
> real    0m46.252s
> user    0m45.924s
> sys     0m0.326s
> 
> ****
> 
> I couldn't make head or tail out of the timeit() function's return
> value, so I just used 'time' from the command line to see what really
> happened.
> 
Neither could I, so I rewrote your test program somewhat (and decreased the loop by a 
factor 10, to be practical):
#!/usr/bin/perl

use Benchmark;

my $loops = 10000000;
NORMAL:{
my $left = 10;
my $right = 3;
my $res = $left / $right;
print "\'NORMAL\' result : $res\n";
my $t0 = Benchmark->new;
for (my $i=0; $i<$loops; $i++) {
   my $res = $left / $right;
}
my $t1 = Benchmark->new;
my $td = timediff($t1, $t0);
print "\'NORMAL\' times :",timestr($td),"\n";
}

INTEGER:{
use integer;
my $left = 10;
my $right = 3;
my $res = $left / $right;
print "\'INTEGER\' result : $res\n";
my $t0 = Benchmark->new;
for (my $i=0; $i<$loops; $i++) {
   my $res = $left / $right;
}
my $t1 = Benchmark->new;
my $td = timediff($t1, $t0);
print "\'INTEGER\' times :",timestr($td),"\n";
}

FLOAT:{
# Note: not really different from the above NORMAL
my $left = 10.0;
my $right = 3.0;
my $res = $left / $right;
print "\'FLOAT\' result : $res\n";
my $t0 = Benchmark->new;
for (my $i=0; $i<$loops; $i++) {
   my $res = $left / $right;
}
my $t1 = Benchmark->new;
my $td = timediff($t1, $t0);
print "\'FLOAT\' times :",timestr($td),"\n";
}

BIGFLOAT:{
use Math::BigFloat;
my $left = Math::BigFloat->new(10.0);
my $right = Math::BigFloat->new(3.0);
my $res = $left / $right;
print "\'BIGFLOAT\' result : $res\n";
my $t0 = Benchmark->new;
for (my $i=0; $i<$loops; $i++) {
   my $res = $left / $right;
}
my $t1 = Benchmark->new;
my $td = timediff($t1, $t0);
print "\'BIGFLOAT\' times :",timestr($td),"\n";
}

BIGINT:{
use bigint;
my $left = 10;
my $right = 3;
my $res = $left / $right;
print "\'BIGINT\' result : $res\n";
my $t0 = Benchmark->new;
for (my $i=0; $i<$loops; $i++) {
   my $res = $left / $right;
}
my $t1 = Benchmark->new;
my $td = timediff($t1, $t0);
print "\'BIGINT\' times :",timestr($td),"\n";
}

exit 0;


Note that for the BIGFLOAT and BIGINT sections, you need to be *really* patient.
I interrupted at after maybe 10 minutes..

Funny thing is, the INTEGER section seems actually slower than the standard one.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Peter Crowther <pe...@melandra.com>.
On 19 January 2011 16:30, Christopher Schultz
<ch...@christopherschultz.net> wrote:
> [Peter]
>> I'm actually interested to know your environment for your
>> precision.c code, as a single-precision (32-bit) float is only good for 6-7
>> significant figures and your answers agree to 11sf.

... and I'm cross-eyed and can't count digits.  You're right, Chris.

- Peter

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Peter,

On 1/19/2011 6:09 AM, Peter Crowther wrote:
> On 19 January 2011 03:10, Christopher Schultz
> <ch...@christopherschultz.net>wrote:
> 
>> Yup: float is the default decimal type. Double-precision takes longer,
>> so you have to ask for it.
>
> Chris, that's the only comment in your post I'd take issue with. To
> my knowledge, a constant with a fractional part is assumed to be
> double unless stated otherwise.

I think I assumed that float was standard, ran the program, saw that the
answers were different, and concluded that I was right. I didn't really
check the numbers.

I actually have my copy of Harbison/Steele's C: "A Reference Manual" in
front of me for a technical review I'm doing of an Objective-C for iOS
book (see how this all ties together?).

Section 5.2 ("Floating-Point Types") has this to say:

"The use of float, double, and long double is analogous to the use of
short, int, and long. Prior to ISO C, all implementations were required
to convert all values of type float to type double before any operations
were performed (see section 6.3.4), so using type float was not
necessarily more efficient than using type double. In ISO C, operations
*can now be performed using type float*" (emphasis mine).

Section 6.3.4 ("Usual binary conversions") has a table which shows what
type of conversion is done given a pair of operands and the environment.
For float and double, these are the rows:

Op A	Op B	ISO C	Traditional
double	any	double	double
float	any	float	double

So, it looks like ISO C changed the rules to actually make more sense
(to me, at least) in that "float" is the default floating-point
arithmetic strategy. (This makes sense to me because the compiler ought
to do the fastest thing possible by default, and the programmer should
have to specify double-precision if desired.)

> I'm actually interested to know your environment for your
> precision.c code, as a single-precision (32-bit) float is only good for 6-7
> significant figures and your answers agree to 11sf.  Is your compiler
> quietly using IEEE754 64-bit precision, even where you request float?

Not sure.

$ cc -v
Using built-in specs.
Target: i486-linux-gnu
Configured with: ../src/configure -v --with-pkgversion='Debian
4.3.2-1.1' --with-bugurl=file:///usr/share/doc/gcc-4.3/README.Bugs
- --enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr
- --enable-shared --with-system-zlib --libexecdir=/usr/lib
- --without-included-gettext --enable-threads=posix --enable-nls
- --with-gxx-include-dir=/usr/include/c++/4.3 --program-suffix=-4.3
- --enable-clocale=gnu --enable-libstdcxx-debug --enable-objc-gc
- --enable-mpfr --enable-targets=all --enable-cld
- --enable-checking=release --build=i486-linux-gnu --host=i486-linux-gnu
- --target=i486-linux-gnu
Thread model: posix
gcc version 4.3.2 (Debian 4.3.2-1.1)

$ uname -a
Linux dev.chadis.com 2.6.18-14-fza-686-bigmem #1 SMP Thu Jan 1 17:20:47
UTC 2009 i686 GNU/Linux


Fortunately, I'm not a theoretical physicist, so I'm not usually worried
about the difference between floating-point numbers at the e-10 level :)

- -chris

> I love Smalltalk as a prototyping language, for example; but I don't use it
> for the inner loops of genomics code that's optimised to squeeze every piece
> of speed of of a particular AMD processor in a cluster, and that takes the
> time to process some experimental results down from a year to a day.

Oddly enough, I remember back around 2002 when "bioinformatics" was
looking to be the Next Big Thing, lots of people were talking about how
Perl was going to take over the world because of how easy it was to do
certain operations (pattern matching, hashing, etc.) and our dev group
all laughed because, while we all love Perl (and Java), we knew that
failing to write those algorithms in a high-performance language was
going to literally set them back months or years in their research just
due to wasted CPU time. We even scoffed at the use of Java for such
things... but that was before JITs were really, really good.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk03EaUACgkQ9CaO5/Lv0PCvYQCfREBBEgnVyCtXJ9mjQuU8duqm
J54AniueuAXWK8NhbH5vs+x0kXJtfw1B
=4D5l
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Peter Crowther <pe...@melandra.com>.
On 19 January 2011 03:10, Christopher Schultz
<ch...@christopherschultz.net>wrote:

> Yup: float is the default decimal type. Double-precision takes longer,
> so you have to ask for it.
>

Chris, that's the only comment in your post I'd take issue with.  To my
knowledge, a constant with a fractional part is assumed to be double unless
stated otherwise.  I'm actually interested to know your environment for your
precision.c code, as a single-precision (32-bit) float is only good for 6-7
significant figures and your answers agree to 11sf.  Is your compiler
quietly using IEEE754 64-bit precision, even where you request float?

> I maintain what I said : a programming language which produces a wrong
> > result, without even a warning, for an expression as simple as
> > Long a = (1000 * 60 * 60 * 24 * 365)
> > should be consigned to iPods and stuff, not used for serious things like
> > Tomcat.
>

Andre,

On the contrary: I consider a language that allows one to disable at runtime
bounds checks, overflow checks and any other time overhead to be ideal for
code that gains advantage from being highly performant.  The smaller
Tomcat's overhead, the greater the processing power available for
applications.  In turn, this means fewer joules of heat generated per
request processed, less power and air conditioning load in the data centre,
and hence cheaper application deployments.  Given the number of Tomcat
deployments worldwide, I would expect almost any investment in improving
Tomcat's performance to pay off in terms of reduced total cost to humanity.

"Friendly" languages, on the other hand, are ideal for workstations, where a
few microseconds or milliseconds per iteration rarely matters, or for code
where the cost of execution is vastly outwighed by the cost of development.
I love Smalltalk as a prototyping language, for example; but I don't use it
for the inner loops of genomics code that's optimised to squeeze every piece
of speed of of a particular AMD processor in a cluster, and that takes the
time to process some experimental results down from a year to a day.

Horses for courses.

- Peter

Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

André,

(You always make me write so much code!)

On 1/18/2011 7:12 PM, André Warnier wrote:
> Christopher Schultz wrote:
>> There's nothing magical about the first operand: you can cast any of the
>> operands to trigger this promotion. 
> 
> Not quite true I think. See note below.

You're right: you have to do it before the first truncation.

> Well here you see the difference with Java.
> Java seems to overflow without even a warning.

Note that it's the Java compiler not the runtime that fails to deliver
an error. The compiled C code happily overflows without any warning. Had
I written the code using an array to store the operands and used an int
to store the temporary result, you'd see the same truncation behavior
with no compiler warnings. The fact that constants are being used are
allowing the compiler to complain in this case.

Revised code:

$ cat longtime.c
#include <stdio.h>

int main(int argc, char *argv[]) {
  int cacheTime1 = (1000 * 60 * 60 * 24 * 100 * 3);
  long cacheTime2 = ((long)1000 * 60 * 60 * 24 * 100 * 3);
  long long cacheTime3 = ((long long)1000 * 60 * 60 * 24 * 100 * 3);
  long long cacheTime4 = (1000 * 60 * 60 * 24 * 100 * (long long)3);

  printf("%d\n%ld\n%lld\n%lld\n", cacheTime1, cacheTime2, cacheTime3,
cacheTime4);

  return 0;
}
cschultz@dev:~/projects/toys$ cc -ansi -pedantic -Wall -o longtime \
    longtime.c && ./longtime
longtime.c: In function `main':
longtime.c:4: warning: integer overflow in expression
longtime.c:5: warning: integer overflow in expression
longtime.c:6: warning: ISO C90 does not support `long long'
longtime.c:6: warning: ISO C90 does not support `long long'
longtime.c:7: warning: ISO C90 does not support `long long'
longtime.c:7: warning: integer overflow in expression
longtime.c:7: warning: ISO C90 does not support `long long'
longtime.c:9: warning: ISO C90 does not support the `ll' printf length
modifier
longtime.c:9: warning: ISO C90 does not support the `ll' printf length
modifier
150196224
150196224
25920000000
150196224

So, the expression type escalation needs to happen before the first
overflow in order for things to work out well.

> Now the calculation overflows an int at the penultimate step (* 100),
> and setting the last term to be a long does not help, it's too late.

Not enough people use the word "penultimate": nice work.

> I think that what happens is :
> - the expression is evaluated from left to right, not in one single step
> - multiplying an int by a long (in whatever order), is done in long mode
> and generates a long

Correct on both counts.

>> Most languages' behavior are surprising to Perl programmers :)
> 
> See below.
> 
>>
>> Seriously, though, these are the tradeoffs of a strongly-typed language:
>> you have to be very precise about the way you want calculations to be
>> performed. The compiler assumes that if you wanted double-precision
>> integers, you'd ensure that the calculation is done using "long" and not
>> "int". Presumably, 64-bit operations are (or were) considered slower
>> than 32-bit operations and so require the coder to specify that 64-bit
>> operations are desired.
>>
> At the cost of truncating the result and obtaining an incorrect one
> surrepticiously and without a warning ?

Well, at some point (such as non-constant calculations) overflow checks
are either not possible (Java?) or not practical (C) at runtime. C and
similar languages are well-documented to silently ignore overflow (or
underflow for that matter) and it's up to the programmer to check for
this kind of thing. Overflow checking is something that takes time, and
the C language was designed to compile to minimal machine code. If the
programmer cares about overflow, the programmer needs to check for it.

Likewise, if a Java programmer wants to avoid overflow in all cases, he
or she only need to use BigInteger for everything. Of course,
performance totally sucks when using BigInteger, but hey, I don't think
you'll ever overflow that (unless your BigInteger has something like
2^16 digits in it).

> I would find : (long)(1000 * 60 * 60 * 24 * 365)
> more intuitive, if it forced the calculation to be done in Long mode
> (which I suspect it does not; it probably just "promotes" the truncated
> result to long before the assignment).

It does not: see the C code I posted. I would be surprised if Java acted
differently, though I'm unwilling to write the code myself just now to
test it.

>> No, the clarity is in the fact that the target identifier should be able
>> to store a double-precision value. It says nothing about calculations
>> that are assigned to it.
>>
>> If you saw this, would the result (0.0) confuse you?
>>
>> double d = 1 / 2;
> 
> It would not confuse me, because by now I am ready for anything.  But I
> would find this just as unintuitive and wrong, for exactly the same
> reason.  What kind of stupid compiler is this, which requires me to say
> double d = 1.0 / 2;
> to get a correct result ?

It's one that produces seriously fast code:

$ cat divisionSpeedTest.c
#include <stdio.h>
#include <sys/time.h>

#define ITERATIONS 100000000

int main(int argc, char *argv[]) {
  struct timeval start, end;

  int i;

  int integral;
  int ileft=1, iright=2;

  float decimal;
  float fleft = 1.0, fright=2.0;

  /* time empty loop */
  gettimeofday(&start, NULL); /* start clock */

  for(i=0; i<ITERATIONS; ++i)
    ;

  gettimeofday(&end, NULL); /* stop clock */

  long adjustment = (long)(end.tv_sec - start.tv_sec) * 1000
      + (((end.tv_usec - start.tv_usec) / 1000.0) + 0.5);

  printf("Look with no work took %ldms\n", adjustment);

  gettimeofday(&start, NULL); /* start clock */

  for(i=0; i<ITERATIONS; ++i)
    integral = ileft / iright;

  gettimeofday(&end, NULL); /* stop clock */

  long elapsed = (long)(end.tv_sec - start.tv_sec) * 1000
      + (((end.tv_usec - start.tv_usec) / 1000.0) + 0.5)
      - adjustment;

  printf("Integer divisions took %ldms\n", elapsed);

  gettimeofday(&start, NULL); /* start clock */

  for(i=0; i<ITERATIONS; ++i)
    decimal = fleft / fright;

  gettimeofday(&end, NULL); /* stop clock */

  elapsed = (long)(end.tv_sec - start.tv_sec) * 1000
      + (((end.tv_usec - start.tv_usec) / 1000.0) + 0.5)
      - adjustment;

  printf("Float divisions took %ldms\n", elapsed);

  return 0;
}
$ cc -ansi -pedantic -Wall -o divisionSpeedTest divisionSpeedTest.c &&
time ./divisionSpeedTest
divisionSpeedTest.c: In function `main':
divisionSpeedTest.c:25: warning: ISO C90 forbids mixed declarations and code
divisionSpeedTest.c:37: warning: ISO C90 forbids mixed declarations and code
Look with no work took 188ms
Integer divisions took 1081ms
Float divisions took 1163ms

real    0m2.810s
user    0m2.803s
sys     0m0.005s

$ cat divisionSpeedTest.pl
#!/usr/bin/perl

use Benchmark;
my($left, $right);

$left = 1;
$right = 2;

# Not even bothering to store the result
print timestr(timeit(100000000, "$left / $right"));

$ time ./divisionSpeedTest.pl

 2 wallclock secs ( 1.50 usr +  0.06 sys =  1.56 CPU) @ 64102564.10/s
(n=100000000)
real    0m46.252s
user    0m45.924s
sys     0m0.326s

****

I couldn't make head or tail out of the timeit() function's return
value, so I just used 'time' from the command line to see what really
happened.

So, the C code is roughly 20 times as fast. Ask any mathematician or
physicist who is running simulations which they would rather have. In C,
you can test for overflow if you want to. Can you disable this checking?
Can you disable runtime type determination? I'm guessing not. The price
C programmers pay is verbosity and the occasional surprising roundoff.

> And even then, if the expression was
> double d = 1.0 / 3;
> I would probably *still* not get a result with the precision afforded by
> the double d, and would have to write
> double d = 1.0D / 3;
> to get it right, right ?

Yup: float is the default decimal type. Double-precision takes longer,
so you have to ask for it.

$ cat precision.c
#include <stdio.h>

int main(int argc, char *argv[]) {
  float f = 1.0 / 7;
  float ff = (1.0f / 7.0f);
  double d = 1.0 / 7;
  double dd = 1.0 / 7;

  printf("%1.10e\n%1.10e\n%1.10e\n%1.10e\n", f, ff, d, dd);

  return 0;
}
cschultz@dev:~/projects/toys$ cc -ansi -pedantic -Wall -o precision
precision.c && ./precision
1.4285714924e-01
1.4285714924e-01
1.4285714286e-01
1.4285714286e-01

> I maintain what I said : a programming language which produces a wrong
> result, without even a warning, for an expression as simple as
> Long a = (1000 * 60 * 60 * 24 * 365)
> should be consigned to iPods and stuff, not used for serious things like
> Tomcat.

There are people using iPads for healthcare. One would expect that
precision counts, there, too. ;)

> Incidentally, and since you mentioned it :
> 
> C:\WINDOWS>perl
> print (1000 * 60 * 60 * 24 * 365);
> ^Z
> 31536000000

Of course! It just takes a few million more cycles to do it.

> That's what I call a smart and intuitive language..

Just not for the impatient.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk02VjcACgkQ9CaO5/Lv0PDCOQCglqCp8wMh/69GrDErUL2loORl
H04An1lW8Pjq3xJnthVsDfQnuSAPyHmP
=2m1U
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by André Warnier <aw...@ice-sa.com>.
Peter Crowther wrote:
> On 19 January 2011 08:34, André Warnier <aw...@ice-sa.com> wrote:
> 
>> Well, they haven't made a language yet which can divide acres by feet and
>> coerce the result into furlongs.
>>
> 
> Google "20 acres / 22 feet in furlongs" and prepare for a surprise ;-).
> 
I /am/ impressed.

On the other hand, it means that the last pocket of resistance against the rational metric 
system is not about to disappear.  The dark side of technology..


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Peter Crowther <pe...@melandra.com>.
On 19 January 2011 08:34, André Warnier <aw...@ice-sa.com> wrote:

> Well, they haven't made a language yet which can divide acres by feet and
> coerce the result into furlongs.
>

Google "20 acres / 22 feet in furlongs" and prepare for a surprise ;-).

- Peter

Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by André Warnier <aw...@ice-sa.com>.
Caldarale, Charles R wrote:
> 
>> (No wonder after that, that lunar probes go CFIT.)
> 
> Nah, it's that damn metric system (think Gimli Glider).
> 
Well, they haven't made a language yet which can divide acres by feet and coerce the 
result into furlongs.

And thanks for the Gimli Glider story, I did not know that one.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Chuck,

On 1/18/2011 9:47 PM, Caldarale, Charles R wrote:
> However, I suspect that Objective-C still follows the C standards for expressions.

Objective-C /must/ follow the C standards: it is a strict superset of C.
Early Objective-C compilers were just huge libraries of preprocessor
macros built on top of a standard C compiler.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk03C/wACgkQ9CaO5/Lv0PAAPwCgkilLEpZpx9miqGWvO7uBmdtr
OwMAn0iIZfDI/kKsmQc4z2lcF51/vALc
=63Zc
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: André Warnier [mailto:aw@ice-sa.com] 
> Subject: Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

> What kind of stupid compiler is this, which requires me to say
> double d = 1.0 / 2;
> to get a correct result ?

One that abides by the C (or Java) standards.

> And even then, if the expression was
> double d = 1.0 / 3;
> I would probably *still* not get a result with the precision 
> afforded by the double d, and would have to write
> double d = 1.0D / 3;
> to get it right, right ?

Nope - the standards require that otherwise unannotated floating point operations must be done in double precision.  (What, you want consistency?)

> I maintain what I said : a programming language which produces a 
> wrong result, without even a warning, for an expression as simple as
> Long a = (1000 * 60 * 60 * 24 * 365)
> should be consigned to iPods and stuff, not used for serious things
> like Tomcat.

Careful, there's a lot more mathematically-sensitive code in an iPod, iPhone, or iPad than in Tomcat.  (Think about video and audio decoding.)  However, I suspect that Objective-C still follows the C standards for expressions.

> (No wonder after that, that lunar probes go CFIT.)

Nah, it's that damn metric system (think Gimli Glider).

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by André Warnier <aw...@ice-sa.com>.
Christopher Schultz wrote:
> -----BEGIN PGP SIGNED MESSAGE-----
> Hash: SHA1
> 
> André,
> 
> On 1/16/2011 8:41 AM, André Warnier wrote:
>> Ran Berenfeld wrote:
>>> well ...no... first evaluate, then assign. and constants are int by
>>> default.
>>> I think C/C++ would have the same problem...
>>>
>> Maybe.
> 
> FYI they do.
> 
>> But then why does the fact of specifying just the first
>> right-hand side constant in the calculation as a long, magically change
>> the whole result into a long ?
>> (1000 * 60 * 60 * 24 * 365)  --> int
>> (1000L * 60 * 60 * 24 * 365) --> long
> 
> Because it promotes the type of the entire expression to "long" and the
> laws change for the expression. The assignment works as usual.
> 
> There's nothing magical about the first operand: you can cast any of the
> operands to trigger this promotion. 

Not quite true I think. See note below.

Here's some C code that demonstrates
> it (note that Java's long is 64-bit so we need "long long" which has
> spotty ANSI support):
> 
> $ cat longtime.c
> #include <stdio.h>
> 
> int main(int argc, char *argv[]) {
>   int cacheTime1 = (1000 * 60 * 60 * 24 * 365);
>   long cacheTime2 = ((long)1000 * 60 * 60 * 24 * 365);
>   long long cacheTime3 = ((long long)1000 * 60 * 60 * 24 * 365);
>   long long cacheTime4 = (1000 * 60 * 60 * 24 * (long long)365);
> 
>   printf("%d\n%ld\n%lld\n%lld\n", cacheTime1, cacheTime2, cacheTime3,
> cacheTime4);
> 
>   return 0;
> }
> cschultz@dev:~/projects/toys$ cc -ansi -pedantic -Wall -o longtime \
>    longtime.c && ./longtime
> longtime.c: In function `main':
> longtime.c:4: warning: integer overflow in expression
> longtime.c:5: warning: integer overflow in expression

Well here you see the difference with Java.
Java seems to overflow without even a warning.
(Chuck tried to get a warning at compile time, without success.)

One additional remark about the calculations you show above (which also applies to Java) :
In (1000 * 60 * 60 * 24 * 365), the overflow occurs at the last step, when multiplying by 365.
So in this particular case you are right, the fact of setting *any* factor of the 
multiplication to be a long "saves the day", because subsequent operations will be done in 
"long mode", and it is enough to make the last term a long, to avoid the problem.
However, suppose for the sake of argument that a year would have 300 days, and that 
instead the OP had expressed his duration like this :
(1000 * 60 * 60 * 24 * 100 * 3L)
Now the calculation overflows an int at the penultimate step (* 100), and setting the last 
term to be a long does not help, it's too late.
I think that what happens is :
- the expression is evaluated from left to right, not in one single step
- multiplying an int by a long (in whatever order), is done in long mode and generates a long
- so, in the original calculation
     1000 * 60 is done in int-mode, and generates an int R1
       R1 * 60 is done in int-mode, and generates an int R2
       R2 * 24 is done in int-mode, and generates an int R3
       R3 * 365 is done in int-mode, overflows, but still generates an int
- while
     1000 * 60 is done in int-mode, and generates an int R1
       R1 * 60 is done in int-mode, and generates an int R2
       R2 * 24 is done in int-mode, and generates an int R3
       R3 * 365L is done in long-mode, does not overflow, and generates a correct long

- but with the revised calculation (1000 * 60 * 60 * 24 * 100 * 3.65L):
     1000 * 60 is done in int-mode, and generates an int R1
       R1 * 60 is done in int-mode, and generates an int R2
       R2 * 24 is done in int-mode, and generates an int R3
       R3 * 100 is done in int-mode, generating an int R4 which is already truncated
       R4 * 3L would generate a long, but with the error magnified

...
> 
> Most languages' behavior are surprising to Perl programmers :)

See below.

> 
> Seriously, though, these are the tradeoffs of a strongly-typed language:
> you have to be very precise about the way you want calculations to be
> performed. The compiler assumes that if you wanted double-precision
> integers, you'd ensure that the calculation is done using "long" and not
> "int". Presumably, 64-bit operations are (or were) considered slower
> than 32-bit operations and so require the coder to specify that 64-bit
> operations are desired.
> 
At the cost of truncating the result and obtaining an incorrect one surrepticiously and 
without a warning ?

I would find : (long)(1000 * 60 * 60 * 24 * 365)
more intuitive, if it forced the calculation to be done in Long mode (which I suspect it 
does not; it probably just "promotes" the truncated result to long before the assignment).

...

> 
> No, the clarity is in the fact that the target identifier should be able
> to store a double-precision value. It says nothing about calculations
> that are assigned to it.
> 
> If you saw this, would the result (0.0) confuse you?
> 
> double d = 1 / 2;

It would not confuse me, because by now I am ready for anything.  But I would find this 
just as unintuitive and wrong, for exactly the same reason.  What kind of stupid compiler 
is this, which requires me to say
double d = 1.0 / 2;
to get a correct result ?
And even then, if the expression was
double d = 1.0 / 3;
I would probably *still* not get a result with the precision afforded by the double d, and 
would have to write
double d = 1.0D / 3;
to get it right, right ?

I maintain what I said : a programming language which produces a wrong result, without 
even a warning, for an expression as simple as
Long a = (1000 * 60 * 60 * 24 * 365)
should be consigned to iPods and stuff, not used for serious things like Tomcat.
(No wonder after that, that lunar probes go CFIT.)

Incidentally, and since you mentioned it :

C:\WINDOWS>perl
print (1000 * 60 * 60 * 24 * 365);
^Z
31536000000

and even :

C:\WINDOWS>perl
print ("1000" * 60 * 60 * 24 * 365);
^Z
31536000000

and also
C:\WINDOWS>perl
print ("1000.0" * 60 * 60 * 24 * 365);
^Z
31536000000

That's what I call a smart and intuitive language..
:-)

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Christopher Schultz <ch...@christopherschultz.net>.
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

André,

On 1/16/2011 8:41 AM, André Warnier wrote:
> Ran Berenfeld wrote:
>> well ...no... first evaluate, then assign. and constants are int by
>> default.
>> I think C/C++ would have the same problem...
>>
> Maybe.

FYI they do.

> But then why does the fact of specifying just the first
> right-hand side constant in the calculation as a long, magically change
> the whole result into a long ?
> (1000 * 60 * 60 * 24 * 365)  --> int
> (1000L * 60 * 60 * 24 * 365) --> long

Because it promotes the type of the entire expression to "long" and the
laws change for the expression. The assignment works as usual.

There's nothing magical about the first operand: you can cast any of the
operands to trigger this promotion. Here's some C code that demonstrates
it (note that Java's long is 64-bit so we need "long long" which has
spotty ANSI support):

$ cat longtime.c
#include <stdio.h>

int main(int argc, char *argv[]) {
  int cacheTime1 = (1000 * 60 * 60 * 24 * 365);
  long cacheTime2 = ((long)1000 * 60 * 60 * 24 * 365);
  long long cacheTime3 = ((long long)1000 * 60 * 60 * 24 * 365);
  long long cacheTime4 = (1000 * 60 * 60 * 24 * (long long)365);

  printf("%d\n%ld\n%lld\n%lld\n", cacheTime1, cacheTime2, cacheTime3,
cacheTime4);

  return 0;
}
cschultz@dev:~/projects/toys$ cc -ansi -pedantic -Wall -o longtime \
   longtime.c && ./longtime
longtime.c: In function `main':
longtime.c:4: warning: integer overflow in expression
longtime.c:5: warning: integer overflow in expression
longtime.c:6: warning: ISO C90 does not support `long long'
longtime.c:6: warning: ISO C90 does not support `long long'
longtime.c:7: warning: ISO C90 does not support `long long'
longtime.c:7: warning: ISO C90 does not support `long long'
longtime.c:9: warning: ISO C90 does not support the `ll' printf length
modifier
longtime.c:9: warning: ISO C90 does not support the `ll' printf length
modifier
1471228928
1471228928
31536000000
31536000000

> But I find this unintuitive.

Most languages' behavior are surprising to Perl programmers :)

Seriously, though, these are the tradeoffs of a strongly-typed language:
you have to be very precise about the way you want calculations to be
performed. The compiler assumes that if you wanted double-precision
integers, you'd ensure that the calculation is done using "long" and not
"int". Presumably, 64-bit operations are (or were) considered slower
than 32-bit operations and so require the coder to specify that 64-bit
operations are desired.

> Specially since it appears that in your first formula, the result is
> overflowing at some point in the calculation, without even a warning (?).

Yes, that's unfortunate: as you can see, the C compiler warns you. But
gcc is quite a bit older and wiser than javac :)

> If someone writes
> Long a = something
> then someone clearly expresses the desire to obtain a Long result.

No, the clarity is in the fact that the target identifier should be able
to store a double-precision value. It says nothing about calculations
that are assigned to it.

If you saw this, would the result (0.0) confuse you?

double d = 1 / 2;

> I suppose that there must be some implacable logic in the way it's done
> now, other than the evil intention to fool the unsuspecting programmer,
> but I honestly fail to see it.

Performance, baby. Java follows C rules, and C was all about performance.

- -chris
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (MingW32)
Comment: Using GnuPG with Mozilla - http://enigmail.mozdev.org/

iEYEARECAAYFAk015g4ACgkQ9CaO5/Lv0PChCwCeMF2Sx0s/Xl6v84FPr96FWwDk
lI0AoImU6lKtFA/D8NUHlzTX8BoblVwM
=A8sz
-----END PGP SIGNATURE-----

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


RE: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by "Caldarale, Charles R" <Ch...@unisys.com>.
> From: Len Popp [mailto:len.popp@gmail.com] 
> Subject: Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

> > I suppose that there must be some implacable logic in the way it's done now,
> > other than the evil intention to fool the unsuspecting programmer, but I
> > honestly fail to see it.

> There certainly are logical rules behind it. If you want the "why", I
> guess you'd have to ask Jim Gosling.

You'd have to go back much farther than that - those are the rules in pretty much every algebraically-oriented language - predating even C, which Java tries to be compatible with at the expression level.  (FORTRAN, anyone?)

 - Chuck


THIS COMMUNICATION MAY CONTAIN CONFIDENTIAL AND/OR OTHERWISE PROPRIETARY MATERIAL and is thus for use only by the intended recipient. If you received this in error, please contact the sender and delete the e-mail and its attachments from all computers.


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by Len Popp <le...@gmail.com>.
On Sun, Jan 16, 2011 at 08:41, André Warnier <aw...@ice-sa.com> wrote:
> Ran Berenfeld wrote:
>>
>> well ...no... first evaluate, then assign. and constants are int by
>> default.
>> I think C/C++ would have the same problem...
>>
> Maybe.  But then why does the fact of specifying just the first right-hand
> side constant in the calculation as a long, magically change the whole
> result into a long ?

It's not magic. For each * operation, if one operand is int and one is
long, the compiler does a 64-bit multiply and produces a long result.
Now, consider each "*" in that expression (in order of evaluation) and
ask, What type is each operand?

Some people would explicitly write "(1000L * 60L * 60L * 24L * 365L)"
to avoid this sort of head-scratching.

> (1000 * 60 * 60 * 24 * 365)  --> int
> (1000L * 60 * 60 * 24 * 365) --> long
>
> Note: my intention is not to start a rant or a flame on the way Java does
> things.
> I suppose that the Java syntax rules describe this accurately.
> But I find this unintuitive.
> Specially since it appears that in your first formula, the result is
> overflowing at some point in the calculation, without even a warning (?).

Yep, there's no overflow checking for arithmetic on primitive types.
For the sake of efficiency, I presume.

>
> If someone writes
> Long a = something
> then someone clearly expresses the desire to obtain a Long result.
> And if for some obscure reason that was really not the case, one could
> always write
> Long a = (int) something
>
> I suppose that there must be some implacable logic in the way it's done now,
> other than the evil intention to fool the unsuspecting programmer, but I
> honestly fail to see it.

There certainly are logical rules behind it. If you want the "why", I
guess you'd have to ask Jim Gosling.
--
Len

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: [OT] Setting HTTP response headers caching for 1 year doesn't work

Posted by André Warnier <aw...@ice-sa.com>.
Ran Berenfeld wrote:
> well ...no... first evaluate, then assign. and constants are int by default.
> I think C/C++ would have the same problem...
> 
Maybe.  But then why does the fact of specifying just the first right-hand side constant 
in the calculation as a long, magically change the whole result into a long ?
(1000 * 60 * 60 * 24 * 365)  --> int
(1000L * 60 * 60 * 24 * 365) --> long

Note: my intention is not to start a rant or a flame on the way Java does things.
I suppose that the Java syntax rules describe this accurately.
But I find this unintuitive.
Specially since it appears that in your first formula, the result is overflowing at some 
point in the calculation, without even a warning (?).

If someone writes
Long a = something
then someone clearly expresses the desire to obtain a Long result.
And if for some obscure reason that was really not the case, one could always write
Long a = (int) something

I suppose that there must be some implacable logic in the way it's done now, other than 
the evil intention to fool the unsuspecting programmer, but I honestly fail to see it.


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Setting HTTP response headers caching for 1 year doesn't work

Posted by Ran Berenfeld <ic...@ichess.co.il>.
well ...no... first evaluate, then assign. and constants are int by default.
I think C/C++ would have the same problem...

On Sun, Jan 16, 2011 at 1:25 PM, André Warnier <aw...@ice-sa.com> wrote:

> Ran Berenfeld wrote:
>
>> thanks :) silly me. problem solved....
>>
>
> It's more silly Java.  It could figure out that the left side wants a long,
> couldn't it ?
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>


-- 
רן ברנפלד
מנהל
אתר השחמט הישראלי
*http://www.ichess.co.il*

Re: Setting HTTP response headers caching for 1 year doesn't work

Posted by André Warnier <aw...@ice-sa.com>.
Ran Berenfeld wrote:
> thanks :) silly me. problem solved....

It's more silly Java.  It could figure out that the left side wants a long, couldn't it ?

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org


Re: Setting HTTP response headers caching for 1 year doesn't work

Posted by Ran Berenfeld <ic...@ichess.co.il>.
thanks :) silly me. problem solved....

On Sun, Jan 16, 2011 at 12:21 PM, Konstantin Kolinko <knst.kolinko@gmail.com
> wrote:

> 2011/1/16 Ran Berenfeld <ic...@ichess.co.il>:
> >    // cache for 1 year
> >    private static final long _cacheTime = (1000 * 60 * 60 * 24 * 365);
>
> With this sample program:
> public class foo{
> public static void main(String[] a){
> long _cacheTime = (1000 * 60 * 60 * 24 * 365);
> System.out.println("_cacheTime: " + _cacheTime);
> long _cacheTime2 = (1000L * 60 * 60 * 24 * 365);
> System.out.println("_cacheTime: " + _cacheTime2);
> }
> }
>
> It prints:
> _cacheTime: 1471228928
> _cacheTime: 31536000000
>
> 1471228928 msecs = about 17 days
>
> Best regards,
> Konstantin Kolinko
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: users-help@tomcat.apache.org
>
>


-- 
רן ברנפלד
מנהל
אתר השחמט הישראלי
*http://www.ichess.co.il*

Re: Setting HTTP response headers caching for 1 year doesn't work

Posted by Konstantin Kolinko <kn...@gmail.com>.
2011/1/16 Ran Berenfeld <ic...@ichess.co.il>:
>    // cache for 1 year
>    private static final long _cacheTime = (1000 * 60 * 60 * 24 * 365);

With this sample program:
public class foo{
public static void main(String[] a){
long _cacheTime = (1000 * 60 * 60 * 24 * 365);
System.out.println("_cacheTime: " + _cacheTime);
long _cacheTime2 = (1000L * 60 * 60 * 24 * 365);
System.out.println("_cacheTime: " + _cacheTime2);
}
}

It prints:
_cacheTime: 1471228928
_cacheTime: 31536000000

1471228928 msecs = about 17 days

Best regards,
Konstantin Kolinko

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@tomcat.apache.org
For additional commands, e-mail: users-help@tomcat.apache.org