maidan-co/go-rest-expander — pull request #1 by chrisport (2014-09-24 15:01:30+00:00)
Title: Parallelization and limiting expansion

## Parallelization

I parallelized the expansion part by always running the function ```getResourceFrom``` in a goroutine.

### Main idea
I run the most expensive function in a goroutine: getResourceFrom. I changed its usage as in following example

Original:

```
//synchronous call
resource, ok := getResourceFrom(uri.(string), filters, recursive)
//work with the result
if ok {
result[key] = resource
}
```
Parallelized:

```
waitGroup.Add(1)
go func(mIndex int) {
resource, ok := getResourceFrom(uri, filters.Get(parentKey).Children, recursive)
if ok {
result[mIndex] = resource
}
waitGroup.Done()
}(i)
```

The method is called in a own goroutine. The waitGroup is created in the root-method Expand and injected as parameter into walkByExpansion and deeper recursive calls.

### Performance comparison
90 HTTP-calls were made during this request to resolve DBRefs
For testing I used the following call:
http://localhost:8080/all?expand=data(in,posts(author,comments(_id,author)))&filter=data(affection,in(_id,title),posts(author(info(firstname,lastname),_id,avatar),_id,summary,thumbState,upsCount,downsCount,on,comments(_id,author(_id,info(firstname,lastname),avatar),content)),staffPicked,_id,cover,tags,in,on,type,title)&trim=250&p=1&s=34&

I measured 3 calls and took the average time:

**Without parallelization**

1. 2.842s
2. 2.413s
3. 2.028s

Average: 2.427666667s

**With parallelized**

1. 1.605s
2. 1.529s
3. 1.697s

Average: 1.610333333s

**Improvement**

33.67%

## Expand only filtered fields
In case someone calls expand *, but filters, I replaced expand with filter in order to reduce the amount of expansions to a minimum. Else other fields are expanded, but thrown away when the result is filtered.
```?expand=*&filter=oneField```