/** Release any free memory back to the system, * but only if you are above a certain fraction of use of the * total available PHYSICAL memory. * Calling this could help the system avoid going into swap. * * NOTE: This only works if you linked against tcmalloc. * NOTE 2: This takes at least 0.1 ms on a Ubuntu 10.10 system, because of * the call to MemoryStats.update(). * * @param threshold :: multiplier (0-1.0) of the amount of physical * memory used that has to be in use before the call to * release memory is actually called. */ void MemoryManagerImpl::releaseFreeMemoryIfAbove(double threshold) { UNUSED_ARG(threshold); #ifdef USE_TCMALLOC Kernel::MemoryStats mem; mem.update(); double fraction_available = static_cast<double>(mem.availMem()) / static_cast<double>(mem.totalMem()); if (fraction_available < (1.0 - threshold)) { // Make TCMALLOC release memory to the system MallocExtension::instance()->ReleaseFreeMemory(); } #endif }
/** Write the group labeled "data" * * @param bank :: name of the bank * @param is_definition * @return error code */ int SaveToSNSHistogramNexus::WriteDataGroup(std::string bank, int is_definition) { int dataType, dataRank, dataDimensions[NX_MAXRANK]; NXname name; void *dataBuffer; if (NXgetinfo(inId, &dataRank, dataDimensions, &dataType) != NX_OK) return NX_ERROR; // Get the rectangular detector IComponent_const_sptr det_comp = inputWorkspace->getInstrument()->getComponentByName(std::string(bank)); RectangularDetector_const_sptr det = boost::dynamic_pointer_cast<const RectangularDetector>(det_comp); if (!det) { g_log.information() << "Detector '" + bank + "' not found, or it is not a rectangular detector!\n"; // Just copy that then. if (NXmalloc(&dataBuffer, dataRank, dataDimensions, dataType) != NX_OK) return NX_ERROR; if (NXgetdata(inId, dataBuffer) != NX_OK) return NX_ERROR; if (NXcompmakedata(outId, name, dataType, dataRank, dataDimensions, NX_COMP_LZW, dataDimensions) != NX_OK) return NX_ERROR; if (NXopendata(outId, name) != NX_OK) return NX_ERROR; if (WriteAttributes(is_definition) != NX_OK) return NX_ERROR; if (NXputdata(outId, dataBuffer) != NX_OK) return NX_ERROR; if (NXfree(&dataBuffer) != NX_OK) return NX_ERROR; if (NXclosedata(outId) != NX_OK) return NX_ERROR; } else { // YES it is a rectangular detector. // --- Memory requirements ---- size_t memory_required = size_t(det->xpixels() * det->ypixels()) * size_t(inputWorkspace->blocksize()) * 2 * sizeof(float); Kernel::MemoryStats mem; mem.update(); size_t memory_available = mem.availMem() * 1024; std::cout << "Memory available: " << memory_available / 1024 << " kb. "; std::cout << "Memory required: " << memory_required / 1024 << " kb. "; // Give a 50% margin of error in allocating the memory memory_available = memory_available / 2; if (memory_available > static_cast<size_t>(5e9)) memory_available = static_cast<size_t>(5e9); if (memory_available < memory_required) { // Compute how large of a slab you can still use. int x_slab; x_slab = static_cast<int>( memory_available / (det->ypixels() * inputWorkspace->blocksize() * 2 * sizeof(float))); if (x_slab <= 0) x_slab = 1; // Look for a slab size that evenly divides the # of pixels. while (x_slab > 1) { if ((det->xpixels() % x_slab) == 0) break; x_slab--; } std::cout << "Saving in slabs of " << x_slab << " X pixels.\n"; if (this->WriteOutDataOrErrors(det, x_slab, "data", "data_errors", false, false, is_definition, bank) != NX_OK) return NX_ERROR; if (this->WriteOutDataOrErrors(det, x_slab, "errors", "", true, false, is_definition, bank) != NX_OK) return NX_ERROR; } else { std::cout << "Saving in one block.\n"; if (this->WriteOutDataOrErrors(det, det->xpixels(), "data", "data_errors", false, true, is_definition, bank) != NX_OK) return NX_ERROR; } } return NX_OK; }