a bunch of optimizations

Mathieu Lacage 2007-06-03 20:09:56 +02:00
parent a6c8a11881
commit a4f727f68d
3 changed files with 364 additions and 202 deletions

View File

@ -22,10 +22,15 @@
#include <list> #include <list>
#include "ns3/assert.h" #include "ns3/assert.h"
#include "ns3/fatal-error.h" #include "ns3/fatal-error.h"
#include "ns3/debug.h"
#include "packet-history.h" #include "packet-history.h"
#include "chunk.h" #include "chunk.h"
#include "buffer.h" #include "buffer.h"
NS_DEBUG_COMPONENT_DEFINE ("PacketHistory");
#define noUSE_ULEB 1
namespace { namespace {
class ItemList class ItemList
@ -278,6 +283,44 @@ namespace ns3 {
bool PacketHistory::m_enable = false; bool PacketHistory::m_enable = false;
uint32_t PacketHistory::m_maxSize = 0; uint32_t PacketHistory::m_maxSize = 0;
PacketHistory::DataFreeList PacketHistory::m_freeList; PacketHistory::DataFreeList PacketHistory::m_freeList;
uint32_t g_nAllocs = 0;
uint32_t g_nDeAllocs = 0;
uint32_t g_nRecycle = 0;
uint32_t g_nCreate = 0;
uint32_t g_one = 0;
uint32_t g_two = 0;
uint32_t g_three = 0;
uint32_t g_four = 0;
uint32_t g_five = 0;
void
PacketHistory::PrintStats (void)
{
std::cout << "allocs="<<g_nAllocs<<", deallocs="<<g_nDeAllocs
<<", recycle="<<g_nRecycle<<", create="<<g_nCreate<<std::endl;
std::cout << "one="<<g_one<<", two="<<g_two<<", three="<<g_three<<std::endl;
//std::cout << "four="<<g_four<<", five="<<g_five<<std::endl;
g_nAllocs = 0;
g_nDeAllocs = 0;
g_nRecycle = 0;
g_nCreate = 0;
g_one = 0;
g_two = 0;
g_three = 0;
g_four = 0;
g_five = 0;
#if 0
PacketHistory h (0, 0);
for (uint32_t i = 0; i < 0xffffff; i++)
{
if (h.GetUleb128Size (i) == 4)
{
std::cout << i << std::endl;
break;
}
}
#endif
}
void void
PacketHistory::Enable (void) PacketHistory::Enable (void)
@ -285,86 +328,11 @@ PacketHistory::Enable (void)
m_enable = true; m_enable = true;
} }
PacketHistory::PacketHistory ()
: m_data (0),
m_end (0),
m_n (0),
m_aggregated (false)
{
Construct (0, 0);
}
PacketHistory::PacketHistory (uint32_t uid, uint32_t size)
: m_data (0),
m_end (0),
m_n (0),
m_aggregated (false)
{
Construct (uid, size);
}
void
PacketHistory::Construct (uint32_t uid, uint32_t size)
{
if (m_enable)
{
m_data = PacketHistory::Create (size);
AppendOneCommand (PacketHistory::INIT,
size, uid);
}
}
PacketHistory::PacketHistory (PacketHistory const &o)
: m_data (o.m_data),
m_end (o.m_end),
m_n (o.m_n),
m_aggregated (o.m_aggregated)
{
if (m_data != 0)
{
m_data->m_count++;
}
}
PacketHistory &
PacketHistory::operator = (PacketHistory const& o)
{
if (m_data == o.m_data)
{
// self assignment
return *this;
}
if (m_data != 0)
{
m_data->m_count--;
if (m_data->m_count == 0)
{
PacketHistory::Recycle (m_data);
}
}
m_data = o.m_data;
m_end = o.m_end;
m_n = o.m_n;
m_aggregated = o.m_aggregated;
if (m_data != 0)
{
m_data->m_count++;
}
return *this;
}
PacketHistory::~PacketHistory ()
{
if (m_data != 0)
{
m_data->m_count--;
if (m_data->m_count == 0)
{
PacketHistory::Recycle (m_data);
}
}
}
struct PacketHistory::CommandData * struct PacketHistory::CommandData *
PacketHistory::Create (uint32_t size) PacketHistory::Create (uint32_t size)
{ {
g_nCreate++;
NS_DEBUG ("create size="<<size<<", max="<<m_maxSize);
if (size > m_maxSize) if (size > m_maxSize)
{ {
m_maxSize = size; m_maxSize = size;
@ -375,17 +343,22 @@ PacketHistory::Create (uint32_t size)
m_freeList.pop_back (); m_freeList.pop_back ();
if (data->m_size >= size) if (data->m_size >= size)
{ {
NS_DEBUG ("create found size="<<data->m_size);
data->m_count = 1; data->m_count = 1;
return data; return data;
} }
PacketHistory::Deallocate (data); PacketHistory::Deallocate (data);
NS_DEBUG ("create dealloc size="<<data->m_size);
} }
return PacketHistory::Allocate (size); NS_DEBUG ("create alloc size="<<m_maxSize);
return PacketHistory::Allocate (m_maxSize);
} }
void void
PacketHistory::Recycle (struct CommandData *data) PacketHistory::Recycle (struct CommandData *data)
{ {
g_nRecycle++;
NS_DEBUG ("recycle size="<<data->m_size<<", list="<<m_freeList.size ());
NS_ASSERT (data->m_count == 0); NS_ASSERT (data->m_count == 0);
if (m_freeList.size () > 1000 || if (m_freeList.size () > 1000 ||
data->m_size < m_maxSize) data->m_size < m_maxSize)
@ -401,6 +374,7 @@ PacketHistory::Recycle (struct CommandData *data)
struct PacketHistory::CommandData * struct PacketHistory::CommandData *
PacketHistory::Allocate (uint32_t n) PacketHistory::Allocate (uint32_t n)
{ {
g_nAllocs++;
uint32_t size = sizeof (struct CommandData); uint32_t size = sizeof (struct CommandData);
if (n <= 4) if (n <= 4)
{ {
@ -416,118 +390,98 @@ PacketHistory::Allocate (uint32_t n)
void void
PacketHistory::Deallocate (struct CommandData *data) PacketHistory::Deallocate (struct CommandData *data)
{ {
g_nDeAllocs++;
uint8_t *buf = (uint8_t *)data; uint8_t *buf = (uint8_t *)data;
delete [] buf; delete [] buf;
} }
void bool
PacketHistory::AppendOneCommand (uint32_t type, uint32_t data0, uint32_t data1) PacketHistory::TryToAppendSmallValue (uint32_t value, uint8_t **buffer)
{ {
NS_ASSERT (m_data != 0); uint8_t *start = *buffer;
uint32_t n = GetUleb128Size (type); uint8_t *end = &m_data->m_data[m_data->m_size];
n += GetUleb128Size (data0); if (value < 0x80 && start < end)
n += GetUleb128Size (data1);
if (m_data->m_size > m_end + n)
{ {
if (m_data->m_count == 1 || start[0] = value;
m_data->m_dirtyEnd == m_end) *buffer = start + 1;
{ return true;
AppendValue (type);
AppendValue (data0);
AppendValue (data1);
m_n++;
return;
}
else
{
uint8_t *buffer = &(m_data->m_data[m_end]);
uint32_t lastType = ReadForwardValue (&buffer);
if (lastType == type)
{
uint32_t lastData = ReadForwardValue (&buffer);
if (lastData == data0)
{
lastData = ReadForwardValue (&buffer);
if (lastData == data1)
{
return;
}
}
}
}
} }
Reserve (n); if (value < 0x4000 && start + 1 < end)
AppendValue (type); {
AppendValue (data0); uint8_t byte = value & (~0x80);
AppendValue (data1); start[0] = 0x80 | byte;
m_n++; value >>= 7;
start[1] = value;
*buffer = start + 2;
return true;
}
return false;
} }
bool
void PacketHistory::TryToAppendValue (uint32_t value, uint8_t **buffer)
PacketHistory::AppendOneCommand (uint32_t type, uint32_t data)
{ {
NS_ASSERT (m_data != 0); uint8_t *start = *buffer;
uint32_t n = GetUleb128Size (data); uint8_t *end = &m_data->m_data[m_data->m_size];
n += GetUleb128Size (type); if (value < 0x80 && start < end)
if (m_data->m_size > m_end + n)
{ {
if (m_data->m_count == 1 || start[0] = value;
m_data->m_dirtyEnd == m_end) *buffer = start + 1;
{ return true;
AppendValue (type);
AppendValue (data);
m_n++;
return;
}
else
{
uint8_t *buffer = &(m_data->m_data[m_end]);
uint32_t lastType = ReadForwardValue (&buffer);
if (lastType == type)
{
uint32_t lastData = ReadForwardValue (&buffer);
if (lastData == data)
{
return;
}
}
}
} }
Reserve (n); if (value < 0x4000 && start + 1 < end)
AppendValue (type);
AppendValue (data);
m_n++;
}
void
PacketHistory::ReserveCopy (uint32_t size)
{
struct CommandData *newData = PacketHistory::Create (m_end + size);
memcpy (newData->m_data, m_data->m_data, m_end);
newData->m_dirtyEnd = m_end;
m_data->m_count--;
if (m_data->m_count == 0)
{ {
PacketHistory::Recycle (m_data); uint8_t byte = value & (~0x80);
start[0] = 0x80 | byte;
value >>= 7;
start[1] = value;
*buffer = start + 2;
return true;
} }
m_data = newData; if (value < 0x200000 && start + 2 < end)
}
void
PacketHistory::Reserve (uint32_t size)
{
NS_ASSERT (m_data != 0);
if (m_data->m_size > m_end + size &&
(m_data->m_count == 1 ||
m_data->m_dirtyEnd == m_end))
{ {
/* enough room, not dirty. */ uint8_t byte = value & (~0x80);
start[0] = 0x80 | byte;
value >>= 7;
start[1] = 0x80 | byte;
value >>= 7;
start[2] = value;
*buffer = start + 3;
return true;
} }
else if (start + 3 < end)
{ {
/* (enough room and dirty) or (not enough room) */ uint8_t byte = value & (~0x80);
ReserveCopy (size); start[0] = 0x80 | byte;
value >>= 7;
start[1] = 0x80 | byte;
value >>= 7;
start[2] = 0x80 | byte;
value >>= 7;
start[3] = value;
*buffer = start + 4;
return true;
} }
return false;
#if 0
// more generic version of the above.
do {
uint8_t byte = value & (~0x80);
value >>= 7;
if (value != 0)
{
/* more bytes to come */
byte |= 0x80;
}
*current = byte;
current++;
} while (value != 0 && current != end);
if (value != 0 && current == end)
{
return false;
}
*buffer = current;
return true;
#endif
} }
uint32_t uint32_t
@ -542,25 +496,6 @@ PacketHistory::GetUleb128Size (uint32_t value) const
return n; return n;
} }
uint32_t
PacketHistory::GetReverseUleb128Size (uint8_t *buffer) const
{
uint8_t *cur = buffer;
uint8_t byte = *cur;
if (byte & 0x80)
{
NS_FATAL_ERROR ("The last byte should have a zero high bit");
}
cur--;
while ((byte & 0x80) && (buffer - cur) < 5)
{
cur--;
byte = *cur;
}
uint32_t n = buffer - cur;
return n;
}
void void
PacketHistory::AppendValue (uint32_t value) PacketHistory::AppendValue (uint32_t value)
{ {
@ -588,6 +523,7 @@ PacketHistory::AppendValue (uint32_t value)
uint32_t uint32_t
PacketHistory::ReadValue (uint8_t *buffer, uint32_t *n) const PacketHistory::ReadValue (uint8_t *buffer, uint32_t *n) const
{ {
#ifdef USE_ULEB
uint32_t result = 0; uint32_t result = 0;
uint8_t shift, byte; uint8_t shift, byte;
result = 0; result = 0;
@ -609,6 +545,154 @@ PacketHistory::ReadValue (uint8_t *buffer, uint32_t *n) const
result = 0xffffffff; result = 0xffffffff;
} }
return result; return result;
#else
uint32_t *start = (uint32_t *)buffer;
*n = *n + 4;
return *start;
#endif
}
void
PacketHistory::AppendOneCommand (uint32_t type, uint32_t data0, uint32_t data1)
{
NS_ASSERT (m_data != 0);
#ifdef USE_ULEB
if (m_data->m_count == 1 ||
m_data->m_dirtyEnd == m_end)
{
uint8_t *start = &m_data->m_data[m_end];
uint8_t *current = start;
if (TryToAppendSmallValue (type, &current) &&
TryToAppendSmallValue (data0, &current) &&
TryToAppendValue (data1, &current))
{
uintptr_t written = current - start;
m_end += written;
m_data->m_dirtyEnd = m_end;
m_n++;
g_one++;
return;
}
}
g_two++;
uint32_t n = GetUleb128Size (type);
n += GetUleb128Size (data0);
n += GetUleb128Size (data1);
Reserve (n);
AppendValue (type);
AppendValue (data0);
AppendValue (data1);
m_n++;
#else
restart:
if (m_data->m_count == 1 ||
m_data->m_dirtyEnd == m_end)
{
uint32_t *start = (uint32_t *)&m_data->m_data[m_end];
uint32_t *end = (uint32_t *)&m_data->m_data[m_data->m_size];
if (start + 2 < end)
{
start[0] = type;
start[1] = data0;
start[2] = data1;
m_end += 12;
m_data->m_dirtyEnd = m_end;
m_n++;
g_one++;
return;
}
}
g_two++;
Reserve (12);
goto restart;
#endif
}
void
PacketHistory::AppendOneCommand (uint32_t type, uint32_t data)
{
NS_ASSERT (m_data != 0);
#ifdef USE_ULEB
if (m_data->m_count == 1 ||
m_data->m_dirtyEnd == m_end)
{
uint8_t *start = &m_data->m_data[m_end];
uint8_t *current = start;
if (TryToAppendSmallValue (type, &current) &&
TryToAppendSmallValue (data, &current))
{
uintptr_t written = current - start;
m_end += written;
m_data->m_dirtyEnd = m_end;
m_n++;
g_one++;
return;
}
}
g_two++;
uint32_t n = GetUleb128Size (data);
n += GetUleb128Size (type);
Reserve (n);
AppendValue (type);
AppendValue (data);
m_n++;
#else
restart:
if (m_data->m_count == 1 ||
m_data->m_dirtyEnd == m_end)
{
uint32_t *start = (uint32_t *)&m_data->m_data[m_end];
uint32_t *end = (uint32_t *)&m_data->m_data[m_data->m_size];
if (start + 1 < end)
{
start[0] = type;
start[1] = data;
m_end += 8;
m_data->m_dirtyEnd = m_end;
m_n++;
g_one++;
return;
}
}
g_two++;
Reserve (8);
goto restart;
#endif
}
void
PacketHistory::ReserveCopy (uint32_t size)
{
struct CommandData *newData = PacketHistory::Create (m_end + size);
memcpy (newData->m_data, m_data->m_data, m_end);
newData->m_dirtyEnd = m_end;
m_data->m_count--;
if (m_data->m_count == 0)
{
PacketHistory::Recycle (m_data);
}
m_data = newData;
}
void
PacketHistory::Reserve (uint32_t size)
{
NS_ASSERT (m_data != 0);
if (m_data->m_size >= m_end + size &&
(m_data->m_count == 1 ||
m_data->m_dirtyEnd == m_end))
{
/* enough room, not dirty. */
g_four++;
}
else
{
/* (enough room and dirty) or (not enough room) */
ReserveCopy (size);
g_five++;
}
} }
uint32_t uint32_t
@ -666,7 +750,6 @@ PacketHistory::AddAtEnd (PacketHistory const&o)
{ {
if (m_enable) if (m_enable)
{ {
m_aggregated = true;
uint32_t n = GetUleb128Size (PacketHistory::ADD_AT_END); uint32_t n = GetUleb128Size (PacketHistory::ADD_AT_END);
n += GetUleb128Size (o.m_end); n += GetUleb128Size (o.m_end);
n += GetUleb128Size (o.m_n); n += GetUleb128Size (o.m_n);

View File

@ -39,10 +39,10 @@ class PacketHistory {
public: public:
static void Enable (void); static void Enable (void);
PacketHistory (uint32_t uid, uint32_t size); inline PacketHistory (uint32_t uid, uint32_t size);
PacketHistory (PacketHistory const &o); inline PacketHistory (PacketHistory const &o);
PacketHistory &operator = (PacketHistory const& o); inline PacketHistory &operator = (PacketHistory const& o);
~PacketHistory (); inline ~PacketHistory ();
template <typename T> template <typename T>
void AddHeader (T const &header, uint32_t size); void AddHeader (T const &header, uint32_t size);
@ -63,6 +63,8 @@ public:
void PrintDefault (std::ostream &os, Buffer buffer) const; void PrintDefault (std::ostream &os, Buffer buffer) const;
void Print (std::ostream &os, Buffer buffer, PacketPrinter const &printer) const; void Print (std::ostream &os, Buffer buffer, PacketPrinter const &printer) const;
static void PrintStats (void);
private: private:
enum CommandType { enum CommandType {
INIT = 0, INIT = 0,
@ -88,9 +90,8 @@ private:
PacketHistory (); PacketHistory ();
void Reserve (uint32_t n); void Reserve (uint32_t n);
void Construct (uint32_t uid, uint32_t size); inline void Construct (uint32_t uid, uint32_t size);
uint32_t GetUleb128Size (uint32_t value) const; uint32_t GetUleb128Size (uint32_t value) const;
uint32_t GetReverseUleb128Size (uint8_t *buffer) const;
void AppendValue (uint32_t value); void AppendValue (uint32_t value);
uint32_t ReadForwardValue (uint8_t **pBuffer) const; uint32_t ReadForwardValue (uint8_t **pBuffer) const;
uint32_t ReadValue (uint8_t *buffer, uint32_t *n) const; uint32_t ReadValue (uint8_t *buffer, uint32_t *n) const;
@ -103,6 +104,8 @@ private:
void RemoveTrailer (uint32_t uid, Chunk const & trailer, uint32_t size); void RemoveTrailer (uint32_t uid, Chunk const & trailer, uint32_t size);
void PrintComplex (std::ostream &os, Buffer buffer, const PacketPrinter &printer) const; void PrintComplex (std::ostream &os, Buffer buffer, const PacketPrinter &printer) const;
void BuildItemList (ItemList *list, uint8_t **buffer, uint32_t size, uint32_t n) const; void BuildItemList (ItemList *list, uint8_t **buffer, uint32_t size, uint32_t n) const;
inline bool TryToAppendValue (uint32_t value, uint8_t **buffer);
inline bool TryToAppendSmallValue (uint32_t value, uint8_t **buffer);
static struct PacketHistory::CommandData *Create (uint32_t size); static struct PacketHistory::CommandData *Create (uint32_t size);
static void Recycle (struct CommandData *data); static void Recycle (struct CommandData *data);
@ -116,7 +119,6 @@ private:
struct CommandData *m_data; struct CommandData *m_data;
uint32_t m_end; uint32_t m_end;
uint32_t m_n; uint32_t m_n;
bool m_aggregated;
}; };
}; // namespace ns3 }; // namespace ns3
@ -149,6 +151,72 @@ PacketHistory::RemoveTrailer (T const &trailer, uint32_t size)
RemoveTrailer (PacketPrinter::GetUid<T> (), trailer, size); RemoveTrailer (PacketPrinter::GetUid<T> (), trailer, size);
} }
PacketHistory::PacketHistory (uint32_t uid, uint32_t size)
: m_data (0),
m_end (0),
m_n (0)
{
Construct (uid, size);
}
void
PacketHistory::Construct (uint32_t uid, uint32_t size)
{
if (m_enable)
{
m_data = PacketHistory::Create (0);
AppendOneCommand (PacketHistory::INIT,
size, uid);
}
}
PacketHistory::PacketHistory (PacketHistory const &o)
: m_data (o.m_data),
m_end (o.m_end),
m_n (o.m_n)
{
if (m_data != 0)
{
m_data->m_count++;
}
}
PacketHistory &
PacketHistory::operator = (PacketHistory const& o)
{
if (m_data == o.m_data)
{
// self assignment
return *this;
}
if (m_data != 0)
{
m_data->m_count--;
if (m_data->m_count == 0)
{
PacketHistory::Recycle (m_data);
}
}
m_data = o.m_data;
m_end = o.m_end;
m_n = o.m_n;
if (m_data != 0)
{
m_data->m_count++;
}
return *this;
}
PacketHistory::~PacketHistory ()
{
if (m_data != 0)
{
m_data->m_count--;
if (m_data->m_count == 0)
{
PacketHistory::Recycle (m_data);
}
}
}
}; // namespace ns3 }; // namespace ns3

View File

@ -20,6 +20,7 @@
*/ */
#include "ns3/system-wall-clock-ms.h" #include "ns3/system-wall-clock-ms.h"
#include "ns3/packet.h" #include "ns3/packet.h"
#include "ns3/packet-history.h"
#include <iostream> #include <iostream>
#include <sstream> #include <sstream>
@ -173,17 +174,27 @@ int main (int argc, char *argv[])
{ {
uint32_t n = 0; uint32_t n = 0;
while (argc > 0) { while (argc > 0) {
if (strncmp ("--n=", argv[0],strlen ("--n=")) == 0) { if (strncmp ("--n=", argv[0],strlen ("--n=")) == 0)
{
char const *nAscii = argv[0] + strlen ("--n="); char const *nAscii = argv[0] + strlen ("--n=");
n = atoi (nAscii); n = atoi (nAscii);
} }
if (strncmp ("--enable-history", argv[0], strlen ("--enable-history")) == 0)
{
PacketHistory::Enable ();
}
argc--; argc--;
argv++; argv++;
} }
runBench (&benchPtrA, n, "a"); runBench (&benchPtrA, n, "a");
PacketHistory::PrintStats ();
runBench (&benchPtrB, n, "b"); runBench (&benchPtrB, n, "b");
PacketHistory::PrintStats ();
runBench (&benchPtrC, n, "c"); runBench (&benchPtrC, n, "c");
PacketHistory::PrintStats ();
return 0; return 0;
} }