Connect with us

Latest

Manual Memory Management in Go using jemalloc – Dgraph Blog

Published

on

Manual Memory Management in Go using jemalloc - Dgraph Blog

Dgraph Labs has been a user of the Go language since our inception in 2015. Five
years and 200K lines of Go code later, we’re happy to report that we are still
convinced Go was and remains the right choice. Our excitement for Go has gone
beyond building systems, and has led us to even write scripts in Go that would
typically be written in Bash or Python. We find that using Go has helped us
build a codebase that is clean, readable, maintainable and – most importantly –
efficient and concurrent.

However, there’s one area of concern that we have had since the early days:
memory management. We have nothing against the Go garbage collector, but while
it offers a convenience to developers, it has the same issue that other memory
garbage collectors do: it simply cannot compete with the efficiency of manual
memory management.

When you manage memory manually, the memory usage is lower, predictable and
allows bursts of memory allocation to not cause crazy spikes in memory usage.
For Dgraph using Go memory, all of those have been a problem. In fact, Dgraph
running out of memory is a very common complaint we hear from our users.

Languages like Rust have been gaining ground partly because it allows safe
manual memory management. We can completely empathize with that.

In our experience, doing manual memory allocation and chasing potential memory
leaks takes less effort than trying to optimize memory usage in a language with
garbage collection. Manual memory management is well worth the trouble when
building database systems that are capable of virtually unlimited scalability.

Our love of Go and our need to avoid Go GC led us to find novel ways to do
manual memory management in Go. Of course, most Go users will never need to do
manual memory management; and we would recommend against it
unless you need it.
And when you do need it, you’ll know.

In this post, I’ll share what we have learned at Dgraph Labs from our
exploration of manual memory management, and explain how we manually manage
memory in Go.

Memory creation via Cgo

The inspiration came from the Cgo wiki section about Turning C arrays into Go
slices
. We could use malloc to allocate memory in C and use
unsafe to pass it over to Go, without any interference from Go GC.

import "C"
import "unsafe"
...
        var theCArray *C.YourType = C.getTheArray()
        length := C.getTheArrayLength()
        slice := (*[1 << 28]C.YourType)(unsafe.Pointer(theCArray))[:length:length]

However, the above comes with a caveat, as noted in golang.org/cmd/cgo.

Note: the current implementation has a bug. While Go code is permitted to write nil or a C pointer (but not a Go pointer) to C memory, the current implementation may sometimes cause a runtime error if the contents of the C memory appear to be a Go pointer. Therefore, avoid passing uninitialized C memory to Go code if the Go code is going to store pointer values in it. Zero out the memory in C before passing it to Go.

So, instead of using malloc, we use its slightly more expensive sibling,
calloc. calloc works the same way as malloc, except it zeroes out
the memory before returning it to the caller.

We started out by just implementing basic Calloc and Free functions, which
allocate and de-allocate byte slices for Go via Cgo.
To test these functions, we
developed and ran a continuous memory usage test. This test
endlessly repeated an allocate/de-allocate cycle in which it first allocated
various randomly-sized memory chunks until it had allocated 16GB of memory, and
then freed these chunks until just 1GB of memory was left allocated.

The C equivalent of this program behaved as expected. We would see the RSS
memory in our htop increasing to 16GB, then going down to 1GB, increasing back
to 16GB, and so on. However, the Go program using Calloc and Free would
use progressively more memory after each cycle (see chart below).

We attributed this behavior to memory fragmentation due to lack of thread
awareness in the default C.calloc calls. After some help from the Go
#dark-arts Slack channel (particular thanks to Kale Blankenship), we decided
to give jemalloc a try.

jemalloc

jemalloc is a general purpose malloc(3) implementation that emphasizes
fragmentation avoidance and scalable concurrency support. jemalloc first came
into use as the FreeBSD libc allocator in 2005, and since then it has found its
way into numerous applications that rely on its predictable behavior. —
http://jemalloc.net

We switched our APIs over to use jemalloc for calloc and free calls. And it
performed beautifully:
jemalloc supports threads natively with little memory
fragmentation. The allocation-deallocation cycles from our memory usage
monitoring test were circulating between expected limits, ignoring a small
overhead required to run the test.

Just to ensure that we’re using jemalloc and avoid a name clash, we added a
je_ prefix during installation, so our APIs are now calling je_calloc and
je_free, instead of calloc and free.


Go memory allocation via calloc vs jemalloc

In the above chart, allocating Go memory via C.calloc resulted in major memory
fragmentation, causing the program to hog on to 20GBs of memory by the 11th
cycle. Equivalent code with jemalloc had no noticeable fragmentation,
going down close to 1GB on every cycle.

At the end of the program (small dips on far right), after all the
allocated memory was released, C.calloc program resulted in still hogging just
under 20GB of memory, while jemalloc showed 400MB of memory usage.


To install jemalloc, download it from here, then run the following commands:

./configure --with-jemalloc-prefix='je_' --with-malloc-conf="background_thread:true,metadata_thp:auto"
make
sudo make install

The overall Calloc code looks something like this:

	ptr := C.je_calloc(C.size_t(n), 1)
	if ptr == nil {
		// NB: throw is like panic, except it guarantees the process will be
		// terminated. The call below is exactly what the Go runtime invokes when
		// it cannot allocate memory.
		throw("out of memory")
	}
	uptr := unsafe.Pointer(ptr)

	atomic.AddInt64(&numBytes, int64(n))
	// Interpret the C pointer as a pointer to a Go array, then slice.
	return (*[MaxArrayLen]byte)(uptr)[:n:n]

We made this code part of Ristretto‘s z package, so both Dgraph and Badger
can use it. To allow our code to switch to using jemalloc to allocate the byte
slices, we added a build tag jemalloc. To further simplify our deployments, we
made the jemalloc library be statically linked in any resulting Go binary by
setting the right LDFLAGS.

Laying out Go structs on byte slices

Now that we have a way to allocate and free a byte slice, the next step
is to use it to layout a Go struct. We can start with a basic one (full code).

type node struct {
    val  int
    next *node
}

var nodeSz = int(unsafe.Sizeof(node{}))

func newNode(val int) *node {
    b := z.Calloc(nodeSz)
    n := (*node)(unsafe.Pointer(&b[0]))
    n.val = val
    return n
}

func freeNode(n *node) {
    buf := (*[z.MaxArrayLen]byte)(unsafe.Pointer(n))[:nodeSz:nodeSz]
    z.Free(buf)
}

In the code above, we laid out a Go struct on C allocated memory using newNode.
We created a corresponding freeNode function, which can free up the memory once
we were done with the struct. The Go struct has the basic data type int and a
pointer to the next node struct, all of which were set and accessed in the
program.
We allocated 2M node objects and created a linked list out of them to
demonstrate the proper functioning of jemalloc.

With default Go memory, we see 31 MiB of heap allocated for the linked list with
2M objects, but nothing allocated via jemalloc.

$ go run .
Allocated memory: 0 Objects: 2000001
node: 0
...
node: 2000000
After freeing. Allocated memory: 0
HeapAlloc: 31 MiB

Using the jemalloc build tag, we see 30 MiB of memory allocated via jemalloc,
which goes down to zero after freeing the linked list. The Go heap allocation is
only a tiny 399 KiB, which probably comes from the overhead of running the
program.

$ go run -tags=jemalloc .
Allocated memory: 30 MiB Objects: 2000001
node: 0
...
node: 2000000
After freeing. Allocated memory: 0
HeapAlloc: 399 KiB

Amortizing the cost of Calloc with Allocator

The above code works great to avoid allocating memory via Go. But, it comes at a
cost: lower performance.
Running both the instances with time, we see that
without jemalloc, the program ran in 1.15s. With jemalloc, it ran ~5x slower at
5.29s.

$ time go run .
go run .  1.15s user 0.25s system 162% cpu 0.861 total

$ time go run -tags=jemalloc .
go run -tags=jemalloc .  5.29s user 0.36s system 108% cpu 5.200 total

We attribute the slower performance to the fact that Cgo calls were made each
time that memory was allocated, and each Cgo call comes with some overhead. To
deal with this, we wrote an Allocator library in ristretto/z package.
This library allocates bigger chunks of memory in one call, which can then be
used to allocate many small objects, avoiding expensive Cgo calls.

Allocator starts with a buffer and when exhausted, creates a new buffer of
twice the size. It maintains an internal list of all the allocated buffers.
Finally, when the user is done with the data, they can call Release to free up
all these buffers in one go. Note that Allocator does not do any memory movement.
This helps ensure that any struct pointers we have stay valid.

While this might look a bit like the slab-style memory management that tcmalloc
/ jemalloc use, this is a lot simpler. Once allocated, you can not
free up just one struct. You can only free up all of the memory used by
Allocator.

What Allocator does well is to layout millions of structs for cheap and free
them when done, without involving the Go heap.
The same program shown
above, when run with a new allocator build tag, runs even faster than
the Go memory version.

$ time go run -tags="jemalloc,allocator" .
go run -tags="jemalloc,allocator" .  1.09s user 0.29s system 143% cpu 0.956 total

Starting in Go 1.14, the -race flag turns on memory alignment checks for
structs. Allocator has an AllocateAligned method which returns memory
starting with the right pointer alignment to pass those checks. Depending upon
the size of the struct, this could result in some memory waste but
makes CPU instructions more efficient due to correct word boundaries.

We faced another memory management problem: Sometimes memory allocation happens
at a very different place from deallocation. The only communication between
these two places might be the structs allocated with no way to pass down the
actual Allocator object. To deal with this, we assign a unique ID to each
Allocator object, which the objects store in a uint64 reference. Each new
Allocator object is stored on a global map against its reference. Allocator
objects can then be recalled using this reference and released when the data is
no longer required.

Reference Wisely

Do NOT reference Go allocated memory from manually allocated memory.

When allocating a struct manually, as shown above, it is important to ensure
that there’s no reference within the struct to Go-allocated memory. Consider a
slight modification to the struct above:

type node struct {
  val int
  next *node
  buf []byte
}

Let’s use the root := newNode(val) func defined above to allocate a node
manually. If, however, we then set root.next = &node{val: val}, which
allocates all the other nodes in the linked list via Go memory, we are bound to
get the following segmentation fault:

$ go run -race -tags="jemalloc" .
Allocated memory: 16 B Objects: 2000001
unexpected fault address 0x1cccb0
fatal error: fault
[signal SIGSEGV: segmentation violation code=0x1 addr=0x1cccb0 pc=0x55a48b]

The memory allocated by Go gets garbage collected because no valid Go struct is
pointing to it. Only C-allocated memory is referencing it, and the Go heap does
not have any reference to it, resulting in the above fault. So, if you
create a struct and manually allocate memory to it, it’s important to ensure
that all the recursively accessible fields are allocated manually as well.

For example, if the above struct was using a byte slice, we allocate that byte
slice using Allocator as well to avoid mixing Go memory with C memory.

b := allocator.AllocateAligned(nodeSz)
n := (*node)(unsafe.Pointer(&b[0]))
n.val = -1
n.buf = allocator.Allocate(16) // Allocate 16 bytes
rand.Read(n.buf)

Dealing with GBs of allocations

Allocator is great for manually allocating millions of structs. However, we have
use cases where we need to create billions of small objects and sort them. The
way one would do that in Go, even with Allocator, looks something like this:

var nodes []*node
for i := 0; i < 1e9; i++ {
  b := allocator.AllocateAligned(nodeSz)
  n := (*node)(unsafe.Pointer(&b[0]))
  n.val = rand.Int63()
  nodes = append(nodes, n)
}
sort.Slice(nodes, func(i, j int) bool {
  return nodes[i].val < nodes[j].val
})
// nodes are now sorted in increasing order of val.

All these 1B nodes are manually allocated on the Allocator, which gets
expensive. We also need to pay the cost of the slice in Go, which at 8GB of
memory (8 bytes per node pointer, 1B entries) is itself quite expensive.

To deal with these kinds of use cases, we built z.Buffer, which can be memory
mapped on a file to allow Linux to page memory in and out as required by the
system. It implements io.Writer and replaces our reliance on bytes.Buffer.

More importantly, z.Buffer provides a new way to allocate smaller slices of
data. With a call to SliceAllocate(n), z.Buffer would write the length of
the slice being allocated (n) followed by allocating the slice. This allows
z.Buffer to understand slice boundaries and iterate over them correctly with
SliceIterate.

Sorting variable-length data

For sorting, we initially tried to get slice offsets from z.Buffer, access the
slices to compare, but sort only the offsets. Given an offset, z.Buffer can
read the offset, find the length of the slice and return that slice. So this
system allowed us to access the slices in sorted order, without incurring any
memory movements. While novel, that mechanism put a lot of pressure on memory,
because we were still paying the 8GB memory penalty just to bring those offsets
into Go memory.

One crucial limitation we had was that slices were not of the same
size.
Moreover, we could only access these slices in sequential order, not in
reverse or random order, without calculating and storing the offsets in advance.
Most in-place sort algorithms assume that values are of the same size , can be
randomly accessed and can be readily swapped. Go’s sort.Slice works the same
way, and hence wasn’t a good fit for z.Buffer.

With these limitations, we found the merge sort algorithm to be the most suitable
for this job. With merge sort, we can operate on the buffer in sequential
order,
taking only an extra half the memory hit over the size of the buffer.
This not only turned out to be cheaper than bringing offsets into memory, but it
was a lot more predictable in terms of memory usage overhead as well (roughly
half the buffer size)
. Even better, the overhead required to run merge sort is
itself memory-mapped.

Merge sort also had one very positive effect. With offset based sorting, we had
to keep the offsets in memory while iterating over and processing the buffer,
which put even more pressure on memory. With merge sort, the extra memory
needed is released by the time iteration starts,
which means more memory is
available for buffer processing.

z.Buffer also supports allocating memory via Calloc, and automatically
memory mapping it once it exceeds a certain user-specified limit. This makes it
work really well across all sizes of data.

buffer := z.NewBuffer(256<<20) // Start with 256MB via Calloc.
buffer.AutoMmapAfter(1<<30)    // Automatically mmap it after it becomes 1GB.

for i := 0; i < 1e9; i++ {
  b := buffer.SliceAllocate(nodeSz)
  n := (*node)(unsafe.Pointer(&b[0]))
  n.val = rand.Int63()
}

buffer.SortSlice(func(left, right []byte) bool {
  nl := (*node)(unsafe.Pointer(&left[0]))
  nr := (*node)(unsafe.Pointer(&right[0]))
  return nl.val < nr.val
})

// Iterate over nodes in increasing order of val.
buffer.SliceIterate(func(b []byte) error {
  n := (*node)(unsafe.Pointer(&b[0]))
  _ = n.val
  return nil
})

Catching Memory Leaks

All of this discussion would not be complete without touching on memory leaks.
Now that we are using manual memory allocation, there are bound to be memory
leaks where we forgot to deallocate memory. How do we catch those?

One simple thing we did early on was to have an atomic counter track the number
of bytes allocated via these calls, so we can quickly know how much memory we
have manually allocated in the program via z.NumAllocBytes(). If by the
end of our memory test we still had any memory left, this indicated a leak.

When we did find a leak, we initially tried to use the jemalloc memory
profiler. But, we soon realized that it isn’t helpful. It doesn’t see the entire
call stack due to the Cgo boundary. All that the profiler sees are allocations
and de-allocations coming from the same z.Calloc and z.Free calls.

Thanks to the Go runtime, we were able to quickly build a simple system to capture
the callers into z.Calloc and match them against z.Free calls. This
system requires mutex locks, so we chose not to enable it by default. Instead,
we use a leak build flag to turn on leak debug messages for our dev builds.
This automatically detects leaks, and prints out the places where any leaks
occur.

// If leak detection is enabled.
pc, _, l, ok := runtime.Caller(1)
if ok {
  dallocsMu.Lock()
  dallocs[uptr] = &dalloc{
    pc: pc,
    no: l,
    sz: n,
  }
  dallocsMu.Unlock()
}

// Induced leak to demonstrate leak capture. The first number shows
// the size of allocation, followed by the function and the line
// number where the allocation was made.
$ go test -v -tags="jemalloc leak" -run=TestCalloc
...
LEAK: 128 at func: github.com/dgraph-io/ristretto/z.TestCalloc 91

Conclusion

With these techniques, we get the best of both worlds: We can do manual memory
allocation in critical, memory-bound code paths.
At the same time,
we can get the benefits of automatic garbage collection in non-critical code
paths.
Even if you are not comfortable using Cgo or jemalloc, you could apply these
techniques on bigger chunks of Go memory, with similar impact.

All of the libraries mentioned above are available under Apache 2.0 license in
the Ristretto/z package. The memtest and demo code is located in
contrib folder.

Both Badger and Dgraph (particularly
Badger) have already gained immensely from using these libraries. We can now
process terabytes of data with limited memory usage – in line with what you’d
expect from a C++ program.
We are further identifying areas where we put
pressure on Go memory, and relieving it by switching to manual memory
management where that makes sense.

Dgraph v20.11 (T’Challa) release will be the first one to include all of these
memory management features. Our goal is to ensure that Dgraph never needs more
than 32 GB of physical RAM to run any kind of workload. And using z.Calloc,
z.Free, z.Allocator and z.Buffer helps us achieve this goal with Go.

Fashion

The truth about fast fashion: can you tell how ethical your clothing is by its price?

Published

on

What is the true cost of a Zara hoodie? In April 2019, David Hachfeld of the Swiss NGO Public Eye, along with a team of researchers and the Clean Clothes Campaign, attempted to find out. They chose to analyse a black, oversized top from Zara’s flagship Join Life sustainability line, which was printed with lyrics made famous by Aretha Franklin: “R-E-S-P-E-C-T: find out what it means to me”. It was an apt choice, because the idea was to work out whether any respect had been paid to the workers involved in the garment’s production, and how much of the hoodie’s average retail price, €26.66 (£22.70), went into their pockets.

This was no simple assignment. It took several people six months, involved badgering Zara’s parent company, Inditex, over email, slowly getting limited information in return, and interviewing dozens of sources on the ground in Izmir, Turkey, where the garment was made. The researchers analysed financial results and trading data, and consulted with experts in pricing and production. It was, Hachfeld says on the phone, with dry understatement, “quite a huge project”.

Their research suggested that the biggest chunk of the hoodie’s retail price – an estimated €10.26 – went back into Zara, to cover retail space and staff wages. The next biggest slice, after VAT at €4.44, was profit for Inditex/Zara, at €4.20. Their research suggested that the textile factory in Izmir received just €1.53 for cutting the material, sewing, packing and attaching the labels, with €1.10 of that being paid to the garment workers for the 30-minute job of putting the hoodie together. The report concluded that workers could not have received anything like a living wage, which the Clean Clothes Campaign defined, at the time the report was released, as a gross hourly wage of €6.19.

When the research was covered by the media at the time, Zara said the report was “based on erroneous premises and inaccurate reporting”, that the €7.76 sourcing price was wrong and that the workers were “paid more than the amounts mentioned in Public Eye’s report”. But at the time and when I contacted Zara for this article, the company declined to set out in greater detail where the research was inaccurate.

Workers in a small garment factory in Istanbul
Workers in a small garment factory in Istanbul. Photograph: NurPhoto/Getty Images

What is clear is that trying to find out the true production cost of a garment is a tortuous and potentially fruitless process – even when assessing a major high street retailer’s flagship “sustainability” line.

Hachfeld points out that Zara is by no means uniquely opaque. It is doing more than many clothing brands and has long-term commitments in place to work towards living wages. “They are launching initiatives and consultations with trade unions. But the question remains: when will they deliver on it?” he says. Vanishingly few retailers guarantee living wages across their vast, complex supply chains. According to the not-for-profit group Fashion Revolution, only two of the world’s 250 largest fashion brands (OVS and Patagonia) disclose how many of their workers are paid a living wage – despite the kind of resources that make billionaires of founders. Forbes estimates that Zara’s founder, Amancio Ortega, is worth $77bn (£55bn) and that H&M’s founder, Stefan Persson, is worth $21.3bn; the Sunday Times puts the wealth of Boohoo’s co-founder, Mahmud Kamani, at £1.4bn.

Throughout fashion, the numbers just don’t add up. High-street clothing has been getting cheaper and cheaper for decades. A major reason why, according to Gordon Renouf, the CEO of the fashion ethics comparison app Good on You, is that so many western brands have “moved from onshore production 40 years ago to larger offshore production”. Often, the countries they have chosen have “much lower wage costs, weaker labour movements and laxer environmental regulations”. Of course, we know all this, but we have also become accustomed to reaping the benefits. Our perception of what clothing should cost – and how much of it we need – has shifted.

In 1970, for example, the average British household spent 7% of its annual income on clothing. This had fallen to 5.9% by 2020. Even though we are spending less proportionally, we tend to own more clothes. According to the UN, the average consumer buys 60% more pieces of clothing – with half the lifespan – than they did 15 years ago. Meanwhile, fashion is getting cheaper: super-fast brands such as Shein (which sells tie-dye crop tops for £1.49) and Alibaba (vest tops for $2.20), have boomed online, making high-street brands look slow-moving and expensive by comparison.

But the correlation between price and ethics is knotty, to say the least. The conversation about sustainable fashion tends to be dominated by expensive designer brands: at Stella McCartney, for example, a wool-cotton jumper costs £925; at Another Tomorrow, each $520 sustainable viscose carbon-offset scarf neck blouse features a QR code in the label that outlines every stage of its “provenance journey”.

On the high street, many who proudly opt out of shopping at Primark or Boohoo for ethical reasons may be unaware that most reassuringly mid-priced brands don’t guarantee workers living wages or produce clothing without using environmentally harmful materials. A garment’s price is often more about aspiration and customer expectation than the cost of production. Hachfeld points out that the Zara hoodie was priced higher in Switzerland (CHF 45.90; €39.57), where Zara is positioned as a mid-range brand, than in Spain (€25.95), where it is perceived as more mainstream and affordable.

Another Tomorrow scar-neck blouse.
‘Provenance journey’ … Another Tomorrow scarf neck blouse.

Online, debates about the price of clothing can get heated. The sustainable-fashion writer Aja Barber, for example, uses the phrase “exploitation prices” to refer to very cheap clothes, such as the 8p bikini offered by the Boohoo brand Pretty Little Thing last autumn. “Either the company or the garment worker is taking the hit, and most likely it’s not the company, because that wouldn’t be a profitable business model,” she says.

Barber has a personal threshold in mind when she buys an item. “Any time a dress is under £50, you really need to break down the labour on it,” she says. “Think about what you get paid hourly – think, could a person make this dress in three hours?” She doesn’t base this calculation on local wages in the global south, either, which are so much lower “because of years of colonialism and oppression”. She buys new clothes infrequently and tries to avoid polyester, which is made with fossil fuels and generally used in garments to make them cheaper.

Barber gets annoyed by the accusations of snobbery that ripple through social media when anyone criticises super-cheap brands. Largely, she says, these comments come from middle-class people “who want to participate in the system and not feel bad about it”. In her view, fast fashion is propped up not by those with very low disposable incomes, but by middle-class overconsumption.

The only way to tell if a garment has been ethically produced is by combing through the details on the manufacturer’s website (although many brands give little or no information) and checking out its rating on Good on You, which compares fashion brands on the basis of their impact on the planet, people and animals. Even among brands that have launched with sustainability as their USP, greenwashing is rife. Renouf warns against those that talk vaguely about being “natural” and “fair”, or bang on about recycled packaging, without giving details about, say, the materials they use or whether they engage with unions in their factories.

For the fashion retailer Sam Mabley, the idea that fashion can be ethical only if it is expensive is a myth. Mabley runs a sustainable fashion store in Bristol; he thought it was a shame that he was selling so many ethical T-shirts at around the £30 price point. Usually, he says, such T-shirts are created in small batches, by “cool indie brands who do printed designs – a lot of the work is in the design”. He decided to invert that business model, ramping up the scale in order to get bigger discounts from suppliers and creating plain, organic cotton, ethically produced Ts in black and white for £7.99. With just a month of social media promotion, he secured 4,000 orders.

A model wears a Yes Friends T-shirt by Sam Mabley
‘Buying power’ … a Yes Friends T-shirt by Sam Mabley.

He believes it would be fairly easy for fast-fashion brands to use their buying power to “drive change for millions of workers around the world” and guarantee their factories paid living wages, without drastically affecting their margins. He is not alone in this view: Jenny Hulme, the head of buying at the sustainable fashion mainstay People Tree, believes ethical production is necessary and possible in every part of the market. “If you order in big volumes, it does reduce price – if a company really wants to improve, it can,” she says.

The reality of high-street clothes shopping is still very far from this ideal. Apart from a few “sustainable” lines produced by the big fast-fashion brands – which I am loath to recommend, because of so many accusations of greenwashing – it is almost impossible to find new, ethical clothing at rock-bottom prices, because the business models that have enabled clothing to get this cheap rely on inexpensive, environmentally damaging fabrics and very low wages.

That may leave anyone wanting to dress ethically on a high-street purse feeling out of options, although Renouf points out that buying better is possible at every budget. That is why, he says, Good on You aims to “provide ratings for as many brands as possible, rather than simply promoting the most sustainable brands”. You could, for example, move from an ultra-rapid fashion brand to a more engaged high-street fast-fashion brand, which might not cost much more, but still could constitute progress.

Buying fewer, but better-quality, items might save you money overall and is the most consistent advice you will hear from fashion campaigners. “Buy the best quality that you can afford, perhaps in end-of-season sales or by buying a thick jumper in the middle of summer to wear the next winter,” says Hulme.

Stepping out of the trend cycle, and avoiding brands that trade on planned obsolescence, is another avenue to explore. For example, Patrick Grant, a judge on the BBC’s The Great British Sewing Bee, explains that his Community Clothing brand aims to give shoppers more bang for their buck by stocking basics rather than continually designing new collections (it also does without retail space and marketing). Working to slimmer margins means he can invest in good fabric, but keep prices fairly low: his £49 hoodies are made from 470g 100% loopback cotton, a thicker, more durable fabric than you might find for a similar price on the high street.

A blazer from ethical brand Lora Gene
A blazer from the ethical brand Lora Gene. Photograph: Lora Gene

For those who can afford mid-high street prices, researching small, sustainable brands might glean results. A quick look at the Zara website today shows silk dresses selling for as much as £199, with plenty of others at £49.99, while H&M-owned &OtherStories sells blazers for about £120; Barber points out that at these prices, shoppers could switch to ethical brands including Lora Gene, for which she has designed a collection, and Ninety Percent. (There is a dress I like the look of for £64 in the Ninety Percent sale; a mustard Lora Gene blazer is £139.)

If those prices are out of reach, swapping clothes, shopping secondhand, repairing and rethinking what you already have, and occasionally renting for special occasions can all be cheaper – even free – alternatives.

Voting with your wallet will only go so far, however, and won’t be possible for many people who are struggling, as the number of people in poverty in the UK soars to 15 million. Questioning the magical thinking of rock-bottom prices is not about blaming the consumer. Instead, you could write to MPs and CEOs and demand that they do something about living wages and the environmental cost of fashion. The responsibility lies with brands, and with the government, which should be held to account for a broken system.

Continue Reading

Latest

What Is Health at Every Size (HAES)? The Approach Focuses on Health vs. Weight

Published

on

By

What Is Health at Every Size (HAES)? The Approach Focuses on Health vs. Weight
anti diet special report bug

Whenever we go to the doctor’s office — whether it’s for an annual physical or a sore throat— one of the first things we do is step on a scale. For some of us, it’s a fraught moment: Will the number be higher or lower than last time? How will we feel about that? And folks in larger bodies, especially, may wonder: What will my doctor think about that?

In a paper published in 2014, researchers found that 21% of patients with BMIs in the “overweight” and “obese” ranges felt that their doctor “judged them about their weight” — and as a result, they were significantly less likely to trust their doctor or even to return for follow-up care. And research shows that this lack of trust is valid: Doctors are more likely to be biased against patients with high BMIs, and that this impacts the quality of the medical care they receive.

After analyzing audio recordings of 208 patient encounters by 39 primary care physicians, scientists found that doctors established less emotional rapport with their higher weight patients, according to a study published in a 2013 issue of the journal Obesity. Other studies have found that this lack of rapport makes doctors more likely to deem a higher-weight patient as “noncompliant” or “difficult,” often before the exam has even begun. And for women, gender non-conforming folks, people of color and people with low socioeconomic status, a doctor’s weight bias may intersect with other biases and potentially make the situation worse.

Medical weight stigma can have dire consequences. When patients delay healthcare because they’re worried about discrimination, they miss regular screening exams and are more likely to be much sicker by the time doctors do see them, which is one of the reasons why some people assume everyone in a larger body is unhealthy and observe correlations (but not causations) between higher body weight and chronic health conditions that benefit from good preventative healthcare.

At the same time, provider bias can lead doctors to under-treat or misdiagnose their larger patients in all sorts of ways. Patients in larger bodies with eating disorders tend to struggle longer and be sicker when they finally do get treatment, because doctors can ignore their symptoms — or even praise their disordered eating when it results in weight loss. Weight stigma also causes doctors to overlook problems that aren’t about weight. For example, in May 2018, a Canadian woman named Ellen Maud Bennett died only a few days after receiving a terminal cancer diagnosis; in her obituary, her family wrote that Bennett had sought medical care for her symptoms for years, but only ever received weight loss advice.

Because of this mounting evidence about the health consequences of medical anti-fat bias, some providers are starting to shift their medical practices to what’s known as the “Health at Every Size” approach, the purpose of which is to take the focus off a person’s weight, and instead look more holistically at their overall health. Of course, many doctors are still using scales and prescribing weight loss. But the Health at Every Size movement can be a model for health and wellness that you can adopt for yourself, too.


anti diet special report bug

While only a fifth of the 600 respondents in a 2012 survey perceived weight-related judgment from PCPs, they were significantly less likely to report high trust in these doctors.


So, what is Health at Every Size?

Most doctors today approach health through what’s known as the “weight-centric” model, where weight is viewed as one of, if not the, most important marker of health. In the weight-centric model, if the patient is in a larger body, many conditions are treated primarily through the prescription of weight loss. Health at Every Size, commonly known as HAES (pronounced “hays”), is an alternative approach, also sometimes referred to as a “weight-inclusive” model of healthcare.

HAES originated in the fat acceptance movement and was further popularized by Lindo Bacon, Ph.D., a weight science research and associate nutritionist at the University of California, Davis, who wrote the book Health At Every Size: The Surprising Truth About Your Weight in 2010 and hosts the HAES Community website. “Health at Every Size is the new peace movement,” writes Bacon. “It is an inclusive movement, recognizing that our social characteristics such as our size, race, national origin, sexuality, gender, disability status and other attributes, are assets and acknowledges and challenges the structural and systemic forces that impinge on living well. It also supports people of all sizes in adopting healthy behaviors.” (If you’re interested, more information about the history and philosophy of HAES is available from the Association for Size Diversity and Health.)

HAES-informed practitioners do not routinely weigh patients, or use weight to determine how healthy a person is. Instead, they look at other biomarkers, like blood pressure and cholesterol levels, to assess physiological health. And they consider how various social, economic and environmental factors in a person’s life impact their ability to pursue health. Translation: Instead of assuming you’re lazy or uninformed if you aren’t exercising or eating vegetables, a HAES-aligned doctor will ask about your schedule, responsibilities and priorities, to see what kind of barriers you face to adopting a regular workout routine. And they’ll take into consideration whether or not you live near a grocery store, have time to cook, or can otherwise easily access healthier food.

This doesn’t mean a HAES provider won’t ever encourage you to be more active or change your eating habits; it means they’ll only recommend changes that are attainable and realistic for you. And, most crucially, they won’t be telling you to do these things to lose weight. In the HAES model, weight loss is never a goal of treatment because your body is never viewed as a problem to be solved. You have the right to pursue health in the body you have, rather than waiting for that body to change in order to be deemed healthy.

But isn’t it unhealthy to be fat?

Contrary to popular belief, it’s not inherently unhealthy to be fat. Research shows that the relationship between weight and health is much less clear-cut than we’re often told. Weight may be a correlating factor in health conditions like diabetes and heart disease, but scientists haven’t been able to prove that a high body weight causes such diseases. In some cases it may contribute, or it may be simply another symptom of a different root cause. (Consider how smoking can cause both lung cancer and yellow teeth — but nobody assumes that yellow teeth cause lung cancer.)

In fact, weighing more can actually protect you against certain health problems, including osteoporosis and some kinds of cancer. Heart surgery patients with higher BMIs also tend to have better survival rates than their thinner counterparts. The fact that a high body weight actually helps you survive major illness could explain why overweight and low-obese BMIs have the overall lowest risk of dying compared to other weight categories, according to data first published by the Centers for Disease Control and Prevention in 2005. In short, it is absolutely possible to be fat and fit.

Even if you live in a larger body and do have health conditions often assumed to be weight-linked, there is good evidence that you can treat those problems and improve your health without pursuing weight loss. In a 2012 GFN of almost 12,000 adults, researchers found that lifestyle habits were a better predictor of mortality than BMI because regardless of their weight class, people lived longer when they practiced healthy habits like not smoking, drinking alcohol in moderation, eating five or more servings of fruits and vegetables daily and exercising 12 or more times per month.

That’s good news because despite how often doctors prescribe it, we don’t have a safe and durable way for most people to lose significant amounts of weight. That’s because our bodies are programmed to fight weight loss, for our own good. According to an evidence review of common commercial weight loss protocols first published in 2007, and later updated in 2013: People lose some weight in the first nine to 12 months of any diet, but over the next two to five years, they gain back all but an average of 2.1 pounds. And dieting and “weight cycling” in this way can increase your risk for disordered eating and other health problems.


anti diet special report bug

In a University of South Carolina study, all of the men and women followed over the course of 170 months benefited from the adoption of healthy habits, no matter their size.

How do I practice HAES — and how do I get my doctor on board?

Practicing Health at Every Size will look different for everyone, because that’s part of its beauty: You get to decide your own health priorities and can focus on the goals that are accessible and realistic for your life, rather than following a doctor’s “one size fits all” approach to health. But there is one universal tenet: Your weight is no longer part of the conversation. That might mean that you ditch your scale, stop dieting and exercising for weight loss, start to explore intuitive eating and joyful movement — or all of the above.

But while there is growing awareness of HAES in the medical community, it is not the default approach in most healthcare offices. To find doctors or other practitioners in your area who identify as HAES-aligned, you can start by checking the HAES provider directory. But if not, it may be possible to have a productive conversation with your current doctor about why you’d like to take the focus off your weight. One simple way to set this boundary is to decline to be weighed at the start of the visit.

You may worry that the doctor’s office won’t allow you to skip the routine weigh-in, but you have a right to refuse to be weighed, says Dana Sturtevent, R.D., a dietitian and co-founder of Be Nourished, a nonprofit organization in Portland, Oregon, which offers workshops, retreats and e-courses for healthcare providers on how to offer trauma-informed and weight-inclusive care. “This can be a very real and potentially vulnerable step towards self-care,” she says. If your doctor objects, you can ask: “How will this information be used?” There are times when a weight is medically necessary, such as when it’s needed to determine the correct dosing of certain medication. If that’s the case, you can ask to be weighed with your back turned to the scale so you can’t see the number. But if you’re told it’s routine or that they just need to write it down for insurance purposes, you can ask that they write “patient declined” instead.

It can also help to give your doctor a heads up that you would prefer not to discuss weight or weight loss at your appointment. If you feel anxious about bringing this up in the exam room, you can download this letter, created by HAES providers Louise Metz, MD., and Anna Lutz, R.D., to send ahead or give to the nurse who takes your vitals at the start of the appointment. Dr. Metz has also collaborated with health coaches Ragen Chastain and Tiana Dodson to create the HAES Health Sheets Library, which contains downloadable fact sheets on how to treat conditions commonly linked to weight from a HAES perspective.

If your doctor persists in a weight-focused approach to your care, remember that you have the right to switch providers. But more importantly: “Remember that you are not required to be a certain weight in order to be worth of love, respect, belonging or decent medical care,” says Sturtevent. “Your body is your body.”

This content is created and maintained by a third party, and imported onto this page to help users provide their email addresses. You may be able to find more information about this and similar content at piano.io

Continue Reading

Fashion

9 Amazon Fashion Brands You Need to Be Shopping

Published

on

9 Amazon Fashion Brands You Need to Be Shopping

You’re already well-acquainted with Amazon as your shopping preference for everything from household products to books, tech accessories to groceries. But since 2017 one of the world’s largest retail marketplaces has made a pointed effort to expand past their traditional stock. In less than four years, Amazon has introduced dozens of in-house fashion brands, making their mark on the style world in the process. (And with free speedy shipping on most Amazon Prime items, there’s never been an easier way to do a spot of last-minute shopping).

We’ve gathered the nine standout Amazon fashion brands you need to know below. Whether you’re looking to refresh your underwear drawer, update your closet with some trend-focused finds, or simply add a few wardrobe essentials, the mega-retailer is literally your one-stop destination.

Core 10

What it is: High-quality workout-wear with tons of amazing reviews

Shop here

If you’re looking for affordable activewear that performs just as well as brands three times the price, Core 10 is your answer (it comes in extended sizing as well). Sports bras, leggings, shorts, hoodies, and more—it’s got all your workout needs covered.

Highlights include a ’90s-fantastic collaboration with Reebok launched earlier this summer and a “Build your own” legging option. Shoppers can customize their perfect pair with three lengths and three waistband styles, resulting in one shopper saying that they’re the “best leggings [she’s] tried. Hands down.”

Wild Meadow

What it is: Basics with a ’90s feel that all cost less than $30

Shop here

Launched this spring, Wild Meadow brings that easy-breezy youthful ’90s vibe and all styles are offered up to a size XXL. The best part? Not a single item costs more than $30, which means you should stock up—ASAP.

In the market for a tie-dye cami dress? A tie-front cropped tee? Still hunting for that perfect slip dress that will take you from day to night with a simple shoe swap? Wild Meadow has you covered with all that and more.

Amazon Essentials

What it is: Non-basic basics that are budget-friendly

Shop here

The Amazon Essentials brand includes food, household items—and wardrobe basics. Essentials, yes, but they’re anything but boring. Expect to find everything from floral t-shirt dresses to cozy fleeces, yoga leggings to bathing suits.

It’s affordable—prices are pretty much all under $50, with most under $25—and available in plus sizes. An important-to-know factor that makes this label stand out is how many maternity options there are, should you be in the market. In short, you can curate your entire wardrobe virtually no matter your size, budget, or stage of life.

Goodthreads

What it is: Trend-driven closet essentials

Shop here

Goodthreads started as a menswear-only Amazon brand but quickly expanded into the womenswear market. This line has a lot of wardrobe essentials, like button-down shirts, chinos, and sundresses, but they’re a bit more fashion-focused than some of Amazon’s other basics go-tos (like Amazon Essentials).

Here, you’ll find cinched-waist midi dresses, tops with subtly ruffled sleeves, and colorfully striped button-downs. The biggest draw, though, is the denim, which is sold in six different silhouettes, showcasing an impressive number of length and wash options. The size range for Goodthreads is XS-XXL on most pieces.

There is

What it is: Everyday underwear and lingerie, plus great swim options

Shop here

Amazon’s own lingerie brand offers everything from underwire bras to slinky slips and lace-trimmed thongs. If you’re looking for underwear or sleepwear of any kind, this is your brand.

For casual everyday wear, Mae offers cotton briefs and bras, lacy bralettes, and future go-to t-shirt bras to name a few. If you’re looking for more of a special lingerie moment, consider their wide selection of sexy, flirty sets and separates. The brand has expanded into swim, shapewear, and pajamas, too.

Daily Ritual

What it is: Comfortable basics that go up to 7X

Shop here

Daily Ritual is your go-to for comfortable options that look presentable enough for stepping out with friends or running errands. The brand is known for its selection of casual essentials that are anything but basic, and most items are made of a super soft cotton jersey or fleece.

There’s a bit of everything, including puffer jackets for when temps get chilly, but the majority of the pieces focus on classic cotton tees, joggers, and the like. An impressive amount is offered in plus sizes up to 7X, providing real universal appeal. For the shopper who loves to dress simply, stay comfortable, and look put-together, this is the Amazon fashion brand for you.

The Drop

What it is: Limited-edition collections co-created with some of today’s biggest social stars

Shop here

Built on the concept of curated, limited-edition capsule collections that are only promised to be available for a quick 30 hours, The Drop is Amazon’s most coveted line. Each collab is designed and curated by a rotating list of bloggers and influencers uniquely catering to their individual style at affordable prices—it’s either pieces they want for their own wardrobe or have developed a signature look around.

Past influencers to participate include Charlotte Groeneveld of The Fashion Guitar, Leonie Hanne of Ohh Couture, Quigley Goode of Officially Quigley, and more. Depending on the influencer, The Drop could include everything from wrap dresses to faux leather pants; teddy bear shearling coats or shackets. You have 30 hours to order originally, but some styles (like the below) make a reappearance.

Cable Stitch

What it is: Classic knitwear silhouettes, updated

Shop here

The name literally says it all: Cable Stitch is the Amazon brand to go to if you love a good knitwear moment. Cardigans, pullovers, dresses…you name it. The range will appeal to minimalists and maximalists alike, with classic solid colors and brightly colored stripes in the mix.

When Amazon creates an entire line centered around knitwear, you know they’re going to go big or go home. You can shop an array of the more unconventional knits that are trending (like side-slit midis and puff-sleeve pullovers) as well as basics. Most pieces retail between $20 and $60, though some outliers will exist from season to season.

The Fix

What it is: Stand-out shoes and bags that can upgrade everything in your closet

Shop here

Accessory obsessed? You need to know about The Fix. Specializing in the little pieces that make or break a look, this is your shop for all the trendiest footwear and handbags you’ve been coveting since you first saw them explode on the street style scene.

At The Fix, you can shop heels, flats, sandals, and sneakers in a range of head-turning styles. There are certainly no basics here, with every style boasting at least one special detail that makes them stand out from the rest. Whether that’s an ankle strap or chunky heels covered in velvet, special details let you transform your look by swapping in a new accessory.

This content is created and maintained by a third party, and imported onto this page to help users provide their email addresses. You may be able to find more information about this and similar content at piano.io

Continue Reading

Trending