Tag Archives: design

Bitmap, cache and fresco Android image loading Library

Fresco Android image loading Library — Facebook

Fresco is a powerful image loading component.

A module called image pipeline is designed in fresco. It is responsible for loading images from network, local file system and local resources. In order to save space and CPU time to the greatest extent, it contains 3-level cache design (2-level memory, 1-level file).

There is a module called drawings in fresco, which can easily display the loading graph. When the picture is no longer displayed on the screen, it can release the memory and space in time.

Fresco supports Android 2.3 (API level 9) and above.

memory management

The extracted image, that is, the bitmap in Android, takes up a lot of memory. Large memory consumption is bound to lead to more frequent GC. Below 5.0, GC will cause interface stuck.

In systems below 5.0, fresco places the image in a special memory area. Of course, when the picture is not displayed, the occupied memory will be released automatically. This will make the app smoother and reduce the oom caused by image memory occupation.

Fresco does just as well on low-end machines, so you don’t have to think twice about how much image memory you’re using.

Progressive image presentation #
the progressive JPEG image format has been popular for several years. The progressive image format first presents the outline of the image, and then presents the gradually clear image as the image download continues, which is of great benefit to mobile devices, especially the slow network, and can bring better user experience.

Android’s own image library does not support this format, but fresco does. When using it, as usual, you just need to provide a URI of the image, and fresco will handle the rest.

It is very important to display pictures quickly and efficiently on Android devices. In the past few years, we have encountered many problems in how to efficiently store images. The picture is too big, but the memory of the phone is very small. The R, G, B and alpha channels of each pixel take up a total of 4 bytes of space. If the screen of the mobile phone is 480 * 800, a picture of the screen size will occupy 1.5m of memory. The memory of mobile phones is usually very small, especially Android devices need to allocate memory for various applications. On some devices, only 16MB of memory is allocated to the Facebook app. A picture will occupy one tenth of its memory.

What happens when your app runs out of memory?Of course it will collapse! We developed a library to solve this problem. We call it fresco. It can manage the images and memory used, and the app will no longer crash.

Memory area

In order to understand what Facebook does, we need to understand the difference between the heap memory that Android can use. The Java heap memory size of every app in Android is strictly limited. Each object is instantiated in heap memory using java new, which is a relatively safe area in memory. Memory has garbage collection mechanism, so when the app is not using memory, the system will automatically recycle this memory.

Unfortunately, the process of garbage collection in memory is the problem. When the memory is garbage collected, the memory is not only garbage collected, but also the Android application is completely terminated. This is also one of the most common reasons for users to get stuck or temporarily feign death when using the app. This will make the users who are using the app very depressed, and then they may anxiously slide the screen or click the button, but the only response of the app is to ask the user to wait patiently before the app returns to normal

In contrast, the native heap is allocated by the new of the C + + program. There is more available memory in the native heap. App is only limited by the physical available memory of the device, and there is no garbage collection mechanism or other things. But the C + + programmer must recycle every memory allocated by himself, otherwise it will cause memory leakage and eventually lead to program crash.

Android has another memory area called ashmem. It operates more like a native heap, but with additional system calls. When Android operates the ashmem heap, it will extract the memory area in the heap that contains data from the ashmem heap instead of releasing it, which is a weak memory release mode; the extracted memory will be released only when the system really needs more memory (the system memory is not enough). When Android puts the extracted memory back to the ashmem heap, as long as the extracted memory space is not released, the previous data will be restored to the corresponding location.

Three level cache
1. Bitmap cache
bitmap cache stores bitmap objects, which can be immediately used for display or post-processing

In systems below 5.0, the bitmap cache is located in ashmem, so that the creation and release of bitmap objects will not cause GC, and fewer GC will make your app run more smoothly.

In contrast, memory management has been greatly improved, so the bitmap cache is directly located on the heap of Java.

When the application is running in the background, the memory will be cleared.

    1. memory cache of undeciphered pictures
    this cache stores pictures in the original compressed format. The pictures retrieved from the cache need to be decoded before being used.

If there is any resizing, rotation, or webp transcoding work to be done, it will be done before decoding.

When the app is in the background, the cache will also be cleared.

    1. file cache
    is similar to UN decoded memory cache. File cache stores UN decoded images in original compressed format, which also needs decoding before use.

Unlike the memory cache, when the app is in the background, the content will not be cleared. Not even if it’s turned off. Users can clear the cache at any time in the system’s settings menu.

Bitmap and cache

Bitmap is special in Android, because Android limits the memory of single APP, for example, allocate 16MB, and the domestic custom system will be larger than 16. There are two common caching strategies in Android, LruCache and DiskLruCache. The former is used as memory cache method and the latter is used as storage cache method.

android.support Brief reading of lrucache source code in. V4 package

package android.util;  

import java.util.LinkedHashMap;  
import java.util.Map;  

/** 
 * A cache that holds strong references to a limited number of values. Each time 
 * a value is accessed, it is moved to the head of a queue. When a value is 
 * added to a full cache, the value at the end of that queue is evicted and may 
 * become eligible for garbage collection. 
 * Cache keeps a strong reference to limit the number of contents. Whenever an Item is accessed, this Item is moved to the head of the queue.
 * When a new item is added when the cache is full, the item at the end of the queue is reclaimed.
 * <p>If your cached values hold resources that need to be explicitly released, 
 * override {@link #entryRemoved}. 
 * If a value in your cache needs to be explicitly freed, override entryRemoved()
 * <p>If a cache miss should be computed on demand for the corresponding keys, 
 * override {@link #create}. This simplifies the calling code, allowing it to 
 * assume a value will always be returned, even when there's a cache miss. 
 * If the item corresponding to the key is lost, rewrite create(). This simplifies the calling code and always returns it even if it is lost.
 * <p>By default, the cache size is measured in the number of entries. Override 
 * {@link #sizeOf} to size the cache in different units. For example, this cache 
 * is limited to 4MiB of bitmaps: The default cache size is the number of items measured, rewrite sizeof to calculate the size of different items
 * size.
 * <pre>   {@code 
 *   int cacheSize = 4 * 1024 * 1024; // 4MiB 
 *   LruCache<String, Bitmap> bitmapCache = new LruCache<String, Bitmap>(cacheSize) { 
 *       protected int sizeOf(String key, Bitmap value) { 
 *           return value.getByteCount(); 
 *       } 
 *   }}</pre> 
 * 
 * <p>This class is thread-safe. Perform multiple cache operations atomically by 
 * synchronizing on the cache: <pre>   {@code 
 *   synchronized (cache) { 
 *     if (cache.get(key) == null) { 
 *         cache.put(key, value); 
 *     } 
 *   }}</pre> 
 * 
 * <p>This class does not allow null to be used as a key or value. A return 
 * value of null from {@link #get}, {@link #put} or {@link #remove} is 
 * unambiguous: the key was not in the cache.
 * Do not allow key or value to be null
 * When get(), put(), remove() return null, the corresponding item of the key is not in the cache
 */  
public class LruCache<K, V> {  
    private final LinkedHashMap<K, V> map;  

    /** Size of this cache in units. Not necessarily the number of elements. */  
    private int size; //The size of the already stored
    private int maxSize; //the maximum storage space specified

    private int putCount; //the number of times to put
    private int createCount; //the number of times to create
    private int evictionCount; //the number of times to recycle
    private int hitCount; //number of hits
    private int missCount; //number of misses

    /** 
     * @param maxSize for caches that do not override {@link #sizeOf}, this is 
     *     the maximum number of entries in the cache. For all other caches, 
     *     this is the maximum sum of the sizes of the entries in this cache. 
     */  
    public LruCache(int maxSize) {  
        if (maxSize <= 0) {  
            throw new IllegalArgumentException("maxSize <= 0");  
        }  
        this.maxSize = maxSize;  
        this.map = new LinkedHashMap<K, V>(0, 0.75f, true);  
    }  

    /** 
     * Returns the value for {@code key} if it exists in the cache or can be 
     * created by {@code #create}. If a value was returned, it is moved to the 
     * head of the queue. This returns null if a value is not cached and cannot 
     * be created. The corresponding item is returned by key, or created. the corresponding item is moved to the head of the queue.
     * If the value of the item is not cached or cannot be created, null is returned.
     */  
    public final V get(K key) {  
        if (key == null) {  
            throw new NullPointerException("key == null");  
        }  

        V mapValue;  
        synchronized (this) {  
            mapValue = map.get(key);  
            if (mapValue != null) {  
                hitCount++;  
                return mapValue;  
            }  
            missCount++;  
        }  

        /* 
         * Attempt to create a value. This may take a long time, and the map 
         * may be different when create() returns. If a conflicting value was 
         * added to the map while create() was working, we leave that value in 
         * the map and release the created value. 
         * If it's missing, try to create an item
         */  

        V createdValue = create(key);  
        if (createdValue == null) {  
            return null;  
        }  

        synchronized (this) {  
            createCount++;
            mapValue = map.put(key, createdValue);  

            if (mapValue != null) {  
                // There was a conflict so undo that last put  
                //If oldValue exists before it, then undo put() 
                map.put(key, mapValue);  
            } else {  
                size += safeSizeOf(key, createdValue);  
            }  
        }  

        if (mapValue != null) {  
            entryRemoved(false, key, createdValue, mapValue);  
            return mapValue;  
        } else {  
            trimToSize(maxSize);  
            return createdValue;  
        }  
    }  

    /** 
     * Caches {@code value} for {@code key}. The value is moved to the head of 
     * the queue. 
     * 
     * @return the previous value mapped by {@code key}. 
     */  
    public final V put(K key, V value) {  
        if (key == null || value == null) {  
            throw new NullPointerException("key == null || value == null");  
        }  

        V previous;  
        synchronized (this) {  
            putCount++;  
            size += safeSizeOf(key, value);  
            previous = map.put(key, value);  
            if (previous != null) {  //The previous value returned
                size -= safeSizeOf(key, previous);  
            }  
        }  

        if (previous != null) {  
            entryRemoved(false, key, previous, value);  
        }  

        trimToSize(maxSize);  
        return previous;  
    }  

    /** 
     * @param maxSize the maximum size of the cache before returning. May be -1 
     *     to evict even 0-sized elements. 
     *  Empty cache space
     */  
    private void trimToSize(int maxSize) {  
        while (true) {  
            K key;  
            V value;  
            synchronized (this) {  
                if (size < 0 || (map.isEmpty() && size != 0)) {  
                    throw new IllegalStateException(getClass().getName()  
                            + ".sizeOf() is reporting inconsistent results!");  
                }  

                if (size <= maxSize) {  
                    break;  
                }  

                Map.Entry<K, V> toEvict = map.eldest();  
                if (toEvict == null) {  
                    break;  
                }  

                key = toEvict.getKey();  
                value = toEvict.getValue();  
                map.remove(key);  
                size -= safeSizeOf(key, value);  
                evictionCount++;  
            }  

            entryRemoved(true, key, value, null);  
        }  
    }  

    /** 
     * Removes the entry for {@code key} if it exists. 
     * Delete the corresponding cache item of the key and return the corresponding value
     * @return the previous value mapped by {@code key}. 
     */  
    public final V remove(K key) {  
        if (key == null) {  
            throw new NullPointerException("key == null");  
        }  

        V previous;  
        synchronized (this) {  
            previous = map.remove(key);  
            if (previous != null) {  
                size -= safeSizeOf(key, previous);  
            }  
        }  

        if (previous != null) {  
            entryRemoved(false, key, previous, null);  
        }  

        return previous;  
    }  

    /** 
     * Called for entries that have been evicted or removed. This method is 
     * invoked when a value is evicted to make space, removed by a call to 
     * {@link #remove}, or replaced by a call to {@link #put}. The default 
     * implementation does nothing. 
     * Called when the item is recycled or deleted. Change method is called by remove when value is reclaimed to free up storage space.
     * or put called when the value of the item is replaced, the default implementation does nothing.
     * <p>The method is called without synchronization: other threads may 
     * access the cache while this method is executing. 
     * 
     * @param evicted true if the entry is being removed to make space, false 
     *     if the removal was caused by a {@link #put} or {@link #remove}. 
     * true---is deleted for free space; false - put or remove causes
     * @param newValue the new value for {@code key}, if it exists. If non-null, 
     *     this removal was caused by a {@link #put}. Otherwise it was caused by 
     *     an eviction or a {@link #remove}. 
     */  
    protected void entryRemoved(boolean evicted, K key, V oldValue, V newValue) {}  

    /** 
     * Called after a cache miss to compute a value for the corresponding key. 
     * Returns the computed value or null if no value can be computed. The 
     * default implementation returns null. 
     * Called when an Item is missing and returns the corresponding calculated value or null
     * <p>The method is called without synchronization: other threads may 
     * access the cache while this method is executing. 
     * 
     * <p>If a value for {@code key} exists in the cache when this method 
     * returns, the created value will be released with {@link #entryRemoved} 
     * and discarded. This can occur when multiple threads request the same key 
     * at the same time (causing multiple values to be created), or when one 
     * thread calls {@link #put} while another is creating a value for the same 
     * key. 
     */  
    protected V create(K key) {  
        return null;  
    }  

    private int safeSizeOf(K key, V value) {  
        int result = sizeOf(key, value);  
        if (result < 0) {  
            throw new IllegalStateException("Negative size: " + key + "=" + value);  
        }  
        return result;  
    }  

    /** 
     * Returns the size of the entry for {@code key} and {@code value} in 
     * user-defined units.  The default implementation returns 1 so that size 
     * is the number of entries and max size is the maximum number of entries. 
     * Return the size of the user-defined item, the default return 1 represents the number of items, the maximum size is the maximum item value
     * <p>An entry's size must not change while it is in the cache. 
     */  
    protected int sizeOf(K key, V value) {  
        return 1;  
    }  

    /** 
     * Clear the cache, calling {@link #entryRemoved} on each removed entry. 
     * 清空cacke
     */  
    public final void evictAll() {  
        trimToSize(-1); // -1 will evict 0-sized elements  
    }  

    /** 
     * For caches that do not override {@link #sizeOf}, this returns the number 
     * of entries in the cache. For all other caches, this returns the sum of 
     * the sizes of the entries in this cache. 
     */  
    public synchronized final int size() {  
        return size;  
    }  

    /** 
     * For caches that do not override {@link #sizeOf}, this returns the maximum 
     * number of entries in the cache. For all other caches, this returns the 
     * maximum sum of the sizes of the entries in this cache. 
     */  
    public synchronized final int maxSize() {  
        return maxSize;  
    }  

    /** 
     * Returns the number of times {@link #get} returned a value that was 
     * already present in the cache. 
     */  
    public synchronized final int hitCount() {  
        return hitCount;  
    }  

    /** 
     * Returns the number of times {@link #get} returned null or required a new 
     * value to be created. 
     */  
    public synchronized final int missCount() {  
        return missCount;  
    }  

    /** 
     * Returns the number of times {@link #create(Object)} returned a value. 
     */  
    public synchronized final int createCount() {  
        return createCount;  
    }  

    /** 
     * Returns the number of times {@link #put} was called. 
     */  
    public synchronized final int putCount() {  
        return putCount;  
    }  

    /** 
     * Returns the number of values that have been evicted. 
     * Return the number of recycled
     */  
    public synchronized final int evictionCount() {  
        return evictionCount;  
    }  

    /** 
     * Returns a copy of the current contents of the cache, ordered from least 
     * recently accessed to most recently accessed. Returns a copy of the current cache, from least recently accessed to most accessed
     */  
    public synchronized final Map<K, V> snapshot() {  
        return new LinkedHashMap<K, V>(map);  
    }  

    @Override public synchronized final String toString() {  
        int accesses = hitCount + missCount;  
        int hitPercent = accesses != 0 ?(100 * hitCount/accesses) : 0;  
        return String.format("LruCache[maxSize=%d,hits=%d,misses=%d,hitRate=%d%%]",  
                maxSize, hitCount, missCount, hitPercent);  
    }  
}

Practice based on how to tango with Django 1.7 (1)

The point of the book is to develop an application called Rango. To develop this application, it will cover most of the core content of making web applications.
2.4Rango: Initial Design and Planning
2.4.1 Design overview
Your client needs to set up a website called Rango, which allows users to browse their own customized web pages. In Spanish language, rango used to mean “sort through quality” or “place in the hierarchy of society” (see https://www.vocabulary.com/dictionary/es/rango).

On the home page of the site, visitors can see:

The 5 Most viewed pages the 5 highest quality directories How visitors can browse or find a directory

When a user views a directory page, it will display:

Directory name, number of visits, number of likes; A page close to the directory (showing the page title and its URL); Some search functions (via Bing’s search API) are used to find other pages that can be linked to this directory

A particular directory, the name of the directory the client wants, the number of times each directory page has been visited and how many users have clicked the ‘like’ button to be recorded. Each directory can be accessed via a readable URL – e.g. /rango/books-about-django/. Only registered users can search and add pages to the catalog. In the meantime, visitors can sign up for an account.

At first glance, the app looks strange. In fact, it’s just a list of directories, and they can link to the page, right?However, there is still a lot of complexity to deal with. First, let’s try to draw a picture of what we want to develop.
2.5 practice
Before going on, consider the instructions below and try to draw a design.
A framework URL binding of the N-tier or system architecture diagram home page and catalog page is the entity-relationship diagram that we are going to implement the data model
2.6 N- layer structure
Rango is a variant of the 3-tier structure in which most Web applications are structured, and requires interaction with an external service.
The UML diagram is drawn using Processon

If we were to create Web applications using Django, we would need the following techniques for each layer.
Client is a browser (i.e. Chrome, Firefox, Safari, etc.) that will return HTML/CSS page; Middleware is a Django application that will form the end of developing Django built into a Web service; database will be SQLite3 database engine based on Python; search API will be Bing search API
Although we had to deal with all the pieces above, most of the focus of the book was on developing middleware.
2.7 wire frame
Wireframes are a great way to design a website’s interface. They save a lot of time and are different from tool-dependent hand drawing. For Rango, we would like its home page to look like the figure below.

The directory page is shown in the figure below:

2.8 Page and URL mappings
By the rule description, we have confirmed that we will present two pages to the user at different times. To get to different pages we need to map the URL, which is the text that the user enters in the browser to get to the page.Rango’s URL map is shown below.
/rango/about/ will point to the About page view./ Rango /category/ will point to each category page view, which might be:

The game; Python trick code or compiler

/rango/etc/, which sets aside etc for future functional implementation
When we create an application, we might need to create some other URL mappings. But those are the ones that we need to build in the first place. Also consider that if the provided directory name does not exist, we need to convert the directory name to a valid URL string.
As we dig deeper into the book, we’ll get a handle on creating web pages with the Django framework and using the model-View-Template design pattern. Now that we have a general idea of the URL mapping and web page interface, we also need to define the data model to provide the data for our application.
2.9 Entity-relationship diagram
Given the rules, we know that there are at least two entities: a directory and a page. One directory can hold many pages at the same time. We can describe our data model through the ER diagram below.

Note that a page can be in one or more directories. So we need to have a many-to-many relationship. To make things less complicated, let’s make the simple assumption that a directory can contain multiple pages, but a page can only belong to one directory. This does not prevent a page from appearing in two different directories – in a less-than-ideal situation, the page might enter twice.
Writing technical notes is a great hobby, especially when you know it will happen again! By writing them down, you can communicate with your development team to ensure that the same problems can be solved quickly.
Str for string or char,Int for integer,URL for URL, FK for Foreign Key.

We also have a user table – not shown here, but described later. In the following sections we will see how to instantiate these data models in Django and learn how to use Django’s ORM to connect to a database.
2.10 summarize
These designs and instructions will be helpful in building our Web applications. The same techniques and procedures we will use apply to most data-driven websites. Familiarity with these specifications and designs is of great benefit to us.
If you already have Python2.7 and Django1.7 installed, and you know how to set up your path from the command line, you can skip the Django basics chapter. Otherwise, let’s look at chapter three.
2.10.1 Work with the Django official tutorial
We recommend that the Django official tutorial be used as an exercise for each chapter of the book. You can find the correspondence between the chapters in the two books in the table below. The official teaching exercises will help you get a deep understanding of the Django framework and improve your skills.
Tango woth Django Django Tutorial
Chapter 3 Part 1 – Models
Chapter 5 Part 2 – The Admin Interface
Chapter 6 Part 3 – URLs and Views
Chapter 7 Part 4 – Templates
Chapter 18 Part 5 – Testing
Chapter 11 Part 6 – CSS

modelsim actually error loading design?

After a semester of EDA courses, I finally unloaded the ModelSim five times.

I believe that many students have encountered such problems when using ModelSim. Even though every design file has been compiled, the following sentence still appears:
Error loading design.
And then… There’s no then, there’s no hint.

At this point, you may need to do the following:
1. Check whether the file is not included and not added to the project.
2. Check that the port declaration of the design file is consistent with the port when instantiated.
3. Check that the module name of the design file is the same as the module name when instantiated.
4. Check if the port that has not been modified in the top-level file is wire (it has been poked for two weeks).
Ask your teacher or boss for help.

Virgin paste, please forgive me.
Uncle Huang in 2018.6.19 17:06