Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Smaller serialisation of messages. #167

Merged
merged 1 commit into from

3 participants

@williambailey

Serialising messages results in a large serialised string with lots of duplicated data.

This is an initial attempt to reduce some of that information which should reduce spooler disk usage. I tried to to change too much and most of the changes involve moving shared data into class constants or static variables that get initialised once and ignored when the objects get serialised and unserialised.

@williambailey williambailey Reduce amount of information serialised.
Serialising messages results in a late serialised string. This is an
initial attempt to reduce some of that information.
d550dfc
@damianb

considering this, it'd also likely reduce the memory usage OF swiftmailer too

@williambailey

Sorry that should have said "I tried to NOT change too much" :)

@fabpot fabpot referenced this pull request from a commit
@fabpot fabpot merged branch williambailey/master (PR #167)
Commits
-------

d550dfc Reduce amount of information serialised.

Discussion
----------

Smaller serialisation of messages.

Serialising messages results in a large serialised string with lots of duplicated data.

This is an initial attempt to reduce some of that information which should reduce spooler disk usage. I tried to to change too much and most of the changes involve moving shared data into class constants or static variables that get initialised once and ignored when the objects get serialised and unserialised.

---------------------------------------------------------------------------

by damianb at 2012-02-28T04:02:03Z

considering this, it'd also likely reduce the memory usage OF swiftmailer too

---------------------------------------------------------------------------

by williambailey at 2012-02-28T07:44:24Z

Sorry that should have said "I tried to NOT change too much" :)
ab21859
@fabpot fabpot merged commit d550dfc into swiftmailer:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Feb 27, 2012
  1. @williambailey

    Reduce amount of information serialised.

    williambailey authored
    Serialising messages results in a late serialised string. This is an
    initial attempt to reduce some of that information.
This page is out of date. Refresh to see the latest.
View
57 lib/classes/Swift/CharacterReaderFactory/SimpleCharacterReaderFactory.php
@@ -24,20 +24,35 @@ class Swift_CharacterReaderFactory_SimpleCharacterReaderFactory
* @var array
* @access private
*/
- private $_map = array();
+ private static $_map = array();
/**
* Factories which have already been loaded.
* @var Swift_CharacterReaderFactory[]
* @access private
*/
- private $_loaded = array();
+ private static $_loaded = array();
/**
* Creates a new CharacterReaderFactory.
*/
public function __construct()
{
+ $this->init();
+ }
+
+ public function __wakeup()
+ {
+ $this->init();
+ }
+
+ public function init()
+ {
+ if(count(self::$_map) > 0)
+ {
+ return;
+ }
+
$prefix = 'Swift_CharacterReader_';
$singleByte = array(
@@ -56,32 +71,32 @@ public function __construct()
);
//Utf-8
- $this->_map['utf-?8'] = array(
+ self::$_map['utf-?8'] = array(
'class' => $prefix . 'Utf8Reader',
'constructor' => array()
);
//7-8 bit charsets
- $this->_map['(us-)?ascii'] = $singleByte;
- $this->_map['(iso|iec)-?8859-?[0-9]+'] = $singleByte;
- $this->_map['windows-?125[0-9]'] = $singleByte;
- $this->_map['cp-?[0-9]+'] = $singleByte;
- $this->_map['ansi'] = $singleByte;
- $this->_map['macintosh'] = $singleByte;
- $this->_map['koi-?7'] = $singleByte;
- $this->_map['koi-?8-?.+'] = $singleByte;
- $this->_map['mik'] = $singleByte;
- $this->_map['(cork|t1)'] = $singleByte;
- $this->_map['v?iscii'] = $singleByte;
+ self::$_map['(us-)?ascii'] = $singleByte;
+ self::$_map['(iso|iec)-?8859-?[0-9]+'] = $singleByte;
+ self::$_map['windows-?125[0-9]'] = $singleByte;
+ self::$_map['cp-?[0-9]+'] = $singleByte;
+ self::$_map['ansi'] = $singleByte;
+ self::$_map['macintosh'] = $singleByte;
+ self::$_map['koi-?7'] = $singleByte;
+ self::$_map['koi-?8-?.+'] = $singleByte;
+ self::$_map['mik'] = $singleByte;
+ self::$_map['(cork|t1)'] = $singleByte;
+ self::$_map['v?iscii'] = $singleByte;
//16 bits
- $this->_map['(ucs-?2|utf-?16)'] = $doubleByte;
+ self::$_map['(ucs-?2|utf-?16)'] = $doubleByte;
//32 bits
- $this->_map['(ucs-?4|utf-?32)'] = $fourBytes;
+ self::$_map['(ucs-?4|utf-?32)'] = $fourBytes;
//Fallback
- $this->_map['.*'] = $singleByte;
+ self::$_map['.*'] = $singleByte;
}
/**
@@ -92,12 +107,12 @@ public function __construct()
public function getReaderFor($charset)
{
$charset = trim(strtolower($charset));
- foreach ($this->_map as $pattern => $spec)
+ foreach (self::$_map as $pattern => $spec)
{
$re = '/^' . $pattern . '$/D';
if (preg_match($re, $charset))
{
- if (!array_key_exists($pattern, $this->_loaded))
+ if (!array_key_exists($pattern, self::$_loaded))
{
$reflector = new ReflectionClass($spec['class']);
if ($reflector->getConstructor())
@@ -108,9 +123,9 @@ public function getReaderFor($charset)
{
$reader = $reflector->newInstance();
}
- $this->_loaded[$pattern] = $reader;
+ self::$_loaded[$pattern] = $reader;
}
- return $this->_loaded[$pattern];
+ return self::$_loaded[$pattern];
}
}
}
View
47 lib/classes/Swift/Encoder/QpEncoder.php
@@ -38,7 +38,7 @@ class Swift_Encoder_QpEncoder implements Swift_Encoder
* @var string[]
* @access protected
*/
- protected $_qpMap = array(
+ protected static $_qpMap = array(
0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04',
5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09',
10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E',
@@ -93,6 +93,9 @@ class Swift_Encoder_QpEncoder implements Swift_Encoder
255 => '=FF'
);
+ protected static $_safeMapShare = array();
+ protected $_safeMapShareId = __CLASS__;
+
/**
* A map of non-encoded ascii characters.
* @var string[]
@@ -109,12 +112,48 @@ public function __construct(Swift_CharacterStream $charStream,
Swift_StreamFilter $filter = null)
{
$this->_charStream = $charStream;
+ if(!isset(self::$_safeMapShare[$this->getSafeMapShareId()]))
+ {
+ $this->initSafeMap();
+ self::$_safeMapShare[$this->getSafeMapShareId()] = $this->_safeMap;
+ }
+ else
+ {
+ $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()];
+ }
+ $this->_filter = $filter;
+ }
+
+ public function __sleep()
+ {
+ return array('_charStream', '_filter');
+ }
+
+ public function __wakeup()
+ {
+ if(!isset(self::$_safeMapShare[$this->getSafeMapShareId()]))
+ {
+ $this->initSafeMap();
+ self::$_safeMapShare[$this->$_safeMapShareId] = $this->_safeMap;
+ }
+ else
+ {
+ $this->_safeMap = self::$_safeMapShare[$this->getSafeMapShareId()];
+ }
+ }
+
+ protected function getSafeMapShareId()
+ {
+ return get_class($this);
+ }
+
+ protected function initSafeMap()
+ {
foreach (array_merge(
array(0x09, 0x20), range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte)
{
$this->_safeMap[$byte] = chr($byte);
}
- $this->_filter = $filter;
}
/**
@@ -217,7 +256,7 @@ protected function _encodeByteSequence(array $bytes, &$size)
}
else
{
- $ret .= $this->_qpMap[$b];
+ $ret .= self::$_qpMap[$b];
$size+=3;
}
}
@@ -250,7 +289,7 @@ protected function _standardize($string)
{
case 0x09:
case 0x20:
- $string = substr_replace($string, $this->_qpMap[$end], -1);
+ $string = substr_replace($string, self::$_qpMap[$end], -1);
}
return $string;
}
View
22 lib/classes/Swift/Mime/ContentEncoder/QpContentEncoder.php
@@ -19,6 +19,8 @@ class Swift_Mime_ContentEncoder_QpContentEncoder extends Swift_Encoder_QpEncoder
implements Swift_Mime_ContentEncoder
{
+ protected $_dotEscape;
+
/**
* Creates a new QpContentEncoder for the given CharacterStream.
* @param Swift_CharacterStream $charStream to use for reading characters
@@ -28,11 +30,27 @@ class Swift_Mime_ContentEncoder_QpContentEncoder extends Swift_Encoder_QpEncoder
public function __construct(Swift_CharacterStream $charStream,
Swift_StreamFilter $filter = null, $dotEscape=false)
{
+ $this->_dotEscape = $dotEscape;
parent::__construct($charStream, $filter);
- if ($dotEscape) {
+ }
+
+ public function __sleep()
+ {
+ return array('_charStream', '_filter', '_dotEscape');
+ }
+
+ protected function getSafeMapShareId()
+ {
+ return get_class($this).($this->_dotEscape ? '.dotEscape' : '');
+ }
+
+ protected function initSafeMap()
+ {
+ parent::initSafeMap();
+ if ($this->_dotEscape) {
/* Encode . as =2e for buggy remote servers */
unset($this->_safeMap[0x2e]);
- }
+ }
}
/**
View
133 lib/classes/Swift/Mime/Grammar.php
@@ -22,14 +22,14 @@ class Swift_Mime_Grammar
* @var string[]
* @access private
*/
- private $_specials = array();
+ private static $_specials = array();
/**
* Tokens defined in RFC 2822 (and some related RFCs).
* @var string[]
* @access private
*/
- private $_grammar = array();
+ private static $_grammar = array();
/**
* Initialize some RFC 2822 (and friends) ABNF grammar definitions.
@@ -37,7 +37,22 @@ class Swift_Mime_Grammar
*/
public function __construct()
{
- $this->_specials = array(
+ $this->init();
+ }
+
+ public function __wakeup()
+ {
+ $this->init();
+ }
+
+ protected function init()
+ {
+ if(count(self::$_specials) > 0)
+ {
+ return;
+ }
+
+ self::$_specials = array(
'(', ')', '<', '>', '[', ']',
':', ';', '@', ',', '.', '"'
);
@@ -45,65 +60,65 @@ public function __construct()
/*** Refer to RFC 2822 for ABNF grammar ***/
//All basic building blocks
- $this->_grammar['NO-WS-CTL'] = '[\x01-\x08\x0B\x0C\x0E-\x19\x7F]';
- $this->_grammar['WSP'] = '[ \t]';
- $this->_grammar['CRLF'] = '(?:\r\n)';
- $this->_grammar['FWS'] = '(?:(?:' . $this->_grammar['WSP'] . '*' .
- $this->_grammar['CRLF'] . ')?' . $this->_grammar['WSP'] . ')';
- $this->_grammar['text'] = '[\x00-\x08\x0B\x0C\x0E-\x7F]';
- $this->_grammar['quoted-pair'] = '(?:\\\\' . $this->_grammar['text'] . ')';
- $this->_grammar['ctext'] = '(?:' . $this->_grammar['NO-WS-CTL'] .
+ self::$_grammar['NO-WS-CTL'] = '[\x01-\x08\x0B\x0C\x0E-\x19\x7F]';
+ self::$_grammar['WSP'] = '[ \t]';
+ self::$_grammar['CRLF'] = '(?:\r\n)';
+ self::$_grammar['FWS'] = '(?:(?:' . self::$_grammar['WSP'] . '*' .
+ self::$_grammar['CRLF'] . ')?' . self::$_grammar['WSP'] . ')';
+ self::$_grammar['text'] = '[\x00-\x08\x0B\x0C\x0E-\x7F]';
+ self::$_grammar['quoted-pair'] = '(?:\\\\' . self::$_grammar['text'] . ')';
+ self::$_grammar['ctext'] = '(?:' . self::$_grammar['NO-WS-CTL'] .
'|[\x21-\x27\x2A-\x5B\x5D-\x7E])';
//Uses recursive PCRE (?1) -- could be a weak point??
- $this->_grammar['ccontent'] = '(?:' . $this->_grammar['ctext'] . '|' .
- $this->_grammar['quoted-pair'] . '|(?1))';
- $this->_grammar['comment'] = '(\((?:' . $this->_grammar['FWS'] . '|' .
- $this->_grammar['ccontent']. ')*' . $this->_grammar['FWS'] . '?\))';
- $this->_grammar['CFWS'] = '(?:(?:' . $this->_grammar['FWS'] . '?' .
- $this->_grammar['comment'] . ')*(?:(?:' . $this->_grammar['FWS'] . '?' .
- $this->_grammar['comment'] . ')|' . $this->_grammar['FWS'] . '))';
- $this->_grammar['qtext'] = '(?:' . $this->_grammar['NO-WS-CTL'] .
+ self::$_grammar['ccontent'] = '(?:' . self::$_grammar['ctext'] . '|' .
+ self::$_grammar['quoted-pair'] . '|(?1))';
+ self::$_grammar['comment'] = '(\((?:' . self::$_grammar['FWS'] . '|' .
+ self::$_grammar['ccontent']. ')*' . self::$_grammar['FWS'] . '?\))';
+ self::$_grammar['CFWS'] = '(?:(?:' . self::$_grammar['FWS'] . '?' .
+ self::$_grammar['comment'] . ')*(?:(?:' . self::$_grammar['FWS'] . '?' .
+ self::$_grammar['comment'] . ')|' . self::$_grammar['FWS'] . '))';
+ self::$_grammar['qtext'] = '(?:' . self::$_grammar['NO-WS-CTL'] .
'|[\x21\x23-\x5B\x5D-\x7E])';
- $this->_grammar['qcontent'] = '(?:' . $this->_grammar['qtext'] . '|' .
- $this->_grammar['quoted-pair'] . ')';
- $this->_grammar['quoted-string'] = '(?:' . $this->_grammar['CFWS'] . '?"' .
- '(' . $this->_grammar['FWS'] . '?' . $this->_grammar['qcontent'] . ')*' .
- $this->_grammar['FWS'] . '?"' . $this->_grammar['CFWS'] . '?)';
- $this->_grammar['atext'] = '[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]';
- $this->_grammar['atom'] = '(?:' . $this->_grammar['CFWS'] . '?' .
- $this->_grammar['atext'] . '+' . $this->_grammar['CFWS'] . '?)';
- $this->_grammar['dot-atom-text'] = '(?:' . $this->_grammar['atext'] . '+' .
- '(\.' . $this->_grammar['atext'] . '+)*)';
- $this->_grammar['dot-atom'] = '(?:' . $this->_grammar['CFWS'] . '?' .
- $this->_grammar['dot-atom-text'] . '+' . $this->_grammar['CFWS'] . '?)';
- $this->_grammar['word'] = '(?:' . $this->_grammar['atom'] . '|' .
- $this->_grammar['quoted-string'] . ')';
- $this->_grammar['phrase'] = '(?:' . $this->_grammar['word'] . '+?)';
- $this->_grammar['no-fold-quote'] = '(?:"(?:' . $this->_grammar['qtext'] .
- '|' . $this->_grammar['quoted-pair'] . ')*")';
- $this->_grammar['dtext'] = '(?:' . $this->_grammar['NO-WS-CTL'] .
+ self::$_grammar['qcontent'] = '(?:' . self::$_grammar['qtext'] . '|' .
+ self::$_grammar['quoted-pair'] . ')';
+ self::$_grammar['quoted-string'] = '(?:' . self::$_grammar['CFWS'] . '?"' .
+ '(' . self::$_grammar['FWS'] . '?' . self::$_grammar['qcontent'] . ')*' .
+ self::$_grammar['FWS'] . '?"' . self::$_grammar['CFWS'] . '?)';
+ self::$_grammar['atext'] = '[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]';
+ self::$_grammar['atom'] = '(?:' . self::$_grammar['CFWS'] . '?' .
+ self::$_grammar['atext'] . '+' . self::$_grammar['CFWS'] . '?)';
+ self::$_grammar['dot-atom-text'] = '(?:' . self::$_grammar['atext'] . '+' .
+ '(\.' . self::$_grammar['atext'] . '+)*)';
+ self::$_grammar['dot-atom'] = '(?:' . self::$_grammar['CFWS'] . '?' .
+ self::$_grammar['dot-atom-text'] . '+' . self::$_grammar['CFWS'] . '?)';
+ self::$_grammar['word'] = '(?:' . self::$_grammar['atom'] . '|' .
+ self::$_grammar['quoted-string'] . ')';
+ self::$_grammar['phrase'] = '(?:' . self::$_grammar['word'] . '+?)';
+ self::$_grammar['no-fold-quote'] = '(?:"(?:' . self::$_grammar['qtext'] .
+ '|' . self::$_grammar['quoted-pair'] . ')*")';
+ self::$_grammar['dtext'] = '(?:' . self::$_grammar['NO-WS-CTL'] .
'|[\x21-\x5A\x5E-\x7E])';
- $this->_grammar['no-fold-literal'] = '(?:\[(?:' . $this->_grammar['dtext'] .
- '|' . $this->_grammar['quoted-pair'] . ')*\])';
+ self::$_grammar['no-fold-literal'] = '(?:\[(?:' . self::$_grammar['dtext'] .
+ '|' . self::$_grammar['quoted-pair'] . ')*\])';
//Message IDs
- $this->_grammar['id-left'] = '(?:' . $this->_grammar['dot-atom-text'] . '|' .
- $this->_grammar['no-fold-quote'] . ')';
- $this->_grammar['id-right'] = '(?:' . $this->_grammar['dot-atom-text'] . '|' .
- $this->_grammar['no-fold-literal'] . ')';
+ self::$_grammar['id-left'] = '(?:' . self::$_grammar['dot-atom-text'] . '|' .
+ self::$_grammar['no-fold-quote'] . ')';
+ self::$_grammar['id-right'] = '(?:' . self::$_grammar['dot-atom-text'] . '|' .
+ self::$_grammar['no-fold-literal'] . ')';
//Addresses, mailboxes and paths
- $this->_grammar['local-part'] = '(?:' . $this->_grammar['dot-atom'] . '|' .
- $this->_grammar['quoted-string'] . ')';
- $this->_grammar['dcontent'] = '(?:' . $this->_grammar['dtext'] . '|' .
- $this->_grammar['quoted-pair'] . ')';
- $this->_grammar['domain-literal'] = '(?:' . $this->_grammar['CFWS'] . '?\[(' .
- $this->_grammar['FWS'] . '?' . $this->_grammar['dcontent'] . ')*?' .
- $this->_grammar['FWS'] . '?\]' . $this->_grammar['CFWS'] . '?)';
- $this->_grammar['domain'] = '(?:' . $this->_grammar['dot-atom'] . '|' .
- $this->_grammar['domain-literal'] . ')';
- $this->_grammar['addr-spec'] = '(?:' . $this->_grammar['local-part'] . '@' .
- $this->_grammar['domain'] . ')';
+ self::$_grammar['local-part'] = '(?:' . self::$_grammar['dot-atom'] . '|' .
+ self::$_grammar['quoted-string'] . ')';
+ self::$_grammar['dcontent'] = '(?:' . self::$_grammar['dtext'] . '|' .
+ self::$_grammar['quoted-pair'] . ')';
+ self::$_grammar['domain-literal'] = '(?:' . self::$_grammar['CFWS'] . '?\[(' .
+ self::$_grammar['FWS'] . '?' . self::$_grammar['dcontent'] . ')*?' .
+ self::$_grammar['FWS'] . '?\]' . self::$_grammar['CFWS'] . '?)';
+ self::$_grammar['domain'] = '(?:' . self::$_grammar['dot-atom'] . '|' .
+ self::$_grammar['domain-literal'] . ')';
+ self::$_grammar['addr-spec'] = '(?:' . self::$_grammar['local-part'] . '@' .
+ self::$_grammar['domain'] . ')';
}
/**
@@ -113,9 +128,9 @@ public function __construct()
*/
public function getDefinition($name)
{
- if (array_key_exists($name, $this->_grammar))
+ if (array_key_exists($name, self::$_grammar))
{
- return $this->_grammar[$name];
+ return self::$_grammar[$name];
}
else
{
@@ -131,7 +146,7 @@ public function getDefinition($name)
*/
public function getGrammarDefinitions()
{
- return $this->_grammar;
+ return self::$_grammar;
}
/**
@@ -140,7 +155,7 @@ public function getGrammarDefinitions()
*/
public function getSpecials()
{
- return $this->_specials;
+ return self::$_specials;
}
/**
@@ -154,7 +169,7 @@ public function escapeSpecials($token, $include = array(),
$exclude = array())
{
foreach (
- array_merge(array('\\'), array_diff($this->_specials, $exclude), $include) as $char)
+ array_merge(array('\\'), array_diff(self::$_specials, $exclude), $include) as $char)
{
$token = str_replace($char, '\\' . $char, $token);
}
View
6 lib/classes/Swift/Mime/HeaderEncoder/QpHeaderEncoder.php
@@ -29,8 +29,10 @@ class Swift_Mime_HeaderEncoder_QpHeaderEncoder extends Swift_Encoder_QpEncoder
public function __construct(Swift_CharacterStream $charStream)
{
parent::__construct($charStream);
- // Reset the safeMap
- $this->_safeMap=array();
+ }
+
+ protected function initSafeMap()
+ {
foreach (array_merge(
range(0x61, 0x7A), range(0x41, 0x5A),
range(0x30, 0x39), array(0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F)
View
18 lib/classes/Swift/Mime/Headers/ParameterizedHeader.php
@@ -21,6 +21,12 @@ class Swift_Mime_Headers_ParameterizedHeader
{
/**
+ * RFC 2231's definition of a token.
+ * @var string
+ */
+ const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)';
+
+ /**
* The Encoder used to encode the parameters.
* @var Swift_Encoder
* @access private
@@ -35,13 +41,6 @@ class Swift_Mime_Headers_ParameterizedHeader
private $_params = array();
/**
- * RFC 2231's definition of a token.
- * @var string
- * @access private
- */
- private $_tokenRe;
-
- /**
* Creates a new ParameterizedHeader with $name.
* @param string $name
* @param Swift_Mime_HeaderEncoder $encoder
@@ -53,7 +52,6 @@ public function __construct($name, Swift_Mime_HeaderEncoder $encoder,
{
parent::__construct($name, $encoder, $grammar);
$this->_paramEncoder = $paramEncoder;
- $this->_tokenRe = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)';
}
/**
@@ -187,7 +185,7 @@ private function _createParameter($name, $value)
$firstLineOffset = 0;
//If it's not already a valid parameter value...
- if (!preg_match('/^' . $this->_tokenRe . '$/D', $value))
+ if (!preg_match('/^' . self::TOKEN_REGEX . '$/D', $value))
{
//TODO: text, or something else??
//... and it's not ascii
@@ -249,7 +247,7 @@ private function _createParameter($name, $value)
*/
private function _getEndOfParameterValue($value, $encoded = false, $firstLine = false)
{
- if (!preg_match('/^' . $this->_tokenRe . '$/D', $value))
+ if (!preg_match('/^' . self::TOKEN_REGEX . '$/D', $value))
{
$value = '"' . $value . '"';
}
Something went wrong with that request. Please try again.