PHP & 64-bit Integer Modulus (Almost)
Wednesday, October 28th, 2009While at times PHP seems to be capable of 64 bit math, it’s important to understand what’s really going on. Beyond 32 bit integers, PHP is silently converting your integers to floats. While this usually isn’t a problem, many of the operations you might perform on an int, such as modulus choke when attempting to convert back to a 32 bit integer internally.
This is actually the cause of the sprintf / printf issue I encountered before. The code below provides the maximum signed value for integers between 1 and 64 bit in PHP along with the result of the built in modulus operand “%” and a function I wrote mod() which doesn’t go all the way to 64 bits, but gets us a lot closer leveraging the built in data types. If you can install external modules, you might review and test the performance of BCMath or GMP which can both handle much larger values.
<?php // Find out what our internal values are capable of print "PHP_INT_MAX: " . PHP_INT_MAX . "\n"; print "PHP_INT_SIZE: " . PHP_INT_SIZE . " bytes (" . (PHP_INT_SIZE * 8) . " bits)\n"; // Generate an array of maximum signed 32 bit values $ints = array(); for($pwr = 0; $pwr < 64; $pwr++){ $ints[] = pow(2,$pwr) - 1; } // Generate a table of values print "bits\t%100\tmod()\t%s\n"; $bits = 0; foreach($ints as $int){ $bits++; printf("%d\t%s\t%s\t%s\n", $bits, $int%100, mod($int,100), $int); } // (60 bit) - 1 aware modulus function function mod($val, $mod){ return $val - floor($val/$mod) * $mod; } ?> |
This generates the following table. Notice the internal value for integers is capped at 2,147,483,647 and the modulus operation goes kaput beyond 32 bits. The function provided seems to holds up through 59 bits before failing to function properly at 60.
PHP_INT_MAX: 2147483647 PHP_INT_SIZE: 4 bytes (32 bits) bits %100 mod() %s 1 0 0 0 2 1 1 1 3 3 3 3 4 7 7 7 5 15 15 15 6 31 31 31 7 63 63 63 8 27 27 127 9 55 55 255 10 11 11 511 11 23 23 1023 12 47 47 2047 13 95 95 4095 14 91 91 8191 15 83 83 16383 16 67 67 32767 17 35 35 65535 18 71 71 131071 19 43 43 262143 20 87 87 524287 21 75 75 1048575 22 51 51 2097151 23 3 3 4194303 24 7 7 8388607 25 15 15 16777215 26 31 31 33554431 27 63 63 67108863 28 27 27 134217727 29 55 55 268435455 30 11 11 536870911 31 23 23 1073741823 32 47 47 2147483647 33 -1 95 4294967295 34 -1 91 8589934591 35 -1 83 17179869183 36 -1 67 34359738367 37 -1 35 68719476735 38 -1 71 137438953471 39 -1 43 274877906943 40 -1 87 549755813887 41 -1 75 1099511627775 42 -1 51 2199023255551 43 -1 3 4398046511103 44 -1 7 8796093022207 45 -1 15 17592186044415 46 -1 31 35184372088831 47 -1 63 70368744177663 48 -1 27 1.4073748835533E+14 49 -1 55 2.8147497671066E+14 50 -1 11 5.6294995342131E+14 51 -1 23 1.1258999068426E+15 52 -1 47 2.2517998136852E+15 53 -1 95 4.5035996273705E+15 54 -1 91 9.007199254741E+15 55 0 84 1.8014398509482E+16 56 0 68 3.6028797018964E+16 57 0 32 7.2057594037928E+16 58 0 64 1.4411518807586E+17 59 0 32 2.8823037615171E+17 60 0 0 5.7646075230342E+17 61 0 0 1.1529215046068E+18 62 0 0 2.3058430092137E+18 63 0 0 4.6116860184274E+18 64 0 0 9.2233720368548E+18 |
The stable of services available through AWS is continuing to expand! Last night Amazon announced RDS (Relational Database Service) which look a lot like EC2 instances running MySQL with EBS volumes – something I have a fair bit of experience with. However, these have the added benefit of being a service that can scale memory and processor both up and down with a single service call.
Problem: We are given a large MySQL database table that no longer fits in your system’s working memory. You need to prune the data since a significant portion of this data is no longer relevant to keep in this table. Our expectation is ~75% of the data will remain in the table because of a uniform and random distribution of values in col1 and col2. How then, do we go about pruning this table as efficiently as possible?
Generally, if you need to have the browser see a page while you continue executing the request I would use a queue system like
Storing application data on the OpenSocial host is a great way to offload some unnecessary database and application server load. Why request a preference such as a skin for a user profile from your servers if we can just let the container handle it? MySpace allows for ~1K of data storage per user per application. However, there is a bug with the method