| title: | Re PATCH Avoid unnecessary data copying in |
|
Hi
Here is an improved version of the original patch:
The original patch removed unnecessary copying for 204 sized packets only.
This patch improves performance for 188 sized packets too.
Unnecessary copying means: if dvb_dmx_swfilter(_204)() doesnt have to
modify
the source packet, the source packet is delivered for
dvb_dmx_swfilter_packet()
without copying.
This assumes, that a DMA transfer wont modify the accepted 188/204 sized
packet underneath while dvb_dmx_swfilter_packet() processes it.
The assumption is already in dvb_dmx_swfilter_packets().
With tasklets the risk for breaking the assumption is low. If there
would be
a normal thread instead of a tasklet, copying from the DMA buffer might
come too late.
Could someone test this patch who uses the dvb_dmx_swfilter() function
(188 sized)?
So _dvb_dmx_swfilter is now common for both 188 and 204 sized packet
parsing.
The measure was done during recording of H.264 steram under VDR,
using "perf top -d 10"
PerfTop: 62 irqs/sec kernel:80.6% [1000Hz cycles], (all, 1 CPUs)
samples pcnt
function DSO
339.00 18.1%
dvb_dmx_swfilter_packet
[dvb_core]
315.00 16.9%
acpi_pm_read
[kernel.kallsyms]
70.00 3.7%
_ZN2SI5CRC325crc32EPKcij
/usr/sbin/vdr
53.00 2.8%
mantis_i2c_xfer
[mantis_core]
53.00 2.8%
__mktime_internal
/lib64/libc-2.12.so
39.00 2.1%
_ZN14cAudioRepacker6RepackEP17cRingBufferLinearPKhi
/usr/sbin/vdr
33.00 1.8%
delay_tsc
[kernel.kallsyms]
30.00 1.6%
dvb_dmx_memcopy
[dvb_core]
28.00 1.5%
dvb_ringbuffer_write
[dvb_core]
28.00 1.5%
_dvb_dmx_swfilter
[dvb_core]
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c
b/drivers/media/dvb/dvb-core/dvb_demux.c
index 977ddba..2ddaaaa 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -478,95 +478,78 @@ void dvb_dmx_swfilter_packets(struct dvb_demux
*demux, const u8 *buf,
EXPORT_SYMBOL(dvb_dmx_swfilter_packets);
-void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
+static inline int findNextSyncByte(const u8 *buf, int pos, size_t
count, const int pktsize)
+{
+ while(likely(pos < count)) {
+ if (likely(buf[pos] == 0x47 || (pktsize == 204 && buf[pos] ==
0xB8)))
+ break;
+ pos++;
+ }
+
+ return pos;
+}
+
+/* pktsize must be either 204 or 188. If pktsize is 204, 0xB8 must be
accepted for SYNC byte too, but then convert it into 0x47.
+ * Designed pktsize so, that compiler would remove 204 related code
during inlining. */
+static inline void _dvb_dmx_swfilter(struct dvb_demux *demux, const u8
*buf, size_t count, const int pktsize)
{
int p = 0, i, j;
+ const u8 *q;
spin_lock(&demux- lock);
- if (demux- tsbufp) {
+ if (likely(demux- tsbufp)) { /* tsbuf[0] is now 0x47. */
i = demux- tsbufp;
- j = 188 - i;
- if (count < j) {
+ j = pktsize - i;
+ if (unlikely(count < j)) {
memcpy(&demux- tsbuf[i], buf, count);
demux- tsbufp += count;
goto bailout;
}
memcpy(&demux- tsbuf[i], buf, j);
- if (demux- tsbuf[0] == 0x47)
+ if (likely(demux- tsbuf[0] == 0x47)) /* double check */
dvb_dmx_swfilter_packet(demux, demux- tsbuf);
demux- tsbufp = 0;
p += j;
}
- while (p < count) {
- if (buf[p] == 0x47) {
- if (count - p = 188) {
- dvb_dmx_swfilter_packet(demux, &buf[p]);
- p += 188;
- } else {
- i = count - p;
- memcpy(demux- tsbuf, &buf[p], i);
- demux- tsbufp = i;
- goto bailout;
- }
- } else
- p++;
+ while (likely((p = findNextSyncByte(buf, p, count, pktsize)) <
count)) {
+ if (unlikely(count - p < pktsize))
+ break;
+
+ q = &buf[p];
+
+ if (unlikely(pktsize == 204 && (*q == 0xB8))) {
+ memcpy(demux- tsbuf, q, 188);
+ demux- tsbuf[0] = 0x47;
+ q = demux- tsbuf;
+ }
+ dvb_dmx_swfilter_packet(demux, q);
+ p += pktsize;
+ }
+
+ i = count - p;
+ if (likely(i)) {
+ memcpy(demux- tsbuf, &buf[p], i);
+ demux- tsbufp = i;
+ if (unlikely(pktsize == 204 && demux- tsbuf[0] == 0xB8))
+ demux- tsbuf[0] = 0x47;
}
bailout:
spin_unlock(&demux- lock);
}
+void dvb_dmx_swfilter(struct dvb_demux *demux, const u8 *buf, size_t count)
+{
+ _dvb_dmx_swfilter(demux, buf, count, 188);
+}
+
EXPORT_SYMBOL(dvb_dmx_swfilter);
void dvb_dmx_swfilter_204(struct dvb_demux *demux, const u8 *buf,
size_t count)
{
- int p = 0, i, j;
- u8 tmppack[188];
-
- spin_lock(&demux- lock);
-
- if (demux- tsbufp) {
- i = demux- tsbufp;
- j = 204 - i;
- if (count < j) {
- memcpy(&demux- tsbuf[i], buf, count);
- demux- tsbufp += count;
- goto bailout;
- }
- memcpy(&demux- tsbuf[i], buf, j);
- if ((demux- tsbuf[0] == 0x47) || (demux- tsbuf[0] == 0xB8)) {
- memcpy(tmppack, demux- tsbuf, 188);
- if (tmppack[0] == 0xB8)
- tmppack[0] = 0x47;
- dvb_dmx_swfilter_packet(demux, tmppack);
- }
- demux- tsbufp = 0;
- p += j;
- }
-
- while (p < count) {
- if ((buf[p] == 0x47) || (buf[p] == 0xB8)) {
- if (count - p = 204) {
- memcpy(tmppack, &buf[p], 188);
- if (tmppack[0] == 0xB8)
- tmppack[0] = 0x47;
- dvb_dmx_swfilter_packet(demux, tmppack);
- p += 204;
- } else {
- i = count - p;
- memcpy(demux- tsbuf, &buf[p], i);
- demux- tsbufp = i;
- goto bailout;
- }
- } else {
- p++;
- }
- }
-
-bailout:
- spin_unlock(&demux- lock);
+ _dvb_dmx_swfilter(demux, buf, count, 204);
}
EXPORT_SYMBOL(dvb_dmx_swfilter_204);
--
To unsubscribe from this list: send the line "unsubscribe linux-media" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at rel="nofollow" vger.kernel.org/majordomo-info.html vger.kernel.org/majordomo-info.html
|