The document discusses efficient processing of complex data through BFS graph traversal. It describes constructing a graph from a data file by adding nodes and edges. It then performs BFS traversal on the graph, maintaining a queue of nodes to visit and propagating information to discover paths between nodes.
Farewell to Disks: Efficient Processing of Obstinate Data
1. Αποχαιρετισμός στους Δίσκους:
Αποδοτική Επεξεργασία
Περίπλοκων Δεδομένων
Διομήδης Σπινέλλης
Καθηγητής
Τμήμα Διοικητικής Επιστήμης και Τεχνολογίας
Οικονομικό Πανεπιστήμιο Αθηνών
http://www.dmst.aueb.gr/dds
1
1
19. Time (Log scale)
Function call System call Local IPC Remote IPC
1.3ns 1.9μs 4.3μs 1.2ms
select Locations.cc1, Divisions.name,
avg(CO2), count(*), Locations.lat,
Locations.long, POPDENSITY.DENSITY from
Papers
inner join Locations on
Papers.confLocId = Locations.id
inner join Divisions on
Locations.cc1 = Divisions.country
inner join POPDENSITY on
Divisions.name = upper(POPDENSITY.name)
where Divisions.code = '00' and CO2 notnull
group by Locations.cc1
having count(*) > 20
order by avg(CO2) desc;
19
20. /* Get the data */
if (mcSet.dataLen) {
data = xmalloc(mcSet.dataLen);
if (lseek(fd, mcSet.data.off, SEEK_SET) == -1)
CORRUPT();
if (read(fd, data, mcSet.dataLen) != mcSet.dataLen)
CORRUPT();
if (lseek(fd, mcSet.u.firstMsg, SEEK_SET) == -1)
CORRUPT();
for (i = 0; i < mcSet.numMsgs; ++i) {
if (read(fd, &mcMsg, sizeof(mcMsg)) != sizeof(mcMsg))
CORRUPT();
if (mcMsg.invalid) {
--i;
continue;
}
msg = xmalloc(sizeof(msgT));
memset(msg, '0', sizeof(*msg));
/* […] */
msg->msgId = mcMsg.msgId;
msg->str = xstrdup((char *) (data + mcMsg.msg.off));
}
free(data);
}
2
20
21. MMAP(2) FreeBSD System Calls
Manual MMAP(2)
NAME
mmap -- allocate memory, or map files or
devices into memory
SYNOPSIS
#include <sys/mman.h>
void *
mmap(void *addr, size_t len, int prot, int
flags, int fd, off_t offset);
DESCRIPTION
The mmap() system call causes the pages
starting at addr and continuing for at most len
bytes to be mapped from the object described by
fd, starting at byte offset offset.
21
28. 01110010011 0111101101101011 0000101101110011 00101 // romane
01110010011 0111101101101011 0000101101110011 1010101110011 // romanus
01110010011 0111101101101011 10101011011000111010101110011 // romulus
01110010011 10101011000100110 0101011 0111001110011 // rubens
01110010011 10101011000100110 0101011 10010 // ruber
01110010011 10101011000100110 100101100011011 0111101101110 // rubicon
01110010011 10101011000100110 100101100011011 1010101101110011001000111
010101110011 // rubicundus
Δομή Δομή δίσκου Ιστοσελίδα
μνήμης με νέους
δεσμούς
Κατασκευή Κατασκευή
δένδρου δομής wikipedialize
ριζών δίσκου
Κατάλογος Αρχική
άρθρων ιστοσελίδα
for (;;) {
i = bitpos;
// Loop until the end of the current node or the end of the word
while (i < p->end && i < len * 8) {
// Covering whole byte?
if (i % 8 == 0 && i + 8 <= p->end && (i + 8) / 8 <= len &&
data[i / 8] == p->data[i / 8]) {
i += 8;
continue;
}
// Split point
if (getbit(data, i) != getbit(p->data, i)) {
// Node with the new data
struct pnode *n = new_node(data + i / 8, i % 8, (len - i / 8) * 8,
NULL, NULL, true);
// Tail of the current node
struct pnode *t = new_node(p->data + i / 8, i % 8, p->end - (i & ~7),
p->zero, p->one, p->is_terminal);
// Head of current node
if (getbit(data, i))
*p2 = new_node(p->data, bitpos, i, t, n, false);
else
*p2 = new_node(p->data, bitpos, i, n, t, false);
free(p);
return;
}
i++;
} // while
28
29. // Write the given node to the specified file, returning its file offset.
// On return the file's offset is set to the first free byte.
static long
write_node(struct pnode *p, FILE *f)
{
long my_offset = ftell(f);
size_t ret;
if (p->one) {
struct pnode_disk_one pdo;
size_t dlen = datalen(p->end);
long len = sizeof(pdo) + dlen;
fseek(f, len, SEEK_CUR);
pdo.h.type = dt_one;
pdo.h.is_terminal = p->is_terminal;
pdo.h.has_zero = (p->zero != NULL);
pdo.h.has_one = true;
pdo.h.begin = p->begin;
pdo.h.end = p->end;
if (p->zero)
write_node(p->zero, f);
pdo.one = write_node(p->one, f);
long saved_offset = ftell(f);
fseek(f, my_offset, SEEK_SET);
fwrite(&pdo, 1, sizeof(pdo), f);
fwrite(p->data, 1, dlen, f);
fseek(f, saved_offset, SEEK_SET);
return my_offset;
} else {
$ zcat enwiki-latest-all-titles-in-ns0.gz | wc -c
106,237,053
$ wc -c enwiki.pt
144,657,286 enwiki.pt
29
31. $ wc crimeandpunishment.txt
0 203,273 1,462,661 crimeandpunishment.txt
$ time ./wpltest en en_US.UTF-8 ISO-8859-1
data/enwiki.pt <crimeandpunishment.txt >/dev/null
$ time ./wpltest en en_US.UTF-8 ISO-8859-1
data/enwiki.pt <crimeandpunishment.txt >/dev/null
Checked 406,225 prefixes
real 0m5.859s # Cold cache
real 0m1.876s # Warm cache
user 0m1.780s
sys 0m0.090s
31
32. // Prevent memory alignment problems
memcpy(&end, &(p.h->end), sizeof(end));
/*
while (i < end && i < len * 8) {
if (i % 8 == 0 && i + 8 <= end && data[i / 8] == pdata[i / 8]) {
*/
* to understand this
* You are not expected
i += 8;
prefix += 8;
continue;
}
// Split point
if (getbit(data, i) != getbit(pdata, i))
return best / 8;
i++;
prefix++;
}
if (i == end && p.h->is_terminal)
best = prefix;
if (i == len * 8)
return best / 8;
// Move to next node
bitpos = end % 8;
int covered = end / 8;
if (getbit(data, end)) {
if (!p.h->has_one)
return best / 8;
switch (p.h->type) {
case dt_both:
p.h = (struct pnode_disk_head *)(base + p.b->one);
break;
case dt_one:
p.h = (struct pnode_disk_head *)(base + p.o->one);
break;
case dt_short:
default:
assert(0);
}
} else {
if (!p.h->has_zero)
return best / 8;
switch (p.h->type) {
case dt_both:
p.h = (struct pnode_disk_head *)(base + p.b->zero);
break;
case dt_one:
// Advance to the end of this node
p.h = (struct pnode_disk_head *)((char *)p.h + sizeof(struct pnode_disk_one) + datalen(end));
break;
case dt_short:
// Advance to the end of this node
p.h = (struct pnode_disk_head *)((char *)p.h + sizeof(struct pnode_disk_short) + datalen(end));
break;
default:
assert(0);
}
}
32