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 "ns3/assert.h"
#include "ns3/fatal-error.h"
#include "ns3/debug.h"
#include "packet-history.h"
#include "chunk.h"
#include "buffer.h"
NS_DEBUG_COMPONENT_DEFINE ("PacketHistory");
#define noUSE_ULEB 1
namespace {
class ItemList
@ -278,6 +283,44 @@ namespace ns3 {
bool PacketHistory::m_enable = false;
uint32_t PacketHistory::m_maxSize = 0;
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
PacketHistory::Enable (void)
@ -285,86 +328,11 @@ PacketHistory::Enable (void)
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 *
PacketHistory::Create (uint32_t size)
{
g_nCreate++;
NS_DEBUG ("create size="<<size<<", max="<<m_maxSize);
if (size > m_maxSize)
{
m_maxSize = size;
@ -375,17 +343,22 @@ PacketHistory::Create (uint32_t size)
m_freeList.pop_back ();
if (data->m_size >= size)
{
NS_DEBUG ("create found size="<<data->m_size);
data->m_count = 1;
return 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
PacketHistory::Recycle (struct CommandData *data)
{
g_nRecycle++;
NS_DEBUG ("recycle size="<<data->m_size<<", list="<<m_freeList.size ());
NS_ASSERT (data->m_count == 0);
if (m_freeList.size () > 1000 ||
data->m_size < m_maxSize)
@ -401,6 +374,7 @@ PacketHistory::Recycle (struct CommandData *data)
struct PacketHistory::CommandData *
PacketHistory::Allocate (uint32_t n)
{
g_nAllocs++;
uint32_t size = sizeof (struct CommandData);
if (n <= 4)
{
@ -416,118 +390,98 @@ PacketHistory::Allocate (uint32_t n)
void
PacketHistory::Deallocate (struct CommandData *data)
{
g_nDeAllocs++;
uint8_t *buf = (uint8_t *)data;
delete [] buf;
}
void
PacketHistory::AppendOneCommand (uint32_t type, uint32_t data0, uint32_t data1)
bool
PacketHistory::TryToAppendSmallValue (uint32_t value, uint8_t **buffer)
{
NS_ASSERT (m_data != 0);
uint32_t n = GetUleb128Size (type);
n += GetUleb128Size (data0);
n += GetUleb128Size (data1);
if (m_data->m_size > m_end + n)
uint8_t *start = *buffer;
uint8_t *end = &m_data->m_data[m_data->m_size];
if (value < 0x80 && start < end)
{
if (m_data->m_count == 1 ||
m_data->m_dirtyEnd == m_end)
{
AppendValue (type);
AppendValue (data0);
AppendValue (data1);
m_n++;
return;
start[0] = value;
*buffer = start + 1;
return true;
}
else
if (value < 0x4000 && start + 1 < end)
{
uint8_t *buffer = &(m_data->m_data[m_end]);
uint32_t lastType = ReadForwardValue (&buffer);
if (lastType == type)
uint8_t byte = value & (~0x80);
start[0] = 0x80 | byte;
value >>= 7;
start[1] = value;
*buffer = start + 2;
return true;
}
return false;
}
bool
PacketHistory::TryToAppendValue (uint32_t value, uint8_t **buffer)
{
uint32_t lastData = ReadForwardValue (&buffer);
if (lastData == data0)
uint8_t *start = *buffer;
uint8_t *end = &m_data->m_data[m_data->m_size];
if (value < 0x80 && start < end)
{
lastData = ReadForwardValue (&buffer);
if (lastData == data1)
start[0] = value;
*buffer = start + 1;
return true;
}
if (value < 0x4000 && start + 1 < end)
{
return;
uint8_t byte = value & (~0x80);
start[0] = 0x80 | byte;
value >>= 7;
start[1] = value;
*buffer = start + 2;
return true;
}
}
}
}
}
Reserve (n);
AppendValue (type);
AppendValue (data0);
AppendValue (data1);
m_n++;
}
void
PacketHistory::AppendOneCommand (uint32_t type, uint32_t data)
if (value < 0x200000 && start + 2 < end)
{
NS_ASSERT (m_data != 0);
uint32_t n = GetUleb128Size (data);
n += GetUleb128Size (type);
if (m_data->m_size > m_end + n)
{
if (m_data->m_count == 1 ||
m_data->m_dirtyEnd == m_end)
{
AppendValue (type);
AppendValue (data);
m_n++;
return;
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)
{
uint8_t *buffer = &(m_data->m_data[m_end]);
uint32_t lastType = ReadForwardValue (&buffer);
if (lastType == type)
uint8_t byte = value & (~0x80);
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)
{
uint32_t lastData = ReadForwardValue (&buffer);
if (lastData == data)
/* more bytes to come */
byte |= 0x80;
}
*current = byte;
current++;
} while (value != 0 && current != end);
if (value != 0 && current == end)
{
return;
}
}
}
}
Reserve (n);
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);
}
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. */
}
else
{
/* (enough room and dirty) or (not enough room) */
ReserveCopy (size);
return false;
}
*buffer = current;
return true;
#endif
}
uint32_t
@ -542,25 +496,6 @@ PacketHistory::GetUleb128Size (uint32_t value) const
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
PacketHistory::AppendValue (uint32_t value)
{
@ -588,6 +523,7 @@ PacketHistory::AppendValue (uint32_t value)
uint32_t
PacketHistory::ReadValue (uint8_t *buffer, uint32_t *n) const
{
#ifdef USE_ULEB
uint32_t result = 0;
uint8_t shift, byte;
result = 0;
@ -609,6 +545,154 @@ PacketHistory::ReadValue (uint8_t *buffer, uint32_t *n) const
result = 0xffffffff;
}
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
@ -666,7 +750,6 @@ PacketHistory::AddAtEnd (PacketHistory const&o)
{
if (m_enable)
{
m_aggregated = true;
uint32_t n = GetUleb128Size (PacketHistory::ADD_AT_END);
n += GetUleb128Size (o.m_end);
n += GetUleb128Size (o.m_n);

View File

@ -39,10 +39,10 @@ class PacketHistory {
public:
static void Enable (void);
PacketHistory (uint32_t uid, uint32_t size);
PacketHistory (PacketHistory const &o);
PacketHistory &operator = (PacketHistory const& o);
~PacketHistory ();
inline PacketHistory (uint32_t uid, uint32_t size);
inline PacketHistory (PacketHistory const &o);
inline PacketHistory &operator = (PacketHistory const& o);
inline ~PacketHistory ();
template <typename T>
void AddHeader (T const &header, uint32_t size);
@ -63,6 +63,8 @@ public:
void PrintDefault (std::ostream &os, Buffer buffer) const;
void Print (std::ostream &os, Buffer buffer, PacketPrinter const &printer) const;
static void PrintStats (void);
private:
enum CommandType {
INIT = 0,
@ -88,9 +90,8 @@ private:
PacketHistory ();
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 GetReverseUleb128Size (uint8_t *buffer) const;
void AppendValue (uint32_t value);
uint32_t ReadForwardValue (uint8_t **pBuffer) 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 PrintComplex (std::ostream &os, Buffer buffer, const PacketPrinter &printer) 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 void Recycle (struct CommandData *data);
@ -116,7 +119,6 @@ private:
struct CommandData *m_data;
uint32_t m_end;
uint32_t m_n;
bool m_aggregated;
};
}; // namespace ns3
@ -149,6 +151,72 @@ PacketHistory::RemoveTrailer (T const &trailer, uint32_t 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

View File

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