[2/2] Avoid copy constructor in uplink tbf path

Submitted by Bhargava Abhyankar on March 22, 2016, 1:12 p.m.

Details

Message ID 1458652351-19578-2-git-send-email-Bhargava.Abhyankar@radisys.com
State Rejected, archived
Series "Series without cover letter"
Headers show

Commit Message

Bhargava Abhyankar March 22, 2016, 1:12 p.m.
The copy constructor of GprsCodingScheme class object used in
uplink tbf path is replaced by the reference variable.
Appropriate function prototypes and function definition are
changed.
This patch will increase efficiency of the code.
---
 src/bts.cpp                |  4 ++--
 src/bts.h                  |  4 ++--
 src/decoding.cpp           |  4 ++--
 src/decoding.h             |  4 ++--
 src/gprs_coding_scheme.cpp |  4 ++--
 src/gprs_coding_scheme.h   | 24 ++++++++++++------------
 6 files changed, 22 insertions(+), 22 deletions(-)

Patch hide | download patch | download mbox

diff --git a/src/bts.cpp b/src/bts.cpp
index 715fb51..412d502 100644
--- a/src/bts.cpp
+++ b/src/bts.cpp
@@ -1316,7 +1316,7 @@  int gprs_rlcmac_pdch::rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
 }
 
 int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
-	struct pcu_l1_meas *meas, GprsCodingScheme cs)
+	struct pcu_l1_meas *meas, const GprsCodingScheme &cs)
 {
 	int rc;
 	struct gprs_rlc_data_info rlc_dec;
@@ -1375,7 +1375,7 @@  int gprs_rlcmac_pdch::rcv_data_block(uint8_t *data, uint32_t fn,
 }
 
 int gprs_rlcmac_pdch::rcv_block_gprs(uint8_t *data, uint32_t fn,
-	struct pcu_l1_meas *meas, GprsCodingScheme cs)
+	struct pcu_l1_meas *meas, const GprsCodingScheme &cs)
 {
 	unsigned payload = data[0] >> 6;
 	bitvec *block;
diff --git a/src/bts.h b/src/bts.h
index c975304..812419e 100644
--- a/src/bts.h
+++ b/src/bts.h
@@ -66,9 +66,9 @@  struct gprs_rlcmac_pdch {
 	int rcv_block(uint8_t *data, uint8_t len, uint32_t fn,
 		struct pcu_l1_meas *meas);
 	int rcv_block_gprs(uint8_t *data, uint32_t fn,
-		struct pcu_l1_meas *meas, GprsCodingScheme cs);
+		struct pcu_l1_meas *meas, const GprsCodingScheme &cs);
 	int rcv_data_block(uint8_t *data, uint32_t fn,
-		struct pcu_l1_meas *meas, GprsCodingScheme cs);
+		struct pcu_l1_meas *meas, const GprsCodingScheme &cs);
 
 	gprs_rlcmac_bts *bts_data() const;
 	BTS *bts() const;
diff --git a/src/decoding.cpp b/src/decoding.cpp
index 0c81b2a..1c94b5e 100644
--- a/src/decoding.cpp
+++ b/src/decoding.cpp
@@ -181,7 +181,7 @@  static int parse_extensions_gprs(const uint8_t *data, unsigned int data_len,
 }
 
 int Decoding::rlc_data_from_ul_data(
-	const struct gprs_rlc_data_block_info *rdbi, GprsCodingScheme cs,
+	const struct gprs_rlc_data_block_info *rdbi, const GprsCodingScheme &cs,
 	const uint8_t *data, RlcData *chunks, unsigned int chunks_size,
 	uint32_t *tlli)
 {
@@ -342,7 +342,7 @@  void Decoding::extract_rbb(const struct bitvec *rbb, char *show_rbb)
 }
 
 int Decoding::rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
-	const uint8_t *data, GprsCodingScheme cs)
+	const uint8_t *data, const GprsCodingScheme &cs)
 {
 	unsigned int cur_bit = 0;
 	switch(cs.headerTypeData()) {
diff --git a/src/decoding.h b/src/decoding.h
index 1043d67..efee4d2 100644
--- a/src/decoding.h
+++ b/src/decoding.h
@@ -36,7 +36,7 @@  public:
 
 	static int rlc_data_from_ul_data(
 		const struct gprs_rlc_data_block_info *rdbi,
-		GprsCodingScheme cs, const uint8_t *data, RlcData *chunks,
+		const GprsCodingScheme &cs, const uint8_t *data, RlcData *chunks,
 		unsigned int chunks_size, uint32_t *tlli);
 	static uint8_t get_ms_class_by_capability(MS_Radio_Access_capability_t *cap);
 	static uint8_t get_egprs_ms_class_by_capability(MS_Radio_Access_capability_t *cap);
@@ -52,7 +52,7 @@  public:
 		const uint8_t *data,
 		const GprsCodingScheme &cs);
 	static int rlc_parse_ul_data_header(struct gprs_rlc_data_info *rlc,
-		const uint8_t *data, GprsCodingScheme cs);
+		const uint8_t *data, const GprsCodingScheme &cs);
 	static unsigned int rlc_copy_to_aligned_buffer(
 		const struct gprs_rlc_data_info *rlc,
 		unsigned int data_block_idx,
diff --git a/src/gprs_coding_scheme.cpp b/src/gprs_coding_scheme.cpp
index 8601d4f..cb141c1 100644
--- a/src/gprs_coding_scheme.cpp
+++ b/src/gprs_coding_scheme.cpp
@@ -259,7 +259,7 @@  const char *GprsCodingScheme::modeName(Mode mode)
 	}
 }
 
-bool GprsCodingScheme::isFamilyCompatible(GprsCodingScheme o) const
+bool GprsCodingScheme::isFamilyCompatible(const GprsCodingScheme &o) const
 {
 	if (*this == o)
 		return true;
@@ -270,7 +270,7 @@  bool GprsCodingScheme::isFamilyCompatible(GprsCodingScheme o) const
 	return family() == o.family();
 }
 
-bool GprsCodingScheme::isCombinable(GprsCodingScheme o) const
+bool GprsCodingScheme::isCombinable(const GprsCodingScheme &o) const
 {
 	return numDataBlocks() == o.numDataBlocks();
 }
diff --git a/src/gprs_coding_scheme.h b/src/gprs_coding_scheme.h
index aec3762..1519e12 100644
--- a/src/gprs_coding_scheme.h
+++ b/src/gprs_coding_scheme.h
@@ -64,16 +64,16 @@  public:
 	unsigned int to_num() const;
 
 	GprsCodingScheme& operator =(Scheme s);
-	GprsCodingScheme& operator =(GprsCodingScheme o);
+	GprsCodingScheme& operator =(const GprsCodingScheme &o);
 
 	bool isValid()   const {return UNKNOWN <= m_scheme && m_scheme <= MCS9;}
 	bool isGprs()   const {return CS1 <= m_scheme && m_scheme <= CS4;}
 	bool isEgprs()  const {return m_scheme >= MCS1;}
 	bool isEgprsGmsk()  const {return isEgprs() && m_scheme <= MCS4;}
 	bool isCompatible(Mode mode) const;
-	bool isCompatible(GprsCodingScheme o) const;
-	bool isFamilyCompatible(GprsCodingScheme o) const;
-	bool isCombinable(GprsCodingScheme o) const;
+	bool isCompatible(const GprsCodingScheme &o) const;
+	bool isFamilyCompatible(const GprsCodingScheme &o) const;
+	bool isCombinable(const GprsCodingScheme &o) const;
 
 	void inc(Mode mode);
 	void dec(Mode mode);
@@ -133,7 +133,7 @@  inline bool GprsCodingScheme::isCompatible(Mode mode) const
 	return false;
 }
 
-inline bool GprsCodingScheme::isCompatible(GprsCodingScheme o) const
+inline bool GprsCodingScheme::isCompatible(const GprsCodingScheme &o) const
 {
 	return (isGprs() && o.isGprs()) || (isEgprs() && o.isEgprs());
 }
@@ -160,7 +160,7 @@  inline GprsCodingScheme& GprsCodingScheme::operator =(Scheme s)
 	return *this;
 }
 
-inline GprsCodingScheme& GprsCodingScheme::operator =(GprsCodingScheme o)
+inline GprsCodingScheme& GprsCodingScheme::operator =(const GprsCodingScheme &o)
 {
 	m_scheme = o.m_scheme;
 	return *this;
@@ -183,33 +183,33 @@  inline GprsCodingScheme GprsCodingScheme::getEgprsByNum(unsigned num)
 }
 
 /* The coding schemes form a partial ordering */
-inline bool operator ==(GprsCodingScheme a, GprsCodingScheme b)
+inline bool operator ==(const GprsCodingScheme &a, const GprsCodingScheme &b)
 {
 	return GprsCodingScheme::Scheme(a) == GprsCodingScheme::Scheme(b);
 }
 
-inline bool operator !=(GprsCodingScheme a, GprsCodingScheme b)
+inline bool operator !=(const GprsCodingScheme &a, const GprsCodingScheme &b)
 {
 	return !(a == b);
 }
 
-inline bool operator <(GprsCodingScheme a, GprsCodingScheme b)
+inline bool operator <(const GprsCodingScheme &a, const GprsCodingScheme &b)
 {
 	return a.isCompatible(b) &&
 		GprsCodingScheme::Scheme(a) < GprsCodingScheme::Scheme(b);
 }
 
-inline bool operator >(GprsCodingScheme a, GprsCodingScheme b)
+inline bool operator >(const GprsCodingScheme &a, const GprsCodingScheme &b)
 {
 	return b < a;
 }
 
-inline bool operator <=(GprsCodingScheme a, GprsCodingScheme b)
+inline bool operator <=(const GprsCodingScheme &a, const GprsCodingScheme &b)
 {
 	return a == b || a < b;
 }
 
-inline bool operator >=(GprsCodingScheme a, GprsCodingScheme b)
+inline bool operator >=(const GprsCodingScheme &a, const GprsCodingScheme &b)
 {
 	return a == b || a > b;
 }

Comments

Holger Freyther March 22, 2016, 8:26 p.m.
> On 22 Mar 2016, at 14:12, Bhargava Abhyankar <Bhargava.Abhyankar@radisys.com> wrote:
> 
> The copy constructor of GprsCodingScheme class object used in
> uplink tbf path is replaced by the reference variable.
> Appropriate function prototypes and function definition are
> changed.

yes, it is good style to mark them as const (and pass them as reference).


> This patch will increase efficiency of the code.

Given the size of the member and that the constructor is inlined my first assumption is that for this specific type the runtime cost of copying m_scheme and a pointer will be about the same.


kind regards
	holger
Jacob Erlbeck March 23, 2016, 10:23 a.m.
Hi

On 22.03.2016 21:26, Holger Freyther wrote:
> 
>> On 22 Mar 2016, at 14:12, Bhargava Abhyankar <Bhargava.Abhyankar@radisys.com> wrote:
>>
>> The copy constructor of GprsCodingScheme class object used in
>> uplink tbf path is replaced by the reference variable.
>> Appropriate function prototypes and function definition are
>> changed.
> 
> yes, it is good style to mark them as const (and pass them as reference).

Hmm. I do not agree. Passing as reference doesn't make much sense here
(there is not performance issue and no risk of slicing). It just an
integer/enum disguised as class and it is meant be used like an enum.
But of course, if it was a reference, marking it as const would be good.

> 
> 
>> This patch will increase efficiency of the code.

No, using a reference in general (unless inlining is done) will
eventually result in a larger variable/parameter/field size (depending
on the enum size and the pointer size on the target plattform, where the
pointer size will be >= enum size on all platforms I know of). In
addition, dereferencing is needed which cost additional instructions and
memory accesses (albeit with a high probability for a cache hit, if
there is any).

So in my personal opinion I wouldn't merge this patch, BYMMV.

Kind regards

Jacob

> 
> Given the size of the member and that the constructor is inlined my first assumption is that for this specific type the runtime cost of copying m_scheme and a pointer will be about the same.
>
Holger Freyther March 23, 2016, 10:34 a.m.
> On 23 Mar 2016, at 11:23, Jacob <jacob01@gmx.net> wrote:
> 
> Hi

Hi,


>> 
>> yes, it is good style to mark them as const (and pass them as reference).
> 
> Hmm. I do not agree. Passing as reference doesn't make much sense here
> (there is not performance issue and no risk of slicing). It just an
> integer/enum disguised as class and it is meant be used like an enum.
> But of course, if it was a reference, marking it as const would be good.

Given your other argument about the reference I will not merge the patch but could you explain why

	isCompatible(), isFamilyCompatible(), ... and
	pdch::rcv_data_block, rcv_block_gprs

require a mutable argument? I assume that ::inc/::dec should never be called on objects routines? From this point of view I think it is favorable to mark these methods with const parameters? What is your take here?



>>> This patch will increase efficiency of the code.
> 
> No, using a reference in general (unless inlining is done) will
> eventually result in a larger variable/parameter/field size (depending
> on the enum size and the pointer size on the target plattform, where the
> pointer size will be >= enum size on all platforms I know of). In
> addition, dereferencing is needed which cost additional instructions and
> memory accesses (albeit with a high probability for a cache hit, if
> there is any).


good point. I think either way the performance for this one will not be noticeable.

holger
Harald Welte March 23, 2016, 10:46 a.m.
Dear all,

as a general rule, I suggest to refrain from optimizations, unless

a) a performance issue is immediately obvious, or

b) there is actual profiling showing an improvement comparing
   before/after, or at least showing that the existing code is a CPU
   hog.

Everything else is - with all respect - likely to waste time of everyone
involved in preparing the patch, reviewing it, discussing it, etc.

To say it with Donald Knuth:
"Premature optimization is the root of all evil"

Now that of course is no excuse from writing unneccesarily bloated or
inefficient code in the first place, but we generally try to keep things
simple.

Also, keep in mind that a PCU in 1999/2000 had to run on incredibly
small and inefficient hardware, while today I think the smallest system
is the sysmoBTS 1002 on an ARM926EJS processor at 405 MHz.  And it only
has a single TRX at that.

All other systems it runs on have much faster CPU, memory bandwidth, RAM
size.... so let's focus on improving the code functionality and
completeness before optimizing things that are not even proven issues in
the real world

Regards,
	Harald